Skip to content

Commit

Permalink
feat: extending the template project file
Browse files Browse the repository at this point in the history
  • Loading branch information
Becheler committed Dec 20, 2023
1 parent 3770a4f commit 207d2d3
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 17 deletions.
7 changes: 7 additions & 0 deletions docs/2-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ To swiftly open an integrated development environment (IDE), begin coding to exp

This will download the project, builds a Docker Image, manage the dependencies and automatically build and run the tests. If it's the first time you build the image, it may take some time, so you're free to go get a coffee!

Then,
1. navigate to the `template/main.cpp` file
2. Open the VSC Command Palette with `Shift + Command + P` (Mac) or `Ctrl + Shift + P` (Windows/Linux)
3. Click on `Run Task > Run Template Project (Debug)`
4. Read the output in the integrated terminal
5. Edit `template/main.cpp` to your liking and re-run the task, observe the difference in the terminal.

---

### Copy
Expand Down
2 changes: 1 addition & 1 deletion example/expressive_3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ int main()

// 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 elev = expressive::use([e_view](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()
Expand Down
16 changes: 4 additions & 12 deletions example/geography_landscape_1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,16 @@ using namespace quetzal;

int main()
{
// What type you want to use to identify the variable: could also be e.g. an integer
using key_type = std::string;

// What type you want to use to identify the variable: could also be e.g. a time period
using time_type = int;

// Let's define a shorter alias
using landscape_type = quetzal::geography::landscape<key_type, time_type>;

auto file1 = std::filesystem::current_path() / "data/bio1.tif";
auto file2 = std::filesystem::current_path() / "data/bio12.tif";

// The raster have 10 bands that we will assign to 2001 ... 2011.
std::vector<time_type> times(10);
// The raster have 10 bands that we will assign to 2001 ... 2010.
std::vector<int> times(10);
std::iota(times.begin(), times.end(), 2001);

// Initialize the landscape: for each var a key and a file, for all a time series.
auto env = landscape_type::from_files( { {"bio1", file1}, {"bio12", file2} }, times );
using landscape_type = quetzal::geography::landscape<>;
auto env = quetzal::geography::landscape<>::from_files( { {"bio1", file1}, {"bio12", file2} }, times );
std::cout << env << std::endl;

// We indeed recorded 2 variables: bio1 and bio12
Expand Down
3 changes: 2 additions & 1 deletion src/include/quetzal/geography/landscape.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <functional> // std::cref
#include <optional>
#include <iostream>
#include <string>

namespace quetzal::geography
{
Expand All @@ -35,7 +36,7 @@ namespace quetzal::geography
/// @tparam Key A key used to uniquely identifie a variable, e.g. std::string.
/// @tparam Time Type used as time period for every band, e.g. std::string with `4.2-0.3 ka`
/// @ingroup geography
template <typename Key, typename Time>
template <typename Key=std::string, typename Time=int>
class landscape
{

Expand Down
77 changes: 74 additions & 3 deletions template/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,78 @@
#include "quetzal/quetzal.hpp"
#include <cassert>

#include <vector>
#include <string>
#include <filesystem>

int main()
{
std::cout << "yo" << std::endl;
}
// Load the suitability and elevation maps
auto file1 = std::filesystem::current_path() / "data/suitability.tif";
auto file2 = std::filesystem::current_path() / "data/elevation.tif";

// The rasters 10 bands are indexed by the year they represent: 2001 ... 2010
std::vector<int> times(10);
std::iota(times.begin(), times.end(), 2001);

// Initialize the landscape: for each spatial variable a string key and a file value, for all a time series.
auto landscape = quetzal::geography::landscape<>::from_files({{"suit", file1}, {"DEM", file2}}, times);
std::cout << landscape << std::endl;

// Declares some type aliases to shorten notation
using location_type = quetzal::geography::landscape<>::location_descriptor;
using time_type= quetzal::geography::landscape<>::time_descriptor;

// lightweight functors for suitability and digital elevation models that return empty optionals where NA are encounters
auto suit_view = landscape["suit"].to_view();
auto elev_view = landscape["DEM"].to_view();

// We need to make choices here concerning how NA are handled
auto suit = quetzal::expressive::use([&](location_type x, time_type t)
{ return suit_view(x, t).value_or(0.0); });
auto elev = quetzal::expressive::use([&](location_type x, time_type t)
{ return elev_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()

// Small-scale ice-free shelters for the species randomly pop above the snow cover at high-altitude (>123m)
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<double>(is_nunatak) * suit(x, t) : suit(x, t);
};

// To allow dispersal across ocean, we can compose expressions:
auto capacity_with_rafting = [&](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<double>(d(gen)) * 2; // will (rarely) allow 2 individuals to survive in the ocean cell
else if (suit(x, 0) == 0.0 and elev(x, t) > 0.0) // unsuitable continental cell case:
return 0.0; // suitability is minimal, so should be the capacity
else // habitable continental cells:
return nunatak_suitability(x,t); // evaluates suitability simulating nunataks
};

// Account for different dispersal modes
auto friction_with_rafting = [&](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 on the water
else if (suit(x, 0) == 0.0 and elev(x, t) > 0.0) // hostile continental cell case:
return 1.00; // max friction as the cell is not attractive
else // favorable continental cell case:
return 1.0 - suit(x, 0); // higher the suitability, easier the travel
};

// Expressions can be evaluated with a location_type and a time_type argument:
auto x = *landscape.locations().begin();
auto t = *landscape.times().begin();

std::cout << "Friction f( x = " << x << ", t = " << t << " ) = " << friction_with_rafting(x,t) << std::endl;
std::cout << "Carrying capacity K( x = " << x << ", t = " << t << " ) = " << capacity_with_rafting(x,t) << std::endl;

// Spatial graph

}

0 comments on commit 207d2d3

Please sign in to comment.