Distance-Based Kernels
A straightforward approach to determine the dispersal mode across a complete spatial graph involves correlating the geographic distance between two locations with the likelihood of dispersal between them. The objective of this section is to highlight this model choice by parametrizing a simple Dispersal Location Kernel (in the sense of Nathan et al. 2012). Additionally, we will calculate essential metrics, such as the distance between two coordinates, the dispersal probability between them, and the average dispersal distance anticipated under this distribution.
Model's Basics
The dispersal location kernel represents the statistical pattern of dispersal distances within a population. In this context, it essentially serves as the probability density function (pdf) that outlines the distribution of locations after dispersal in relation to the original location. The expressions have been adjusted to incorporate a scale parameter, \(a\), which is consistent with a distance unit, and a shape parameter, \(b\), that dictates the curvature of the distribution curve, emphasizing the influence of long-distance events.
For a source \((x_0,y_0)\), the dispersal location kernel denoted as \(k_L(r)\) provides the density of the probability of the dispersal end point in the 2D space. In this case, \(k_L(r)dA\) is the probability of a dispersal end point to be within a small 2D area \(dA\) around the location \((x,y)\). Since a probability is unitless and \(dA\) is an area, \(k_L(r)\) is expressed in per unit area in a 2D space.
Quetzal incorporates various kernel types available in the quetzal::demography::dispersal_kernel
namespace, and streamlines compile-time dimensional analysis and units conversion using the mp-units
library.
Input
1#include "quetzal/quetzal.hpp"
3#include <mp-units/ostream.h>
10 using namespace mp_units::si::unit_symbols;
15 constexpr auto source = lonlat(2.25, 48.9176);
16 constexpr auto target = lonlat(2.25, 48.95);
17 constexpr auto distance = source.great_circle_distance_to(target);
20 constexpr auto param = gaussian<>::param_type{.a = 1000. * m};
23 auto p = gaussian<>::pdf(distance, param);
24 auto d = gaussian<>::mean_dispersal_distance(param);
26 std::cout <<
"Dispersal from " << source <<
" to " << target <<
" :\n"
27 <<
"distance is " << distance <<
"\n"
28 <<
"probability is " << p <<
"\n"
29 <<
"mean dispersal distance is " << d << std::endl;
Simulation of coalescence-based models of molecular evolution.
Definition coalescence.hpp:21
Gaussian dispersal location kernel (thin-tailed)
Definition dispersal_kernel.hpp:35
Geographic coordinates.
Definition coordinates.hpp:218
Output
1Dispersal from (Lat: 48.9176, Lon: 2.25) to (Lat: 48.95, Lon: 2.25) :
3probability is 7.34343e-13 1/m²
4mean dispersal distance is 886.227 m
Kernels from Spatial Graphs
Users can create a spatial graph from landscape data, customizing assumptions about connectivity and topology. By defining a dispersal kernel and calculating dispersal probabilities for each edge based on distance metrics, users can uncover insights into potential dispersal patterns within the spatial graph. This approach offers a powerful means for exploring and understanding spatial dynamics and connectivity, facilitating deeper analysis of ecological or geographic phenomena.
Here we show how to simply print out the probabilities computed at each edge of the spatial graph.
Input
1#include "quetzal/quetzal.hpp"
8using namespace mp_units::si::unit_symbols;
12 auto file1 = std::filesystem::current_path() /
"data/bio1.tif";
13 auto file2 = std::filesystem::current_path() /
"data/bio12.tif";
16 std::vector<int> times(10);
17 std::iota(times.begin(), times.end(), 2001);
21 auto land = landscape_type::from_file({{
"bio1", file1}, {
"bio12", file2}}, times);
32 auto sphere_distance = [&](
auto point1,
auto point2)
34 return land.to_latlon(point1).great_circle_distance_to(land.to_latlon(point2));
41 auto probabilities = graph.edges()
42 | std::views::transform( [&](
auto const& e){
return sphere_distance( graph.source( e ), graph.target( e ) );} )
43 | std::views::transform( [&](
auto distance){
return kernel::pdf( distance, { .a=200.*km , .b=5.5 } ) ;} );
46 for (
auto const& i : probabilities)
47 std::cout << i <<
'\n';
Discrete spatio-temporal variations of a set of environmental variables.
Definition landscape.hpp:42
Individuals can not escape the landscape's borders.
Definition bound_policy.hpp:20
Geospatial data formatting and processing.
Definition geography.hpp:17
boost::no_property no_property
Represents no information carried by vertices or edges of a graph.
Definition concepts.hpp:71
auto from_grid(SpatialGrid const &grid, VertexProperty const &v, EdgeProperty const &e, Vicinity const &vicinity, Directionality dir, Policy const &bounding_policy)
Spatial graph construction method.
Definition from_grid.hpp:36
boost::undirectedS isotropy
Property of a process independent of the direction of movement.
Definition directionality.hpp:18
Definition geography_dispersal_kernel_4.cpp:13
Exponential Power dispersal location kernel ( : thin-tailed, : fat-tailed. Always thinner than powe...
Definition dispersal_kernel.hpp:164
Definition vicinity.hpp:53
Definition coalescence_binary_tree_2.cpp:5
Output
Using Kernels with Spatial Graphs Edges
In a simulation context, it can be more efficient to compute the dispersal probabilities along the graph's edges once, especially if these probabilities remain constant over time. This saves repeated computations during each simulation step.
There are two main approaches for setting edge properties:
- Default Initialization and Later Update: You can create the graph with default edge properties and then update those properties later by iterating over the edges. It's simple to implement, but you pay the cost of iterating twice over the edges.
- Direct Initialization: If you want to initialize the edge properties directly, the property itself should be a user-defined class with a proper default constructor, allowing for efficient initialization during graph creation. This approach helps optimize performance, particularly in simulations with many edges or static dispersal probabilities.
Default Initialization and Later Update
Here, we explain how to create a weighted graph with default edge properties and update those properties later by iterating over the edges.
First, when constructing the graph, each edge is initialized with a default set of properties (e.g., weights, dispersal probabilities). This allows you to quickly set up the graph structure without needing to provide specific values for every edge upfront.
Once the graph is created, you can update the edge properties by looping through each edge and assigning more accurate or context-specific values. This method is particularly useful when the final edge properties are derived from complex calculations or external data that may not be immediately available at graph creation.
By initializing the graph with default values, you maintain flexibility, allowing you to efficiently adjust edge properties later in the simulation or process without needing to recreate the entire graph structure.
Input
1#include "quetzal/quetzal.hpp"
8using namespace mp_units::si::unit_symbols;
12 auto file1 = std::filesystem::current_path() /
"data/bio1.tif";
13 auto file2 = std::filesystem::current_path() /
"data/bio12.tif";
16 std::vector<int> times(10);
17 std::iota(times.begin(), times.end(), 2001);
21 auto land = landscape_type::from_file({{
"bio1", file1}, {
"bio12", file2}}, times);
28 using edge_info = kernel::pdf_result_type;
35 auto sphere_distance = [&](
auto point1,
auto point2){
36 return land.to_latlon(point1).great_circle_distance_to(land.to_latlon(point2));
40 for (
const auto& e : graph.edges() ) {
41 auto r = sphere_distance( graph.source( e ), graph.target( e ) );
42 graph[e] = kernel::pdf( r, { .a=200.*km , .b=5.5 } );
46 for (
const auto& e : graph.edges() ) {
47 std::cout << e <<
" : " << graph[e] <<
'\n';
Output
1(1,0) : 5.89588e-23 1/m²
3(2,1) : 5.89588e-23 1/m²
4(3,0) : 5.58082e-132 1/m²
8(4,1) : 5.58082e-132 1/m²
10(4,3) : 1.69142e-30 1/m²
13(5,2) : 5.58082e-132 1/m²
15(5,4) : 1.69142e-30 1/m²
19(6,3) : 5.58082e-132 1/m²
26(7,4) : 5.58082e-132 1/m²
28(7,6) : 1.22468e-40 1/m²
34(8,5) : 5.58082e-132 1/m²
36(8,7) : 1.22468e-40 1/m²
Direct Initialization
Here, we demonstrate how to directly initialize the edge properties during graph creation. This approach is particularly useful when working with large graphs, where manually updating each edge later would be inefficient. By initializing the properties in place, you can ensure that each edge has the correct values from the start.
This method requires defining a user-specific Edge Property class, which includes a constructor to allow for proper instantiation. Doing so enables you to efficiently assign properties such as dispersal probabilities or weights directly to the graph’s edges during the initial setup, streamlining the overall process.
Input
1#include "quetzal/quetzal.hpp"
8using namespace mp_units::si::unit_symbols;
15 probability_type weight;
16 auto compute(
auto source,
auto target,
const auto & grid)
18 auto r = grid.to_latlon(source).great_circle_distance_to(grid.to_latlon(target));
21 edge_info(
auto source,
auto target,
const auto & grid): weight(compute(source, target, grid)) {}
27 auto file1 = std::filesystem::current_path() /
"data/bio1.tif";
28 auto file2 = std::filesystem::current_path() /
"data/bio12.tif";
31 std::vector<int> times(10);
32 std::iota(times.begin(), times.end(), 2001);
36 auto land = landscape_type::from_file({{
"bio1", file1}, {
"bio12", file2}}, times);
50 for (
const auto& e : graph.edges() ) {
51 std::cout << e <<
" : " << graph[e].weight <<
'\n';
quantity< inverse(pow< 2 >(Distance::reference)), typename Distance::rep > pdf_result_type
Probability density function value type.
Definition dispersal_kernel.hpp:166
static constexpr pdf_result_type pdf(Distance r, param_type const &p)
Probability density function.
Definition dispersal_kernel.hpp:182
Output