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.rastergraph
— Functionrastergraph(
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.
SpatialGraphs.make_simple_raster_graph
— Functionmake_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.
Weighted Graphs
SpatialGraphs.weightedrastergraph
— Functionweightedrastergraph(
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.
SpatialGraphs.make_weighted_raster_graph
— Functionmake_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.
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_raster
— Functionmake_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.
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
.