From 86e2ea1a1225af0a3659695bf2d0b3ff45ee112c Mon Sep 17 00:00:00 2001
From: Becheler <8360330+Becheler@users.noreply.github.com>
Date: Fri, 9 Feb 2024 17:40:27 +0100
Subject: [PATCH 1/3] doc: updating local and dispersal processes
---
docs/4-tutorials.md | 71 ++++++++++++++++---
...l.cpp => geography_dispersal_kernel_1.cpp} | 0
...1.cpp => geography_dispersal_kernel_2.cpp} | 0
example/geography_graph_local_1.cpp | 44 ++++++++++++
4 files changed, 107 insertions(+), 8 deletions(-)
rename example/{demography_dispersal_kernel.cpp => geography_dispersal_kernel_1.cpp} (100%)
rename example/{geography_graph_complete_1.cpp => geography_dispersal_kernel_2.cpp} (100%)
create mode 100644 example/geography_graph_local_1.cpp
diff --git a/docs/4-tutorials.md b/docs/4-tutorials.md
index 972918aa..e13ffc4e 100644
--- a/docs/4-tutorials.md
+++ b/docs/4-tutorials.md
@@ -30,9 +30,9 @@
- @subpage Phylogenetic Networks
- @subpage spatial_graphs
- @subpage spatial_graph_construction
- - @subpage dispersal_kernels
- - @subpage spatial_graphs_information
- - @subpage Growth Expressions
+ - @subpage spatial_graph_information
+ - @subpage spatial_graph_local_process
+ - @subpage spatial_graph_dispersal_kernels
- @subpage Memory Management
## Graphs
@@ -959,7 +959,7 @@ dynamically adding vertices and edges based on user-defined conditions, resultin
---
[//]: # (----------------------------------------------------------------------)
-@page spatial_graphs_information Embedding information along Vertices and Edges
+@page spatial_graph_information Embedding information along Vertices and Edges
@tableofcontents
The focal point of the provided code snippet revolves around the process of constructing a spatial graph from raster data. This spatial graph serves as a powerful tool for visualizing and analyzing spatial relationships and patterns present within the underlying geographic data.
@@ -979,13 +979,55 @@ This approach enables the creation of spatial graphs that not only capture the t
---
[//]: # (----------------------------------------------------------------------)
-@page dispersal_kernels Distance-based dispersal Kernels
+@page spatial_graph_local_process Local processes
@tableofcontents
-## Distance-based kernel
+Local processes on a spatial graph encompass the dynamic phenomena occurring within localized regions defined by the vertices of the graph.
+These processes can entail interactions, transformations, and behaviors that unfold at a granular level, influencing the spatial dynamics and characteristics of the graph. Understanding local processes is vital for comprehending how spatial relationships evolve, how information or resources propagate through the graph, and how localized phenomena contribute to broader spatial patterns and trends.
+
+In the realm of ecology and evolution, these local processes encompass the intricate dynamics unfolding within specific ecological niches or habitats delineated by the vertices of the graph. These processes encapsulate ecological interactions, evolutionary adaptations, and population dynamics occurring at localized scales, shaping the distribution, abundance, and genetic diversity of species within the spatial landscape.
+
+Formalizing these local processes is crucial for understanding ecological community assembly, species responses to environmental changes, and the emergence of biodiversity patterns in spatially diverse landscapes. By investigating local ecological and evolutionary dynamics, researchers can uncover the mechanisms underlying species interactions, habitat fragmentation, and speciation events, thus deepening our understanding of ecosystem functioning and resilience in the face of environmental perturbations.
+
+Local population growth models, integral to ecological and evolutionary studies, allow researchers to simulate and comprehend population dynamics within specific geographic areas or habitats. These models consider environmental conditions, species interactions, and demographic processes to forecast changes in population size and composition over time.
+
+
+This page provides examples of how to combine **Quetzal** components to construct the local simulation process corresponding to your hypotheses.
+
+## Deterministic Models
+
+Deterministic models describe population growth based on precise mathematical equations that govern population dynamics. These models typically assume constant parameters and predictable relationships between population variables, such as birth rates, death rates, and carrying capacity. While deterministic models provide valuable insights into long-term population trends, they may oversimplify real-world complexities and fail to account for stochastic fluctuations or environmental variability.
+
+---
+
+## Stochastic Models
+
+Stochastic models introduce randomness and variability into population growth processes, acknowledging the inherent uncertainty in ecological systems. These models incorporate probabilistic elements, such as random fluctuations in birth and death rates, environmental variability, and demographic stochasticity. Stochastic models are particularly useful for capturing the effects of environmental variability and demographic stochasticity on population dynamics, allowing researchers to assess the likelihood of rare events and population extinctions.
+
+---
+
+## Environmental Niche Models
+
+Environmental niche models focus on how environmental factors influence the distribution and abundance of species within specific habitats. These models integrate ecological niche theory and environmental data to predict species' occurrence probabilities and population densities across spatial gradients. By quantifying the relationships between environmental variables (e.g., temperature, precipitation, habitat quality) and species' ecological requirements, environmental niche models help elucidate how environmental factors shape local population growth and species distributions.
+
+---
+
+## Species Competition Models
+
+Species competition models explore how interspecific interactions, such as competition for resources or interactions with predators, influence population dynamics and species coexistence within local communities. These models typically incorporate competition coefficients, representing the strength of interspecific interactions, into population equations to simulate the effects of species interactions on population growth rates and carrying capacities. Species competition models provide insights into the mechanisms driving species coexistence, competitive exclusion, and community dynamics within ecological communities.
+
+---
+
+[//]: # (----------------------------------------------------------------------)
+@page dispersal_kernels Spatial Interactions
+@tableofcontents
+
+## 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.
+### 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,
\f$a\f$, which is consistent with a distance unit, and a shape parameter,
\f$b\f$, that dictates the curvature of the distribution curve, emphasizing the influence of long-distance events.
@@ -996,11 +1038,24 @@ Quetzal incorporates various kernel types available in the `quetzal::demography:
**Input**
-@include{lineno} demography_dispersal_kernel.cpp
+@include{lineno} geography_dispersal_kernel_1.cpp
**Output**
-@include{lineno} demography_dispersal_kernel.txt
+@include{lineno} geography_dispersal_kernel_1.txt
+
+---
+
+### Using Kernels with 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.
+
+**Input**
+
+@include{lineno} geography_dispersal_kernel_2.cpp
+
+**Output**
+@include{lineno} geography_dispersal_kernel_2.txt
---
diff --git a/example/demography_dispersal_kernel.cpp b/example/geography_dispersal_kernel_1.cpp
similarity index 100%
rename from example/demography_dispersal_kernel.cpp
rename to example/geography_dispersal_kernel_1.cpp
diff --git a/example/geography_graph_complete_1.cpp b/example/geography_dispersal_kernel_2.cpp
similarity index 100%
rename from example/geography_graph_complete_1.cpp
rename to example/geography_dispersal_kernel_2.cpp
diff --git a/example/geography_graph_local_1.cpp b/example/geography_graph_local_1.cpp
new file mode 100644
index 00000000..8628da44
--- /dev/null
+++ b/example/geography_graph_local_1.cpp
@@ -0,0 +1,44 @@
+#include "quetzal/geography.hpp"
+
+namespace geo = quetzal::geography;
+
+// User-defined data structure to store arbitrary vertex information
+struct MyVertexInfo {
+ std::string population_label = "NA";
+ std::vector population_data_chunk;
+ // ... anything else required by the user context
+};
+
+// User-defined data structure to store arbitrary edge information
+struct MyEdgeInfo {
+ mp_units::quantity distance;
+ // needs to be default-constructible
+ MyEdgeInfo() = default;
+ // constructor required by from_grid method: takes a source and a target vertex descriptor, and a spatial grid
+ MyEdgeInfo(auto s, auto t, auto const& raster){
+ distance = raster.to_lonlat(s).great_circle_distance_to( raster.to_lonlat(t) );
+ }
+};
+
+int main()
+{
+ auto file = std::filesystem::current_path() / "data/bio1.tif";
+
+ // The raster have 10 bands that we will assign to 2001 ... 2010.
+ std::vector times(10);
+ std::iota(times.begin(), times.end(), 2001);
+
+ // Landscape construction
+ using landscape_type = geo::raster<>;
+ auto land = geo::raster<>::from_file(file, times);
+
+ // Graph construction with vertex and edge info
+ auto graph = geo::from_grid(land, MyVertexInfo(), MyEdgeInfo(), geo::connect_fully(), geo::isotropy(), geo::mirror());
+
+ std::cout << "Graph has " << graph.num_vertices() << " vertices, " << graph.num_edges() << " edges." << std::endl;
+
+ for( auto const& e : graph.edges() ){
+ std::cout << graph.source(e) << " <-> " << graph.target(e) << " : " << graph[e].distance << std::endl;
+ }
+
+}
From 261a3b3e813d21fd18cfbd936c272484ad932488 Mon Sep 17 00:00:00 2001
From: Becheler <8360330+Becheler@users.noreply.github.com>
Date: Fri, 9 Feb 2024 19:30:18 +0100
Subject: [PATCH 2/3] doc: moving niche models to local parameters section
---
docs/4-tutorials.md | 289 +++++++++++++++++++++-----------------------
1 file changed, 141 insertions(+), 148 deletions(-)
diff --git a/docs/4-tutorials.md b/docs/4-tutorials.md
index e13ffc4e..f7d47165 100644
--- a/docs/4-tutorials.md
+++ b/docs/4-tutorials.md
@@ -15,25 +15,18 @@
- @subpage geotiff_generator
- @subpage shapefile_generator
-## Linking landscapes to local demographic parameters
-
-- @subpage niche_in_quetzal
-- Examples
- - @subpage expressive_suitability_raster
- - @subpage expressive_suitability_DEM_landscape
- - @subpage expressive_friction
-
## Demographic Histories
- @subpage demographic_histories_in_quetzal
- - @subpage Phylogenetic Trees
- - @subpage Phylogenetic Networks
- - @subpage spatial_graphs
- - @subpage spatial_graph_construction
- - @subpage spatial_graph_information
- - @subpage spatial_graph_local_process
- - @subpage spatial_graph_dispersal_kernels
- - @subpage Memory Management
+- @subpage Phylogenetic Trees
+- @subpage Phylogenetic Networks
+- @subpage spatial_graphs
+ - @subpage spatial_graph_construction
+ - @subpage spatial_graph_information
+ - @subpage spatial_graph_local_parameters
+ - @subpage spatial_graph_local_process
+ - @subpage spatial_graph_dispersal_kernels
+ - @subpage Memory Management
## Graphs
@@ -656,137 +649,6 @@ One way to achieve this is by exporting the samples as a shapefile and employing
@include{lineno} geography_write_sample_1.txt
-[//]: # (----------------------------------------------------------------------)
-@page niche_in_quetzal Niche models in Quetzal
-@tableofcontents
-
-# Niche models as mathematical expressions
-
-In the field of ecology, the **niche** refers to the compatibility between a species and a specific environmental condition. It explains how an organism or a population adapts to the availability of resources and competition.
-
-For instance, when resources are plentiful and the presence of predators, parasites, and pathogens is low, the organism or population tends to grow. In locations and times of resources scarcity and high predation, the populations tend to shrink.
-
-The composition and significance of environmental variables that constitute the dimensions of a niche can vary among species, and the importance of specific environmental factors for a species may change depending on geographical and ecological contexts.
-
-@note
-In the broader context of this library, the niche model lacks a specific definition as it relies on the preferences and requirements of individual users. What we can understand is that it involves some combination of spatial and temporal factors that are closely intertwined with the demographic process.
-This justifies the need for a highly adaptable approach for representing the concept of niche, as it is bound to vary depending on the specific species, population, or geographic area under study.
-
-Given this understanding, the primary goal of **Quetzal** is to provide users with `quetzal::expressive`, a user-friendly means to effectively combine geospatial and temporal elements. This enables users to establish meaningful mathematical connections between a diverse and heterogeneous landscape and the underlying demographic processes, based on their own perspectives and preferences. Generally speaking, users will want to use `quetzal::expressive` to mathematically compose spatio-temporal expressions with a signature `double (location_type, time_type)` until they reach a satisfying definition of the local demographic parameter of interest.
-
-# Mathematical composition in C++
-
-Mathematical composition in C++ is not trivial as unlike languages, C++ does not understand mathematical expressions and their composition. In this strongly-typed language, you can not simply multiply the integer `42` and the function \f$ f(x,y) = x^y \f$ and expect it to work. Indeed, if you try to rescale a lambda function, e.g.:
-```cpp
-int a = 42;
-auto f = [](auto x, auto y){return std::pow(x,y); };
-my_expression = a * f; // error
-```
-it will not compile. As the compiler does not know natively what the rules are to multiply a number with whatever type `f` is, it will (verbosely) insult you saying the [`operator*()`](https://en.cppreference.com/w/cpp/language/operators) is not defined for the type `int` and an anonymous type (the lambda function).
-
-# Mathematical composition with quetzal::expressive
-
-You need a library to tell the compiler what to do. This is where `quetzal::expressive` comes handy: it allows you to add, substract, multiply, or compose mathematical expressions by giving them a uniform interface.
-
-In the context of demographic models, `my_expression` in the example below could represent for example `r(x,t)` the growth rate at location `x` at time `t`. Being able to compose several smaller expressions into bigger expressions gives much freedom to users who can for example define `r` in one part on the program and compose it at a later time with a different expression *e.g.* `k(x,t)` the carrying capacity at location `x` at time `t`. By treating these local demographic parameters as independent expressions that can be mixed and matched, `quetzal::expressive` allows great freedom in the implementation details of a spatio-temporal process.
-
-**Input**
-
-@include{lineno} expressive_1.cpp
-
-**Output**
-
-@include{lineno} expressive_1.txt
-
----
-
-[//]: # (----------------------------------------------------------------------)
-@page expressive_suitability_raster Preparing a suitability landscape for the simulation
-
-@note
-The objective of this section is to load a suitability map with `quetzal::geography::raster` and prepare its integration into the simulation framework with `quetzal::expressive`.
-
-In the context of ecological niche modeling (ENM), suitability refers to the degree of appropriateness or favorability of a particular environmental condition for a species to thrive and persist. ENM is a technique used in ecology to predict the distribution of species across landscapes based on their known occurrences and environmental variables.
-
-Suitability can be thought of as a spectrum, ranging from conditions that are highly suitable for a species' survival and reproduction to conditions that are unsuitable or even detrimental. ENM attempts to map this spectrum across geographical space by analyzing the relationships between species occurrences and various environmental factors, such as temperature, precipitation, elevation, soil type, and vegetation cover.
-
-It's important to note that suitability does not solely depend on a single environmental variable. Instead, it's a complex interplay of multiple factors that determine whether a species can survive, reproduce, and establish a viable population in a given area.
-Suitability GIS maps derived from previous analysis steps (see e.g. the niche models in **Quetzal-crumbs** python package) can then be integrated into the coalescence simulation framework.
-
-The following example code
-- loads a suitability map using `quetzal::geography::raster`
-- prepares its integration into the simulation framework using `quetzal::expressive`
-- it gives to the suitability the semantic of a function of space and time `f(x,t)`
-- it gives it access to mathematical operators with `quetzal::expressive::use`
-- then it builds upon it to define an (arbitrary) expression of e.g. the growth rate (but it could be friction, or carrying capacity...)
-
-**Input**
-
-@include{lineno} expressive_2.cpp
-
-**Output**
-
-@include{lineno} expressive_2.txt
-
----
-
-[//]: # (----------------------------------------------------------------------)
-@page expressive_suitability_DEM_landscape Adjusting a suitability map using a Digital Elevation Model
-
-@note
-The objective of this section is to load both a suitability map and a Digital Elevation Model (DEM) with `quetzal::geography::landscape` and prepare their integration into the simulation framework with `quetzal::expressive`
-by dynamically modulating the suitability value as a function of the local elevation.
-
-## Why separating Elevation from Suitability ?
-
-It is a common approach to pack a wealth of information into a sole raster file. For instance, this can involve using a single friction file and designating ocean cells with NA values, and obstacles for dispersal with values of 1. Another
-way is to try to inject elevational data into the suitability map during the Ecological Niche Modeling step.
-
-While these approaches are feasible and occasionally advantageous, they do not consistently represent the optimal or most adaptable solution.
-
-In a broader sense, it's advisable to consider each Geographic Information System (GIS) input file as a means of representing a distinct attribute of the landscape such as suitability, friction, or elevation, utilizing `quetzal::geography::landscape` to read and align these input files then utilizing `quetzal::expressive` to adjust or combine these quantities according to the user's modeling intentions.
-
-As an illustration we will show in this example how to adjust the stochasticity of a suitability-driven process as a function of the
-elevation model. This case and its variations can be applicable in various contexts:
-
-- Conveniently enforcing a threshold value beyond which the suitability undergoes a significant change (*e.g.*, becoming 0). This approach is valuable for examining sky-island systems or for easily estimating an isoline by dynamically adjusting the cutoff parameter value at runtime, as opposed to altering input files for every simulation run.
-- Depicting the likelihood of a propagule reaching a nunatak, that is a small-scale suitable shelter protruding from the snow sheet (or ice cap). Typically nunataks are the only places where plants can survive in these environments.
-
-**Input**
-
-@include{lineno} expressive_3.cpp
-
-**Output**
-
-@include{lineno} expressive_3.txt
-
----
-
-[//]: # (----------------------------------------------------------------------)
-@page expressive_friction Defining a friction model for trans-oceanic dispersal events
-
-@note
-The objective of this section is to load both a suitability map and a Digital Elevation Model (DEM) with `quetzal::geography::landscape` and prepare their integration into the simulation framework with `quetzal::expressive`
-and account for trans-oceanic dispersal events by dynamically defining the friction and the carrying capacity of a cell as functions of the suitability and elevation value.
-
-Drafting events, in the context of biological dispersal, refer to a phenomenon where organisms are carried across large distances by clinging to or being transported by other organisms, objects, or air currents. This can be thought of as a form of passive dispersal where an organism takes advantage of external forces to move beyond its usual range.
-
-The term "drafting" is borrowed from concepts in physics. In biology, this concept is applied to scenarios where organisms, often small and lightweight, catch a ride on other organisms (like birds, insects, or larger animals), objects (like debris), or wind currents. Drafting events can play a significant role in the dispersal of organisms, especially those with limited mobility.
-
-These drafting events provide an opportunity for organisms to reach new areas that they might not be able to access through their own locomotion. It's an interesting ecological phenomenon that highlights the intricate ways in which different species interact and influence each other's distribution and survival.
-
-The general idea is to define lambda expressions that embed stochastic aspects of the model, while preserving the callable interface `(space, time) -> double`.
-
-**Input**
-
-@include{lineno} expressive_4.cpp
-
-**Output**
-
-@include{lineno} expressive_4.txt
-
----
-
[//]: # (----------------------------------------------------------------------)
@page demographic_histories_in_quetzal Demographic Histories in Quetzal
@@ -978,10 +840,142 @@ This approach enables the creation of spatial graphs that not only capture the t
---
+[//]: # (----------------------------------------------------------------------)
+@page spatial_graph_local_parameters Local Parameters and Ecological Niche Modeling
+@tableofcontents
+
+# Environmental Niche Models
+
+## Niche models as mathematical expressions
+
+In the field of ecology, the **niche** refers to the compatibility between a species and a specific environmental condition. It explains how an organism or a population adapts to the availability of resources and competition.
+
+For instance, when resources are plentiful and the presence of predators, parasites, and pathogens is low, the organism or population tends to grow. In locations and times of resources scarcity and high predation, the populations tend to shrink.
+
+The composition and significance of environmental variables that constitute the dimensions of a niche can vary among species, and the importance of specific environmental factors for a species may change depending on geographical and ecological contexts.
+
+@note
+In the broader context of this library, the niche model lacks a specific definition as it relies on the preferences and requirements of individual users. What we can understand is that it involves some combination of spatial and temporal factors that are closely intertwined with the demographic process.
+This justifies the need for a highly adaptable approach for representing the concept of niche, as it is bound to vary depending on the specific species, population, or geographic area under study.
+
+Given this understanding, the primary goal of **Quetzal** is to provide users with `quetzal::expressive`, a user-friendly means to effectively combine geospatial and temporal elements. This enables users to establish meaningful mathematical connections between a diverse and heterogeneous landscape and the underlying demographic processes, based on their own perspectives and preferences. Generally speaking, users will want to use `quetzal::expressive` to mathematically compose spatio-temporal expressions with a signature `double (location_type, time_type)` until they reach a satisfying definition of the local demographic parameter of interest.
+
+## Mathematical composition in C++
+
+Mathematical composition in C++ is not trivial as unlike languages, C++ does not understand mathematical expressions and their composition. In this strongly-typed language, you can not simply multiply the integer `42` and the function \f$ f(x,y) = x^y \f$ and expect it to work. Indeed, if you try to rescale a lambda function, e.g.:
+```cpp
+int a = 42;
+auto f = [](auto x, auto y){return std::pow(x,y); };
+my_expression = a * f; // error
+```
+it will not compile. As the compiler does not know natively what the rules are to multiply a number with whatever type `f` is, it will (verbosely) insult you saying the [`operator*()`](https://en.cppreference.com/w/cpp/language/operators) is not defined for the type `int` and an anonymous type (the lambda function).
+
+## Mathematical composition with quetzal::expressive
+
+You need a library to tell the compiler what to do. This is where `quetzal::expressive` comes handy: it allows you to add, substract, multiply, or compose mathematical expressions by giving them a uniform interface.
+
+In the context of demographic models, `my_expression` in the example below could represent for example `r(x,t)` the growth rate at location `x` at time `t`. Being able to compose several smaller expressions into bigger expressions gives much freedom to users who can for example define `r` in one part on the program and compose it at a later time with a different expression *e.g.* `k(x,t)` the carrying capacity at location `x` at time `t`. By treating these local demographic parameters as independent expressions that can be mixed and matched, `quetzal::expressive` allows great freedom in the implementation details of a spatio-temporal process.
+
+**Input**
+
+@include{lineno} expressive_1.cpp
+
+**Output**
+
+@include{lineno} expressive_1.txt
+
+---
+
+# Preparing a suitability landscape for the simulation
+
+@note
+The objective of this section is to load a suitability map with `quetzal::geography::raster` and prepare its integration into the simulation framework with `quetzal::expressive`.
+
+In the context of ecological niche modeling (ENM), suitability refers to the degree of appropriateness or favorability of a particular environmental condition for a species to thrive and persist. ENM is a technique used in ecology to predict the distribution of species across landscapes based on their known occurrences and environmental variables.
+
+Suitability can be thought of as a spectrum, ranging from conditions that are highly suitable for a species' survival and reproduction to conditions that are unsuitable or even detrimental. ENM attempts to map this spectrum across geographical space by analyzing the relationships between species occurrences and various environmental factors, such as temperature, precipitation, elevation, soil type, and vegetation cover.
+
+It's important to note that suitability does not solely depend on a single environmental variable. Instead, it's a complex interplay of multiple factors that determine whether a species can survive, reproduce, and establish a viable population in a given area.
+Suitability GIS maps derived from previous analysis steps (see e.g. the niche models in **Quetzal-crumbs** python package) can then be integrated into the coalescence simulation framework.
+
+The following example code
+- loads a suitability map using `quetzal::geography::raster`
+- prepares its integration into the simulation framework using `quetzal::expressive`
+- it gives to the suitability the semantic of a function of space and time `f(x,t)`
+- it gives it access to mathematical operators with `quetzal::expressive::use`
+- then it builds upon it to define an (arbitrary) expression of e.g. the growth rate (but it could be friction, or carrying capacity...)
+
+**Input**
+
+@include{lineno} expressive_2.cpp
+
+**Output**
+
+@include{lineno} expressive_2.txt
+
+---
+
+# Adjusting a suitability map using a Digital Elevation Model
+
+@note
+The objective of this section is to load both a suitability map and a Digital Elevation Model (DEM) with `quetzal::geography::landscape` and prepare their integration into the simulation framework with `quetzal::expressive`
+by dynamically modulating the suitability value as a function of the local elevation.
+
+## Why separating Elevation from Suitability ?
+
+It is a common approach to pack a wealth of information into a sole raster file. For instance, this can involve using a single friction file and designating ocean cells with NA values, and obstacles for dispersal with values of 1. Another
+way is to try to inject elevational data into the suitability map during the Ecological Niche Modeling step.
+
+While these approaches are feasible and occasionally advantageous, they do not consistently represent the optimal or most adaptable solution.
+
+In a broader sense, it's advisable to consider each Geographic Information System (GIS) input file as a means of representing a distinct attribute of the landscape such as suitability, friction, or elevation, utilizing `quetzal::geography::landscape` to read and align these input files then utilizing `quetzal::expressive` to adjust or combine these quantities according to the user's modeling intentions.
+
+As an illustration we will show in this example how to adjust the stochasticity of a suitability-driven process as a function of the
+elevation model. This case and its variations can be applicable in various contexts:
+
+- Conveniently enforcing a threshold value beyond which the suitability undergoes a significant change (*e.g.*, becoming 0). This approach is valuable for examining sky-island systems or for easily estimating an isoline by dynamically adjusting the cutoff parameter value at runtime, as opposed to altering input files for every simulation run.
+- Depicting the likelihood of a propagule reaching a nunatak, that is a small-scale suitable shelter protruding from the snow sheet (or ice cap). Typically nunataks are the only places where plants can survive in these environments.
+
+**Input**
+
+@include{lineno} expressive_3.cpp
+
+**Output**
+
+@include{lineno} expressive_3.txt
+
+---
+
+# Defining a friction model for trans-oceanic dispersal events
+
+@note
+The objective of this section is to load both a suitability map and a Digital Elevation Model (DEM) with `quetzal::geography::landscape` and prepare their integration into the simulation framework with `quetzal::expressive`
+and account for trans-oceanic dispersal events by dynamically defining the friction and the carrying capacity of a cell as functions of the suitability and elevation value.
+
+Drafting events, in the context of biological dispersal, refer to a phenomenon where organisms are carried across large distances by clinging to or being transported by other organisms, objects, or air currents. This can be thought of as a form of passive dispersal where an organism takes advantage of external forces to move beyond its usual range.
+
+The term "drafting" is borrowed from concepts in physics. In biology, this concept is applied to scenarios where organisms, often small and lightweight, catch a ride on other organisms (like birds, insects, or larger animals), objects (like debris), or wind currents. Drafting events can play a significant role in the dispersal of organisms, especially those with limited mobility.
+
+These drafting events provide an opportunity for organisms to reach new areas that they might not be able to access through their own locomotion. It's an interesting ecological phenomenon that highlights the intricate ways in which different species interact and influence each other's distribution and survival.
+
+The general idea is to define lambda expressions that embed stochastic aspects of the model, while preserving the callable interface `(space, time) -> double`.
+
+**Input**
+
+@include{lineno} expressive_4.cpp
+
+**Output**
+
+@include{lineno} expressive_4.txt
+
+---
+
[//]: # (----------------------------------------------------------------------)
@page spatial_graph_local_process Local processes
@tableofcontents
+## Background
+
Local processes on a spatial graph encompass the dynamic phenomena occurring within localized regions defined by the vertices of the graph.
These processes can entail interactions, transformations, and behaviors that unfold at a granular level, influencing the spatial dynamics and characteristics of the graph. Understanding local processes is vital for comprehending how spatial relationships evolve, how information or resources propagate through the graph, and how localized phenomena contribute to broader spatial patterns and trends.
@@ -991,7 +985,6 @@ Formalizing these local processes is crucial for understanding ecological commun
Local population growth models, integral to ecological and evolutionary studies, allow researchers to simulate and comprehend population dynamics within specific geographic areas or habitats. These models consider environmental conditions, species interactions, and demographic processes to forecast changes in population size and composition over time.
-
This page provides examples of how to combine **Quetzal** components to construct the local simulation process corresponding to your hypotheses.
## Deterministic Models
From 8fc57c6a01da4198bb98eaa953e3e3d208e5c11e Mon Sep 17 00:00:00 2001
From: Becheler <8360330+Becheler@users.noreply.github.com>
Date: Mon, 1 Jul 2024 00:16:46 +0200
Subject: [PATCH 3/3] doc: constructing graph from grid and local processes
deterministic/stochastic
---
docs/4-tutorials.md | 66 +++++++++++++++++--
example/expressive_2.cpp | 2 +-
example/expressive_3.cpp | 8 +--
example/expressive_4.cpp | 8 +--
example/geography_graph_4.cpp | 4 +-
example/geography_graph_local_1.cpp | 44 -------------
.../quetzal/geography/graph/from_grid.hpp | 17 ++++-
7 files changed, 87 insertions(+), 62 deletions(-)
delete mode 100644 example/geography_graph_local_1.cpp
diff --git a/docs/4-tutorials.md b/docs/4-tutorials.md
index f7d47165..a5bd70de 100644
--- a/docs/4-tutorials.md
+++ b/docs/4-tutorials.md
@@ -841,7 +841,7 @@ This approach enables the creation of spatial graphs that not only capture the t
---
[//]: # (----------------------------------------------------------------------)
-@page spatial_graph_local_parameters Local Parameters and Ecological Niche Modeling
+@page spatial_graph_local_parameters Local Parameters
@tableofcontents
# Environmental Niche Models
@@ -971,13 +971,12 @@ The general idea is to define lambda expressions that embed stochastic aspects o
---
[//]: # (----------------------------------------------------------------------)
-@page spatial_graph_local_process Local processes
+@page spatial_graph_local_process Local autoregressive processes
@tableofcontents
## Background
-Local processes on a spatial graph encompass the dynamic phenomena occurring within localized regions defined by the vertices of the graph.
-These processes can entail interactions, transformations, and behaviors that unfold at a granular level, influencing the spatial dynamics and characteristics of the graph. Understanding local processes is vital for comprehending how spatial relationships evolve, how information or resources propagate through the graph, and how localized phenomena contribute to broader spatial patterns and trends.
+While local parameters describe a static relationship to the environment, local processes on a spatial graph are dynamic in nature. They encompass the dynamic phenomena occurring within localized regions defined by the vertices of the graph, including interactions, transformations, and behaviors unfolding at a granular level. Understanding these processes is vital for comprehending how spatial relationships evolve, how information or resources propagate through the graph, and how localized phenomena contribute to broader spatial patterns and their temporal trends.
In the realm of ecology and evolution, these local processes encompass the intricate dynamics unfolding within specific ecological niches or habitats delineated by the vertices of the graph. These processes encapsulate ecological interactions, evolutionary adaptations, and population dynamics occurring at localized scales, shaping the distribution, abundance, and genetic diversity of species within the spatial landscape.
@@ -987,28 +986,87 @@ Local population growth models, integral to ecological and evolutionary studies,
This page provides examples of how to combine **Quetzal** components to construct the local simulation process corresponding to your hypotheses.
+## Autoregressive Models
+
+A process in which the value at time \f$ t \f$ depends on its value at time \f$ tâ1 \f$ (like population growth over time)
+is commonly referred to as an autoregressive process or a first-order autoregressive process (\f$AR(1)\f$).
+These are widely used in time series analysis and modeling to capture temporal dependencies and patterns in data.
+
+In mathematical terms, it can be represented as:
+
+\f[
+ X_t =â \phi X_{t-1} + \epsilon_t
+\f]
+
+where:
+
+- \f$ X_t \f$ is the value of the process at time \f$ t \f$
+- \f$ X_{t-1} \f$ is the value of the process at time \f$ t-1 \f$
+- \f$ \phi \f$ is the autoregressive parameter,
+- \f$ \epsilon_t \f$ is a random error term.
+
+Users can represent first-order (or even p-order) autoregressive processes using **Quetzal** components. Although flexible, the general approach will be to represent time series as `std::vector` structures embedded in each vertex or edges they relate to, where a quantity \f$q\f$ a time \f$t\f$ at vertex \f$x\f$ is described by `graph[x][q][t]`.
+
+---
+
## Deterministic Models
Deterministic models describe population growth based on precise mathematical equations that govern population dynamics. These models typically assume constant parameters and predictable relationships between population variables, such as birth rates, death rates, and carrying capacity. While deterministic models provide valuable insights into long-term population trends, they may oversimplify real-world complexities and fail to account for stochastic fluctuations or environmental variability.
+In this example, we store a time-series vector at each vertex of the graph to monitor the population dynamics. After initializing one vertex with a non-zero value, we iterate through time to update the series. It's important to note that, since we defined no migration along the graph's edges, all time-series except one remain at zero.
+
+**Input**
+
+@include{lineno} geography_graph_local_process_1.cpp
+
+**Output**
+
+@include{lineno} geography_graph_local_process_1.txt
+
---
## Stochastic Models
Stochastic models introduce randomness and variability into population growth processes, acknowledging the inherent uncertainty in ecological systems. These models incorporate probabilistic elements, such as random fluctuations in birth and death rates, environmental variability, and demographic stochasticity. Stochastic models are particularly useful for capturing the effects of environmental variability and demographic stochasticity on population dynamics, allowing researchers to assess the likelihood of rare events and population extinctions.
+We build up on the previous example by adding some stochasticity in the process. We store a time-series vector at each vertex of the graph to monitor the population dynamics. After initializing one vertex with a non-zero value, we iterate through time to update the series. It's important to note that, since we defined no migration along the graph's edges, some time-series remain at zero.
+
+**Input**
+
+@include{lineno} geography_graph_local_process_2.cpp
+
+**Output**
+
+@include{lineno} geography_graph_local_process_2.txt
+
---
## Environmental Niche Models
Environmental niche models focus on how environmental factors influence the distribution and abundance of species within specific habitats. These models integrate ecological niche theory and environmental data to predict species' occurrence probabilities and population densities across spatial gradients. By quantifying the relationships between environmental variables (e.g., temperature, precipitation, habitat quality) and species' ecological requirements, environmental niche models help elucidate how environmental factors shape local population growth and species distributions.
+**Input**
+
+@include{lineno} geography_graph_local_process_3.cpp
+
+**Output**
+
+@include{lineno} geography_graph_local_process_3.txt
+
---
## Species Competition Models
Species competition models explore how interspecific interactions, such as competition for resources or interactions with predators, influence population dynamics and species coexistence within local communities. These models typically incorporate competition coefficients, representing the strength of interspecific interactions, into population equations to simulate the effects of species interactions on population growth rates and carrying capacities. Species competition models provide insights into the mechanisms driving species coexistence, competitive exclusion, and community dynamics within ecological communities.
+**Input**
+
+@include{lineno} geography_graph_local_process_4.cpp
+
+**Output**
+
+@include{lineno} geography_graph_local_process_4.txt
+
---
[//]: # (----------------------------------------------------------------------)
diff --git a/example/expressive_2.cpp b/example/expressive_2.cpp
index 9e0351a7..cd296ab9 100644
--- a/example/expressive_2.cpp
+++ b/example/expressive_2.cpp
@@ -24,7 +24,7 @@ int main()
// We need to make choices here concerning how NA are handled
auto f1 = raster.to_view(); // lightweight functor returning empty optionals for NA
- auto f2 = [f1](location_type x, time_type t) {
+ auto f2 = [&](location_type x, time_type t) {
return f1(x, t).value_or(0.0);
}; // remap empty optionals (NA) to 0.0 suitability value
auto f3 = expressive::use(f2); // f3 has now access to math operators
diff --git a/example/expressive_3.cpp b/example/expressive_3.cpp
index dc04bd73..75e33696 100644
--- a/example/expressive_3.cpp
+++ b/example/expressive_3.cpp
@@ -29,20 +29,20 @@ int main()
auto e_view = landscape["DEM"].to_view();
// We need to make choices here concerning how NA are handled
- auto suit = expressive::use([s_view](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
- auto elev = expressive::use([e_view](location_type x, time_type t) { return e_view(x, t).value_or(0.0); });
+ auto suit = expressive::use([&](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
+ auto elev = expressive::use([&](location_type x, time_type t) { return e_view(x, t).value_or(0.0); });
std::random_device rd; // a seed source for the random number engine
std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd()
// 1) hostile environment above an isoline: particularly useful if 123.0 is a randomly sampled parameter to be
// estimated
- auto isoline_suitability = [suit, elev](location_type x, time_type t) {
+ auto isoline_suitability = [&](location_type x, time_type t) {
return (elev(x, t) >= 123.0) ? 0.0 : suit(x, t);
};
// 2) small-scale suitable ice-free shelters randomly popping above the snow cover at high-altitude
- auto nunatak_suitability = [suit, elev, &gen](location_type x, time_type t) {
+ auto nunatak_suitability = [&](location_type x, time_type t) {
std::bernoulli_distribution d(0.1); // give "false" 9/10 of the time
bool is_nunatak = d(gen);
return (elev(x, t) >= 123.0) ? static_cast(is_nunatak) * suit(x, t) : suit(x, t);
diff --git a/example/expressive_4.cpp b/example/expressive_4.cpp
index 814e08d4..9396725f 100644
--- a/example/expressive_4.cpp
+++ b/example/expressive_4.cpp
@@ -29,13 +29,13 @@ int main()
auto e_view = landscape["DEM"].to_view();
// We need to make choices here concerning how NA are handled
- auto suit = expressive::use([s_view](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
- auto elev = expressive::use([s_view](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
+ auto suit = expressive::use([&](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
+ auto elev = expressive::use([&](location_type x, time_type t) { return s_view(x, t).value_or(0.0); });
std::random_device rd; // a seed source for the random number engine
std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd()
- auto rafting_capacity = [suit, elev, &gen](location_type x, time_type t) {
+ auto rafting_capacity = [&](location_type x, time_type t) {
std::bernoulli_distribution d(0.1); // give "false" 9/10 of the time
if (suit(x, t) == 0.0 and elev(x, t) == 0.0) // ocean cell case
return static_cast(d(gen)) * 2; // will (rarely) allow 2 individuals to survive in the ocean cell
@@ -45,7 +45,7 @@ int main()
return 100. * suit(x, 0); // simple rescaling by the max number of individuals in a cell
};
- auto rafting_friction = [suit, elev](location_type x, time_type t) {
+ auto rafting_friction = [&](location_type x, time_type t) {
if (suit(x, t) == 0.0 and elev(x, t) == 0.0) // ocean cell case
return 0.0; // the raft should move freely
else if (suit(x, 0) == 0.0 and elev(x, t) > 0.0) // hostile continental cell case
diff --git a/example/geography_graph_4.cpp b/example/geography_graph_4.cpp
index 949affe3..f310a5a5 100644
--- a/example/geography_graph_4.cpp
+++ b/example/geography_graph_4.cpp
@@ -6,8 +6,8 @@ namespace geo = quetzal::geography;
struct MySpatialGrid
{
// it is just required to define these two functions
- constexpr int width() const { return 300; }
- constexpr int height() const { return 100; }
+ constexpr int width() const { return 30; }
+ constexpr int height() const { return 10; }
};
int main()
diff --git a/example/geography_graph_local_1.cpp b/example/geography_graph_local_1.cpp
deleted file mode 100644
index 8628da44..00000000
--- a/example/geography_graph_local_1.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "quetzal/geography.hpp"
-
-namespace geo = quetzal::geography;
-
-// User-defined data structure to store arbitrary vertex information
-struct MyVertexInfo {
- std::string population_label = "NA";
- std::vector population_data_chunk;
- // ... anything else required by the user context
-};
-
-// User-defined data structure to store arbitrary edge information
-struct MyEdgeInfo {
- mp_units::quantity distance;
- // needs to be default-constructible
- MyEdgeInfo() = default;
- // constructor required by from_grid method: takes a source and a target vertex descriptor, and a spatial grid
- MyEdgeInfo(auto s, auto t, auto const& raster){
- distance = raster.to_lonlat(s).great_circle_distance_to( raster.to_lonlat(t) );
- }
-};
-
-int main()
-{
- auto file = std::filesystem::current_path() / "data/bio1.tif";
-
- // The raster have 10 bands that we will assign to 2001 ... 2010.
- std::vector times(10);
- std::iota(times.begin(), times.end(), 2001);
-
- // Landscape construction
- using landscape_type = geo::raster<>;
- auto land = geo::raster<>::from_file(file, times);
-
- // Graph construction with vertex and edge info
- auto graph = geo::from_grid(land, MyVertexInfo(), MyEdgeInfo(), geo::connect_fully(), geo::isotropy(), geo::mirror());
-
- std::cout << "Graph has " << graph.num_vertices() << " vertices, " << graph.num_edges() << " edges." << std::endl;
-
- for( auto const& e : graph.edges() ){
- std::cout << graph.source(e) << " <-> " << graph.target(e) << " : " << graph[e].distance << std::endl;
- }
-
-}
diff --git a/src/include/quetzal/geography/graph/from_grid.hpp b/src/include/quetzal/geography/graph/from_grid.hpp
index f861afd3..0067e6ed 100644
--- a/src/include/quetzal/geography/graph/from_grid.hpp
+++ b/src/include/quetzal/geography/graph/from_grid.hpp
@@ -22,7 +22,7 @@ namespace quetzal::geography
/// @param v An example of information to be stored on vertices
/// @param e An example of information to be stored on edges
/// @param vicinity A policy class giving the connectivity method to be applied
-/// @param directionality A policy class giving the directionality (isotropy or anistropy)
+/// @param directionality A policy class giving the directionality (isotropy or anisotropy)
/// @param bound A BoundPolicy
/// @return A graph with the desired level of connectivity
template ;
- // using graph_type = typename Vicinity::graph_type;
- // Graph size has to be static in dense graphs :/
graph_type graph( grid.width() * grid.height() + bounding_policy.num_extra_vertices() ) ;
vicinity.connect(graph, grid, bounding_policy);
+
+ if constexpr ( ! std::is_same_v) {
+ for( auto vertex : graph.vertices() ){
+ graph[vertex] = v;
+ }
+ }
+
+ if constexpr ( ! std::is_same_v) {
+ for(auto edge : graph.edges()){
+ graph[edge] = e;
+ }
+ }
+
return graph;
}