Recently, graph-theory has been characterised as an efficient and useful tool for conservation planning (e.g. Bunn et al. 2000, Calabrese & Fagan 2004, Minor et al. 2008, Zetterberg et. al. 2010). As a part of the r.connectivity.* tool-chain, r.connectivity.distance is intended to make graph-theory more easily available to conservation planning.

r.connectivity.distance is the first tool of the r.connectivity.*-toolchain (followed by and r.connectivity.corridor).

r.connectivity.distance loops through all polygons in the input vector map and calculates the cost-distance to all the other polygons within a user-defined defined Euclidean distance threshold. It produces three csv-files containing an edge-list (connections between patches) and a vertex-list (patches) in two parts.

The edge-list csv-file structure (edges.csv) looks like this:
The vertex-list consists of two parts:
- one part containing the coordinates of the centroids of the input polygons (only for visualisation purposes (not for analysis) ("vertices_part_1.csv") and
- one part containing a population proxy (values of an attribute column from the input patch vector map (both specified by the user)), representing a proxy for the amount of organisms potentially dispersing from a patch (e.g. habitat area) ("vertices_part_2.csv").

The structure of the vertices_part_1.csv looks like this:

The structure of the vertices_part_2.csv looks like this:

The map output of r.connectivity.distance is a (cost) distance raster map for every input polygon which later on are used in r.connectivity.corridors (together with output from for corridor identification. All non map output is stored in a folder, which will be used throughout the entire r.connectivity toolchain. Output-files are: vertices_part_1.csv, vertices_part_2.csv, edges.csv and a log-file (r_connectivity.log). The log-file is used to store and document settings of the tools and to pass arguments to the following tools of the toolchain.

Distance is measured as border to border distance. The user can define the number of cells (n) along the border to be used for distance measuring. The distance from a (start) polygon to another (end) is measured as the n-th closest cell on the border of the other (end) polygon. An increased number of border cells used for distance measuring affects (increases) also the width of possible corridors computed with r.connectivity.corridor.
On user request (p-flag) the shortest paths between the possible combination of patches can be extracted (using r.drain), along with start and stop points.


The following example is based on the North Carolina dataset!

Please be aware that all input parameter of the following example are purely hypothetical (though they intend to imitate a real life situation) and chosen only for the matter of the exercise. Parameters have to be adjusted in other cases according to ecological knowledge in order to give meaningful results!

Let us assume we want to analyse the habitat connectivity for a hypothetical species of the Hardwood Swamps in North Carolina. This species lives only in the larger core area of the swamps (> 1ha) while the borders are no suitable habitats.
It is not the most mobile of species and can cover (under optimal conditions) maximal 1.5 km.

Prepare input data

Befor we can run the connectivity analysis with the r.connectivity.*-tools we need to prepare the the example input data. Because we want to use cost distance as a distance measure we have to provide a cost raster map in addition to the required vector map of (habitat) patches:

Create input patch vector map
###Set region
g.region -p rast=landuse96_28m@PERMANENT align=landuse96_28m@PERMANENT

###Patch input vector map
##Extract habitat patches
#Condition 1: Category 11 = Bottomland Hardwoods/Hardwood Swamps
#Condition 2: no border-cells are suitable  
r.mapcalc "patches=if(landuse96_28m[0,1]==11&&landuse96_28m[0,-1]==11&&landuse96_28m[1,1]==11&&landuse96_28m[1,0]==11&&landuse96_28m[1,-1]==11&&landuse96_28m[-1,1]==11&&landuse96_28m[-1,0]==11&&landuse96_28m[-1,-1]==11&&landuse96_28m==11,1,null())"

#Vectorize patches input=patches output=patches feature=area

#Add a column for the population proxy (in this case area in hectares)
v.db.addcol map=patches layer=1 'columns=area_ha double precision' 

#Upload area to attribute table (later used as population proxy) map=patches type=point,line,boundary,centroid layer=1 qlayer=1 option=area units=hectares columns=area_ha

#Extract core habitat areas with more than 1 ha
v.extract input=patches output=patches_1ha type=area layer=1 where="area_ha>1"
Create a cost raster (se also: r.cost)
For the cost raster, we assume that areas which are developed with high intensity are absolute barriers for our species (not crossable at all). Other developed and managed areas can be crossed, but only at high costs (they are avoided where possible). Other Hardwood landcover types offer best opportnity for the dispersal of our species (they are prefered), while the costs for crossing the other landcover types is somewhere inbetween.
Hint: One might also add infrastructure like e.g. roads
#Reclassify land use map
#Windows users may have to use the GUI version of r.reclass and paste the rules there...
echo '0 = 56 #not classified (2*resolution (28m))
1 = NULL #High Intensity Developed (absolut barrier)
2 = 140 #Low Intensity Developed (5*resolution (28m))
3 = 112 #Cultivated (4*resolution (28m))
4 = 70 #Managed Herbaceous Cover (2,5*resolution (28m))
6 = 28 #Riverine/Estuarine Herbaceous (1*resolution (28m))
7 = 42 #Evergreen Shrubland (1,5*resolution (28m))
8 = 42 #Deciduous Shrubland (1,5*resolution (28m))
9 = 42 #Mixed Shrubland (1,5*resolution (28m))
10 = 28 #Mixed Hardwoods (1*resolution (28m))
11 = 28 #Bottomland Hardwoods/Hardwood Swamps (1*resolution (28m))
15 = 56 #Southern Yellow Pine (2*resolution (28m))
18 = 28 #Mixed Hardwoods/Conifers (1*resolution (28m))
20 = 42 #Water Bodies (1,5*resolution (28m))
21 = 84 #Unconsolidated Sediment (3*resolution (28m))' | r.reclass input=landuse96_28m@PERMANENT output=costs --overwrite 

Create the network (r.connectivity.distance)

In the first step the network dataset is created, and the cost distance between all possible pairs of vertices (patches) is calculated.
Our species is known to be uable to cover more than 1.5 km distance. In order to identify potential for improving the connectectivity of the landscape for our speies we set the cutoff distance (maximum search distance for connections) to three times dispersal potential of our species (4500). In lack of real population data we use the area (ha) as a proxy. The distance between two patches is measured as the maximum distance along the closest 500m of boundary of a patch (ca. 18 border cells with 28m resolution). All non map output is stored in a folder named hws_connectivity in the current working directory.
r.connectivity.distance --verbose patches=patches_1ha costs=costs pop_proxy=area_ha prefix=hws_connectivity folder=./hws_connectivity cutoff=4500 border_dist=18

Analyse the network (

In the next step network analysis is performed. We define the connectivity cutoff (maximum cost distance where connectivity is assumed) to be 1500.0 cost distance units, which represents the maximum known dispersal ability of our species. The dispersal kernel is adjusted to characteristics of this species by setting the exponent to -3, which gives a steeper decrease in successful dispersal with increasing cost distance. Only very few dispersal units of our species are expected to cross more than ca. 900 cost distance units successfully (se: ./hws_connectivity/kernel.eps after running the command or run it with the x-flag (-x) for only displaying the kernel). Connectivity metrics reslults are stored in te attribute table of the vector maps on vertex (patches, map name: "prefix" _ vertex_measures) and edge level (connections, map name: "prefix" _ edge_measures). An overview over connectivity metrics on the graph level (the entire network) is stored in "folder" (./hws_connectivity). We requested also an R-plot of the dispersal kernel and an R-plot givig an overview over network characteristics to be stored in the same folder.

Users with a multi-processor computer (e.g. dual-core) may speed up processing by setting cores > 1 in -y -i folder=./hws_connectivity connectivity_cutoff=1500.0 lnbh_cutoff=2.0 cl_thres=10 exponent=-3 kernel_plot=./hws_connectivity/kernel.eps overview_plot=./hws_connectivity/overview.eps cores=1

Calculate corridors (r.connectivity.corridors)

In this example two alternative (or to some extent complementary) sets of corridors are calculated:

Corridor set 1:
For the first set, corridors are only computed for the minimum spanning tree (in literture sometimes called the backbone of an ecological network). This is specified in the "where"-parameter. Edge betweenness values are used as weights, which represent the centrality of a connection (edge) in a network (and is therewith a measure of importance). The output is a set of corridor raster maps (named: "prefix" _corridor_ "edge_id" _ "weight") and a summary over all computed corridors (named: "prefix" _corridor_ "edge_id" _ "weight" _sum_ "suffix").
r.connectivity.corridors --verbose folder=./hws_connectivity suffix=mst weights=cf_eb_ud where="cf_mst_ud > 1" cores=1
Corridor set 2:
For the second set, corridors are computed for all edges in the graph (network). This takes a little more time. Corridors are then weighted by the modeled, undirected (= in oth directions) flow of propagules ("cf_u").
r.connectivity.corridors --verbose folder=./hws_connectivity suffix=alle weights=cf_u cores=1
Users with a multi-processor computer (e.g. dual-core) may speed up corridor processing by setting cores > 1 r.connectivity.corridors.
An other means for speeding up processing would be to use integer weights (e.g. by converting edge betweenness to integer afte multiplying with 10 to the power of the relevant number of digits). Then r.reclass is used in the script instead of r.recode.

When all analysis is finnished some cleanup may be appropriate, in order to save disk space:
#Add the f-lag (-f) to the following two commands if you are sure you want to delete all intermediate maps from r.connectivity.*.
g.mremove rast=hws_connectivity_corridor_*
g.mremove rast=hws_connectivity_patch_*


Framstad, E., Blumentrath, S., Erikstad, L. & Bakkestuen, V. 2012 (in Norwegian): Naturfaglig evaluering av norske verneområder. Verneområdenes funksjon som økologisk nettverk og toleranse for klimaendringer. NINA Rapport 888: 126 pp. Norsk institutt for naturforskning (NINA), Trondheim.

SEE ALSO, r.connectivity.corridors


Stefan Blumentrath, Norwegian Institute for Nature Research (NINA)

Last changed: $Date$