User Guide

Building Graphs from Rasters

SpatialGraphs.jl offers several functions for constructing graphs from raster data, which are detailed below. Once you have converted your data to an AbstractSpatialGraph, you can analyze the graph using funtions from Graphs.jl. Following you analysis, you can then use the spatial information stored in the AbstractSpatialGraph to map values (such as betweenness or cost distance, for example) back to the appropriate points in space. See the Examples section for a detailed demonstration of how this can be done.

Simple Graphs

SpatialGraphs.rastergraphFunction
rastergraph(
    raster::Raster;
    directed::Bool = true,
    condition::Function = is_data,
    cardinal_neighbors_only::Bool = false
)

Construct a RasterGraph or RasterDiGraph (if directed = true) from a raster dataset.

Parameters

raster: A Rasters.Raster on which to base the graph. Any pixel in raster with a value not equal to raster.missingval will be assigned a vertex in the graph (corresponding to its centroid). The values in the raster can also be used to determine which vertices to connect. See condition below for more information.

Arguments

directed: A Bool determining whether the graph should be directed.

condition: A function that compares the values in raster for two neighbors to determine if those neighbors should be connected. The function must compare two values and return either true or false. Useful functions to use here include <, <=, ==, etc. The first argument to condition corresponds to the source vertex, and the second argument corresponds to the destination vertex. So, if you only want to connect sources to destinations that have a lower value in raster (e.g. in the case of developing a hydrologic flow graph based on elevation), then you would use > for condition. Defaults to is_data, which results in neighbors being connected as long as they are not NoData (raster.missingval). Note that if using an inequality function (or any function where the result depends on argument position), directed should be set to true. For undirected graphs, you can use either is_data or ==, or any other custom function where argument position doesn't matter, e.g. a function that determines whether the values in raster are within a certain distance of each other.

cardinal_neighbors_only: A Bool stating whether only cardinal neighbors should be connected. By default, both cardinal and diagonal neighbors are connected. Note that this particular function does NOT account for the increased distance between diagonal neighbors (as compared to the distance between cardinal neighbors), since for a SimpleGraph or SimpleDiGraph, all weights are effectively set to 1.

source
SpatialGraphs.make_simple_raster_graphFunction
make_simple_raster_graph(
    raster::Raster,
    vertex_raster::Raster;
    directed::Bool = false,
    condition::Function = is_data,
    cardinal_neighbors_only::Bool = false
)

Construct a SimpleGraph or SimpleDiGraph (if directed = true) based on two rasters (raster and vertex_raster). This function is useful if you already have a custom vertex raster and don't want SpatialGraphs.jl to make one for you. The vertex raster denotes the spatial locations of each vertex in the graph, and raster is used to construct the graph and determine which vertices to connect.

Parameters

raster: A Rasters.Raster on which to base the graph. Any pixel in raster with a value not equal to raster.missingval will be assigned a vertex in the graph (corresponding to its centroid). The values in the raster can also be used to determine which vertices to connect. See condition below for more information.

vertex_raster: A Rasters.Raster with integer values ranging from 1:n, where n is the number of unique vertices in the graph.

Arguments

directed: A Bool determining whether the graph should be directed.

condition: A function that compares the values in raster for two neighbors to determine if those neighbors should be connected. The function must compare two values and return either true or false. Useful functions to use here include <, <=, ==, etc. The first argument to condition corresponds to the source vertex, and the second argument corresponds to the destination vertex. So, if you only want to connect sources to destinations with a lower value in raster (e.g. in the case of developing a hydrologic flow graph based on elevation), then you would use > for condition. Defaults to is_data, which results in neighbors being connected as long as they are not NoData in raster (raster.missingval). Note that if using an inequality function (or any function where the result depends on argument position), the graph must be directed. For undirected graphs, you can use either is_data or ==, or any other custom function where argument position doesn't matter, e.g. a function that determines whether the values in raster are within a certain distance of each other.

cardinal_neighbors_only: A Bool stating whether only cardinal neighbors should be connected. By default, both cardinal and diagonal neighbors are connected. Note that this particular function does NOT account for the increased distance between diagonal neighbors (as compared to the distance between cardinal neighbors), since for a SimpleGraph or SimpleDiGraph, all weights are effectively set to 1.

source

Weighted Graphs

SpatialGraphs.weightedrastergraphFunction
weightedrastergraph(
    weight_raster::Raster;
    directed::Bool = false,
    condition_raster::Raster = weight_raster,
    condition::Function = is_data,
    cardinal_neighbors_only::Bool = false,
    connect_using_avg_weights::Bool = true
)

Construct a WeightedRasterGraph or WeightedRasterDiGraph (if directed = true) from a raster dataset. The weight raster denotes the edge weight correponding to each vertex. Since edges are between rather than on vertices, edge weights are calculated as the average of the weights for each vertex.

Parameters

weight_raster: A Rasters.Raster containing values that, where applicable based on other arguments, determine which pixels to connect and the edge weights between pixels. Any pixel in weight_raster with a value not equal to weight_raster.missingval will be assigned a vertex in the graph (corresponding to its centroid).

Arguments

directed: A Bool determining whether the graph should be directed.

condition_raster: A raster with values that can be used to determine whether two neighboring pixels should be connected. For example, an elevation raster can be used to create a hydologic flow graph. Defaults to the weight_raster.

condition: A function that compares the values in condition_raster for two neighbors to determine if those neighbors should be connected. The function must compare two values and return either true or false. Useful functions to use here include <, <=, ==, etc. The first argument to condition corresponds to the source vertex, and the second argument corresponds to the destination vertex. So, if you only want to connect sources to destinations that have a lower value in condition_raster (e.g. in the case of developing a hydrologic flow graph based on elevation), then you would use > for condition. Defaults to is_data, which results in neighbors being connected as long as they are not NoData in condition_raster (condition_raster.missingval). Note that if using an inequality function (or any function where the result depends on argument position), directed should be set to true. For undirected graphs, you can use either is_data or ==, or any other custom function where argument position doesn't matter, e.g. a function that determines whether the values in condition_raster are within a certain distance of each other.

cardinal_neighbors_only: A Bool stating whether only cardinal neighbors should be connected. By default, both cardinal and diagonal neighbors are connected. Note that when determining weights between diagonal neighbors, the increased distance between them (as compared to the distance between cardinal neighbors) is accounted for.

connect_using_avg_weights: Bool. This is intended to offer methods that complement those used in Circuitscape.jl and Omniscape.jl. In this context, weights (the values in weight_raster) are in units of electrical resistance. If false, the weight between two nodes with resistances R1 and R2 is calculated by converting resistance to conductances, taking the average, then taking the inverse of the result to convert back to resistance: 1 / ((1/R1 + 1/R2) / 2). connect_using_avg_weights = false corresponds to the default settings in Circuitscape. Defaults to true, in which case the simple average (adjusted for distance in the case of diagonal neighbors) of the weights in weight_raster is used.

source
SpatialGraphs.make_weighted_raster_graphFunction
make_weighted_raster_graph(
    weight_raster::Raster,
    vertex_raster::Raster;
    directed::Bool = false,
    condition_raster::Raster = weight_raster,
    condition::Function = is_data,
    cardinal_neighbors_only::Bool = false,
    connect_using_avg_weights::Bool = true,
    combine::Function = min
)

Construct a SimpleWeightedGraph or SimpleWeightedDiGraph (if directed = true) based on vertex and weight rasters. This function is useful if you already have a custom vertex raster and don't want SpatialGraphs.jl to make one for you. The vertex raster denotes the spatial locations of each vertex in the graph, and the weight raster denotes the edge weight correponding to each vertex. Since edges are between rather than on vertices, edge weights are calculated as the average of the weights for each vertex being connected.

Parameters

weight_raster: A Rasters.Raster containing values that, where applicable based on other arguments, determine which pixels to connect and the edge weights between pixels. Any pixel in weight_raster with a value not equal to weight_raster.missingval will be assigned a vertex in the graph (corresponding to its centroid).

vertex_raster: A Rasters.Raster with integer values ranging from 1:n, where n is the number of unique vertices in the graph.

Arguments

directed: A Bool determining whether the graph should be directed.

condition_raster: A raster with values that can be used to determine whether two neighboring pixels should be connected. For example, an elevation raster can be used to create a hydologic flow graph. Defaults to the weight_raster.

condition: A function that compares the values in condition_raster for two neighbors to determine if those neighbors should be connected. The function must compare two values and return either true or false. Useful functions to use here include <, <=, ==, etc. The first argument to condition corresponds to the source vertex, and the second argument corresponds to the destination vertex. So, if you only want to connect sources to destinations that have a lower value in condition_raster (e.g. in the case of developing a hydrologic flow graph based on elevation), then you would use > for condition. Defaults to is_data, which results in neighbors being connected as long as they are not NoData in condition_raster (condition_raster.missingval). Note that if using an inequality function (or any function where the result depends on argument position), directed should be set to true. For undirected graphs, you can use either is_data or ==, or any other custom function where argument position doesn't matter, e.g. a function that determines whether the values in condition_raster are within a certain distance of each other.

cardinal_neighbors_only: A Bool stating whether only cardinal neighbors should be connected. By default, both cardinal and diagonal neighbors are connected. Note that when determining weights between diagonal neighbors, the increased distance between them (as compared to the distance between cardinal neighbors) is accounted for.

connect_using_avg_weights: Bool. This is intended to offer methods that complement those used in Circuitscape.jl and Omniscape.jl. In this context, weights (the values in weight_raster) are in units of electrical resistance. If false, the weight between two nodes with resistances R1 and R2 is calculated by converting resistance to conductances, taking the average, then taking the inverse of the result to convert back to resistance: 1 / ((1/R1 + 1/R2) / 2). connect_using_avg_weights = false correspondes to the default settings in Circuitscape. Defaults to true, in which case the simple average (adjusted for distance in the case of diagonal neighbors) of the weights in weight_raster is used.

combine: In the case that there are multiple edges defined for a single pair of vertices, how should the weight be chosen? Defaults to min. See the docs for SparseArrays.sparse() for more information.

source

Making vertex rasters

In SpatialGraphs.jl, vertex rasters serve as the spatial reference for the vertices in a graph. SpatialGraphs.jl provides functions to generate these rasters. Often, it is done internally and the end user doesn't need to use these functions, but there are some cases where it will be necessary. For example, it is often the case that a user may want a single graph vertex to occupy multiple pixels in space (e.g. when modeling habitat connectivity between two protected areas). SpatialGraphs.jl enables this by offering a method for the make_vertex_raster function (below) that accepts a raster representing these patches as an argument.

SpatialGraphs.make_vertex_rasterFunction
make_vertex_raster(A::Raster)

Constuct a vertex raster (a raster where the value of each pixel corresponds to its ID in a graph, and 0s correspond to NoData). Returns a Raster.

Parameters

A: The Raster from which a graph will be built, which is used as the reference for building the vertex raster. Pixels with NoData (A.missingval) are skipped (no vertex is assigned). Pixels with NoData will get a value of 0 in the vertex raster.

source
make_vertex_raster(A::Raster, patches::Raster)

Constuct a vertex raster (a raster where the value of each pixel corresponds to its ID in a graph, and 0s correspond to NoData). Returns a Raster.

Parameters

A: The Raster from which a graph will be built, which is used as the reference for building the vertex raster. Pixels with NoData (A.missingval) are skipped (no vertex is assigned). Pixels with NoData will get a value of 0 in the vertex raster.

patches: A Raster defining patches that may consist of multiple pixels but should be considered a single vertex in the graph. patches must have the same dimensions a A. Each patch should have its own unique value, starting with 1, and ending with n, where n is the total number of patches (e.g. if you have 3 patches, pixels in the first patch should have a value of 1, the second patch a value of 2, and the third patch a value of 3). Non-patch pixels can either be labeled with 0 of the raster's missingval.

source