Skip to contents

Manually editing graphs in geoGraph

This vignette will cover the main functions for manually editing gGraph objects. It also briefly touches on the way geoGraph keeps track of the plotting area, and how to navigate within it as some of the interactive functions rely on using the locator.

Editing gGraphs

Editing graphs is an essential task in geoGraph. While available gGraph objects provide a basis to work with (see ?worldgraph.10k), one may want to adapt a graph to a specific case. For instance, connectivity should be defined according to biological knowledge of the organism under study. gGraph can be modified in different ways: by changing the connectivity, the costs of edges, or the attribute values. We already saw in the vignette ‘get started’ how to manually add a connection between two nodes, and we will see here how to change the global connectivity and edge costs.

Visually inspecting a gGraph object

When customizing a gGraph object, it is often useful to be able to peer at specific regions, and more generally to navigate inside the graphical representation of the data. For this, we can use the interactive functions geo.zoomin, geo.zoomout, geo.slide, geo.back, geo.bookmark, and geo.goto. The zoom and slide functions require to left-click on the graphics to zoom in, zoom out, or slide to adjacent areas; in all cases, a right click ends the function. Also note that geo.zoomin can accept an argument specifying a rectangular region, which will be adapted by the function to fit best a square area with similar position and center, and zoom to this area (see ?geo.zoomin). geo.bookmark and geo.goto respectively set and go to a bookmark, i.e. a tagged area. This is most useful when one has to switch between distant areas repeatedly.

Here are some examples based on the plotting of worldgraph.10k: Zooming in:

plot(worldgraph.10k)
geo.zoomin()
## Spherical geometry (s2) switched off

## Spherical geometry (s2) switched on
## Spherical geometry (s2) switched off

## Spherical geometry (s2) switched on

Zooming out:

## Spherical geometry (s2) switched off

## Spherical geometry (s2) switched on

Sliding to the east:

## Spherical geometry (s2) switched off

## Spherical geometry (s2) switched on

One important thing which makes plotting gGraph objects different from most other plotting in R is that geoGraph keeps the changes made to the plotting area in memory. This allows to undo one or several moves using geo.back. Moreover, even if the graphical device is killed, plotting again a gGraph will use the old parameters by default. To disable this behavior, set the argument reset=TRUE when calling upon plot. Technically, this ‘plotting memory’ is implemented by storing plotting information in an environment defined as the hidden environment geoGraph:::.geoGraphEnv:

ls(env = geoGraph:::.geoGraphEnv)
## [1] "bookmarks"       "last.plot"       "last.plot.param" "last.points"    
## [5] "psize"           "sticky.points"   "usr"             "zoom.log"

You can inspect individual variables within this environment:

get("last.plot.param", envir = geoGraph:::.geoGraphEnv)
## $psize
## [1] 0.5
## 
## $pch
## [1] 19

However, it is recommended not to modify these objects directly, unless you really know what you are doing. In any case, plotting a gGraph object with argument reset=TRUE will remove previous plotting history and undo possible wrong manipulations.

Changing the global connectivity of a gGraph

There are two main ways of changing the connectivity of a gGraph, which match two different objectives. The first approach is to perform global and systematic changes of the connectivity of the graph. Typically, one will want to remove all connections over a given type of landscape, which is impossible to cross by the organism under study. Let’s assume we are interested in saltwater fishes. To model fish dispersal, we have to define a graph which connects only nodes overlaying the sea. We load the gGraph object rawgraph.10k, and zoom in to a smaller area (Madagascar) to illustrate changes in connectivity:

geo.zoomin(c(35, 54, -26, -10))
## Spherical geometry (s2) switched off
## Spherical geometry (s2) switched on
plotEdges(rawgraph.10k)

We shall set a bookmark for this area, in case we would want to get back to this place later on:

geo.bookmark("madagascar")
## 
## Bookmark ' madagascar  'saved.

What we now want to do is remove all but sea-sea connections. To do so, the easiest approach is to i) define costs for the edges based on habitat, with land being given large costs and ii) remove all edges with large costs.

Costs of a given node attribute (here, habitat) can be retrieved using getCosts(x, res.type = ‘rules’) and modified using setCosts with the cost.rules argument.

getCosts(rawgraph.10k, res.type = "rules")
##            habitat cost
## 1              sea  100
## 2             land    1
## 3         mountain   10
## 4       landbridge    5
## 5 oceanic crossing   20
## 6  deselected land  100
cost.rules <- getCosts(rawgraph.10k, res.type = "rules")
cost.rules$cost[cost.rules$habitat == "sea"] <- 1
cost.rules$cost[cost.rules$habitat != "sea"] <- 100
newGraph <- setCosts(rawgraph.10k, attr.name = "habitat", cost.rules = cost.rules)
getCosts(newGraph, res.type = "rules")
##            habitat cost
## 1              sea    1
## 2             land  100
## 3         mountain  100
## 4       landbridge  100
## 5 oceanic crossing  100
## 6  deselected land  100

We have just changed the costs associated to habitat type, but this change is not yet effective on edges between nodes. We use setCosts to set the cost of an edge to the average of the costs of its nodes:

newGraph <- setCosts(newGraph, attr.name = "habitat")
plot(newGraph, edge = TRUE)
## Spherical geometry (s2) switched off

## Spherical geometry (s2) switched on

On this new graph, we represent the edges with a width inversely proportional to the associated cost; that is, bold lines for easy traveling and light edges/dotted lines for more costly movement. This is not enough yet, since traveling on land is still possible. However, we can tell geoGraph to remove all edges associated to too strong a cost, as defined by a given threshold (using dropDeadEdges). Here, only sea-sea connections shall be retained, that is, edges with cost 1.

newGraph <- dropDeadEdges(newGraph, thres = 1.1)
plot(newGraph, edge = TRUE)
## Spherical geometry (s2) switched off

## Spherical geometry (s2) switched on

Here we are: newGraph only contains connections in the sea. Note that, although we restrained the plotting area to Madagascar, this change is effective everywhere. For instance, traveling to the north-west Australian coasts:

geo.zoomin(c(110, 130, -27, -12))
## Spherical geometry (s2) switched off

## Spherical geometry (s2) switched on
geo.bookmark("australia")
## 
## Bookmark ' australia  'saved.

Changing local properties of a gGraph

A second approach to changing a gGraph is to refine the graph by hand, adding or removing locally some connections, or altering the attributes of some nodes. This can be necessary to connect components such as islands to the main landmasses, or to correct erroneous data. As seen in the vignette ‘get started’, adding and removing edges from the grid of a gGraph can be achieved by geo.add.edges and geo.remove.edges, respectively. These functions are interactive, and require the user to select individual nodes or a rectangular area in which edges are added or removed. See ?geo.add.edges for more information on these functions. For instance, we can remove a few odd connections in the previous graph, near the Australian coasts (note that we have to save the changes using <-):

geo.goto("australia")
newGraph <- geo.remove.edges(newGraph)
img
img

When adding connections within an area or in an entire graph, node addition is based on another gGraph, i.e. only connections existing in another gGraph serving as reference can be added to the current gGraph. For graphs based on 10k or 40k grids, the raw graphs provided in geoGraph should be used, (rawgraph.10k, rawgraph.40k), since they are fully connected.

In addition to changing grid connectivity, we may also want to modify the attributes of specific nodes. This is again done interactively, using the function geo.change.attr. For instance, here, we define a new value shallowwater (plotted in light blue) for the attribute habitat, selecting affected nodes using the ‘area’ mode first, and refining the changes using the ‘point’ mode:

plot(newGraph, edge = TRUE)
newGraph <- geo.change.attr(newGraph,
  mode = "area", attr.name = "habitat",
  attr.value = "shallowwater", newCol = "deepskyblue"
)
newGraph <- geo.change.attr(newGraph,
  attr.name = "habitat",
  attr.value = "shallowwater", newCol = "deepskyblue"
)
getColors(newGraph, res.type = "rules")
##            habitat       color
## 1              sea        blue
## 2             land       green
## 3         mountain       brown
## 4       landbridge light green
## 5 oceanic crossing  light blue
## 6  deselected land   lightgray
## 7     shallowwater deepskyblue
plot(newGraph, edge = TRUE)
## Spherical geometry (s2) switched off

## Spherical geometry (s2) switched on

Again, note that the changes made to the graph have to be saved in an object (using <-) to be effective.