pops-core  0.9
PoPS (Pest or Pathogen Spread) Model Core C++ library
radial_kernel.hpp
Go to the documentation of this file.
1 /*
2  * PoPS model - radial disperal kernel
3  *
4  * Copyright (C) 2015-2020 by the authors.
5  *
6  * Authors: Vaclav Petras (wenzeslaus gmail com)
7  * Chris Jones (cjones1688 gmail com)
8  * Anna Petrasova (kratochanna gmail com)
9  * Zexi Chen (zchen22 ncsu edu)
10  *
11  * The code contained herein is licensed under the GNU General Public
12  * License. You may obtain a copy of the GNU General Public License
13  * Version 2 or later at the following locations:
14  *
15  * http://www.opensource.org/licenses/gpl-license.html
16  * http://www.gnu.org/copyleft/gpl.html
17  */
18 
19 #ifndef POPS_RADIAL_KERNEL_HPP
20 #define POPS_RADIAL_KERNEL_HPP
21 
22 #include "kernel_types.hpp"
23 #include "utils.hpp"
26 #include "logistic_kernel.hpp"
28 #include "exponential_kernel.hpp"
29 #include "cauchy_kernel.hpp"
30 #include "gamma_kernel.hpp"
31 #include "lognormal_kernel.hpp"
32 #include "normal_kernel.hpp"
33 #include "weibull_kernel.hpp"
34 #include "power_law_kernel.hpp"
35 
36 #include <cmath>
37 #include <map>
38 #include <tuple>
39 #include <array>
40 #include <random>
41 #include <algorithm>
42 #include <stdexcept>
43 
44 namespace pops {
45 
51 inline Direction direction_from_string(const std::string& text)
52 {
53  std::map<std::string, Direction> mapping{
54  {"N", Direction::N},
55  {"NE", Direction::NE},
56  {"E", Direction::E},
57  {"SE", Direction::SE},
58  {"S", Direction::S},
59  {"SW", Direction::SW},
60  {"W", Direction::W},
61  {"NW", Direction::NW},
62  {"NONE", Direction::None},
63  {"None", Direction::None},
64  {"none", Direction::None},
65  {"", Direction::None}};
66  try {
67  return mapping.at(text);
68  }
69  catch (const std::out_of_range&) {
70  throw std::invalid_argument(
71  "direction_from_string: Invalid value '" + text + "' provided");
72  }
73 }
74 
77 inline Direction direction_from_string(const char* text)
78 {
79  // call the string version
80  return direction_from_string(text ? std::string(text) : std::string());
81 }
82 
93 template<typename IntegerRaster>
95 {
96 protected:
97  // the west-east resolution of the pixel
99  // the north-south resolution of the pixel
113 
114 public:
116  double ew_res,
117  double ns_res,
118  DispersalKernelType dispersal_kernel,
119  double distance_scale,
120  Direction dispersal_direction = Direction::None,
121  double dispersal_direction_kappa = 0,
122  double shape = 1)
123  : east_west_resolution(ew_res),
124  north_south_resolution(ns_res),
125  dispersal_kernel_type_(dispersal_kernel),
126  // Here we initialize all distributions,
127  // although we won't use all of them.
128  cauchy_distribution(distance_scale),
129  // When lambda is higher, exponential gives less higher values,
130  // so we do multiplicative inverse to behave like cauchy.
131  exponential_distribution(distance_scale),
132  weibull_distribution(distance_scale, shape),
133  normal_distribution(distance_scale),
134  lognormal_distribution(distance_scale),
135  power_law_distribution(distance_scale, shape),
136  hyperbolic_secant_distribution(distance_scale),
137  gamma_distribution(distance_scale, shape),
138  exponential_power_distribution(distance_scale, shape),
139  logistic_distribution(distance_scale),
140  // if no wind, then kappa is 0
141  // TODO: change these two computations to standalone inline
142  // functions (dir to rad and adjust kappa)
143  von_mises(
144  static_cast<int>(dispersal_direction) * PI / 180,
145  dispersal_direction == Direction::None ? 0 : dispersal_direction_kappa)
146  {}
147 
156  template<typename Generator>
157  std::tuple<int, int> operator()(Generator& generator, int row, int col)
158  {
159  double distance = 0;
160  double theta = 0;
161  // switch between the supported kernels
162  // generate the distance from cauchy distribution or cauchy mixture distribution
164  distance = std::abs(cauchy_distribution.random(generator));
165  }
167  distance = std::abs(exponential_distribution.random(generator));
168  }
170  distance = std::abs(weibull_distribution.random(generator));
171  }
173  distance = std::abs(normal_distribution.random(generator));
174  }
176  distance = std::abs(lognormal_distribution.random(generator));
177  }
179  distance = std::abs(power_law_distribution.random(generator));
180  }
182  distance = std::abs(hyperbolic_secant_distribution.random(generator));
183  }
185  distance = std::abs(gamma_distribution.random(generator));
186  }
188  distance = std::abs(exponential_power_distribution.random(generator));
189  }
191  distance = std::abs(logistic_distribution.random(generator));
192  }
193  else {
194  // TODO: move this to constructor (fail fast)
195  // not all allowed kernels will/are supported by this class
196  throw std::invalid_argument(
197  "RadialDispersalKernel: Unsupported dispersal kernel type");
198  }
199  theta = von_mises(generator);
200 
201  row -= round(distance * cos(theta) / north_south_resolution);
202  col += round(distance * sin(theta) / east_west_resolution);
203 
204  return std::make_tuple(row, col);
205  }
206 
212  static bool supports_kernel(const DispersalKernelType type)
213  {
214  static const std::array<DispersalKernelType, 10> supports = {
225  auto it = std::find(supports.cbegin(), supports.cend(), type);
226  return it != supports.cend();
227  }
228 };
229 
230 } // namespace pops
231 
232 #endif // POPS_RADIAL_KERNEL_HPP
pops::DispersalKernelType::HyperbolicSecant
@ HyperbolicSecant
Hyperbolic secant dispersal kernel.
Direction::NW
@ NW
Northwest.
pops::RadialDispersalKernel::power_law_distribution
PowerLawKernel power_law_distribution
Definition: radial_kernel.hpp:107
pops::DispersalKernelType::Gamma
@ Gamma
Gamma dispersal kernel.
pops::RadialDispersalKernel::cauchy_distribution
CauchyKernel cauchy_distribution
Definition: radial_kernel.hpp:102
pops::RadialDispersalKernel::dispersal_kernel_type_
DispersalKernelType dispersal_kernel_type_
Definition: radial_kernel.hpp:101
pops::CauchyKernel::random
double random(Generator &generator)
Returns random value from cauchy distribution Used by RadialKernel to determine location of spread.
Definition: cauchy_kernel.hpp:55
pops::DispersalKernelType::Logistic
@ Logistic
Logistic dispersal kernel.
pops::RadialDispersalKernel::gamma_distribution
GammaKernel gamma_distribution
Definition: radial_kernel.hpp:109
pops::WeibullKernel
Dispersal kernel for weibull distribution class utilized by RadialKernel and DeterministicKernel.
Definition: weibull_kernel.hpp:33
utils.hpp
pops::WeibullKernel::random
double random(Generator &generator)
Returns random value from weibull distribution Used by RadialKernel to determine location of spread.
Definition: weibull_kernel.hpp:57
pops::DispersalKernelType::Exponential
@ Exponential
Exponential dispersal kernel.
hyperbolic_secant_kernel.hpp
power_law_kernel.hpp
exponential_kernel.hpp
pops::RadialDispersalKernel::north_south_resolution
double north_south_resolution
Definition: radial_kernel.hpp:100
pops::RadialDispersalKernel::supports_kernel
static bool supports_kernel(const DispersalKernelType type)
Returns true if the kernel class support a given kernel type.
Definition: radial_kernel.hpp:212
pops::DispersalKernelType::Weibull
@ Weibull
Weibull dispersal kernel.
pops::ExponentialPowerKernel
Dispersal kernel for exponential power distribution class utilized by RadialKernel and DeterministicK...
Definition: exponential_power_kernel.hpp:33
pops::DispersalKernelType::ExponentialPower
@ ExponentialPower
Exponential power dispersal kernel.
Direction::W
@ W
West.
PI
#define PI
Definition: utils.hpp:36
pops::CauchyKernel
Dispersal kernel for cauchy distribution class utilized by RadialKernel and DeterministicKernel.
Definition: cauchy_kernel.hpp:33
pops::RadialDispersalKernel::east_west_resolution
double east_west_resolution
Definition: radial_kernel.hpp:98
Direction::SW
@ SW
Southwest.
von_mises_distribution.hpp
pops::GammaKernel::random
double random(Generator &generator)
Returns random value from gamma distribution Used by RadialKernel to determine location of spread.
Definition: gamma_kernel.hpp:57
pops::DispersalKernelType::Normal
@ Normal
Normal dispersal kernel.
pops::VonMisesDistribution
Von Mises Distribution (Circular data distribution)
Definition: von_mises_distribution.hpp:40
pops::NormalKernel::random
double random(Generator &generator)
Returns random value from normal distribution Used by RadialKernel to determine location of spread.
Definition: normal_kernel.hpp:55
pops::RadialDispersalKernel::exponential_distribution
ExponentialKernel exponential_distribution
Definition: radial_kernel.hpp:103
pops::DispersalKernelType
DispersalKernelType
Type of dispersal kernel.
Definition: kernel_types.hpp:53
pops::LogisticKernel
Dispersal kernel for logistic distribution class utilized by RadialKernel and DeterministicKernel.
Definition: logistic_kernel.hpp:32
logistic_kernel.hpp
normal_kernel.hpp
pops::DispersalKernelType::Cauchy
@ Cauchy
Cauchy dispersal kernel.
pops::DispersalKernelType::PowerLaw
@ PowerLaw
Power law dispersal kernel.
pops::HyperbolicSecantKernel::random
double random(Generator &generator)
Returns random value from hyperbolic secant distribution Used by RadialKernel to determine location o...
Definition: hyperbolic_secant_kernel.hpp:54
pops
Definition: cauchy_kernel.hpp:25
pops::RadialDispersalKernel::normal_distribution
NormalKernel normal_distribution
Definition: radial_kernel.hpp:105
Direction::E
@ E
East.
pops::ExponentialKernel::random
double random(Generator &generator)
Returns random value from exponential distribution Used by RadialKernel to determine location of spre...
Definition: exponential_kernel.hpp:54
pops::PowerLawKernel
Dispersal kernel for power law distribution class utilized by RadialKernel and DeterministicKernel.
Definition: power_law_kernel.hpp:31
pops::DispersalKernelType::LogNormal
@ LogNormal
Log-normal dispersal kernel.
pops::ExponentialPowerKernel::random
double random(Generator &generator)
Returns random value from exponential power distribution Used by RadialKernel to determine location o...
Definition: exponential_power_kernel.hpp:57
Direction::SE
@ SE
Southeast.
pops::RadialDispersalKernel::exponential_power_distribution
ExponentialPowerKernel exponential_power_distribution
Definition: radial_kernel.hpp:110
exponential_power_kernel.hpp
pops::RadialDispersalKernel::hyperbolic_secant_distribution
HyperbolicSecantKernel hyperbolic_secant_distribution
Definition: radial_kernel.hpp:108
pops::PowerLawKernel::random
double random(Generator &generator)
Returns random value from power law distribution Used by RadialKernel to determine location of spread...
Definition: power_law_kernel.hpp:57
pops::LogNormalKernel
Dispersal kernel for log normal distribution class utilized by RadialKernel and DeterministicKernel.
Definition: lognormal_kernel.hpp:35
pops::RadialDispersalKernel::logistic_distribution
LogisticKernel logistic_distribution
Definition: radial_kernel.hpp:111
pops::DispersalKernelType::None
@ None
No dispersal kernel (no spread)
pops::ExponentialKernel
Dispersal kernel for exponential distribution class utilized by RadialKernel and DeterministicKernel.
Definition: exponential_kernel.hpp:33
Direction::N
@ N
North.
pops::NormalKernel
Dispersal kernel for normal distribution class utilized by RadialKernel and DeterministicKernel.
Definition: normal_kernel.hpp:34
gamma_kernel.hpp
pops::HyperbolicSecantKernel
Dispersal kernel for hyperbolic secant class utilized by RadialKernel and DeterministicKernel.
Definition: hyperbolic_secant_kernel.hpp:33
pops::direction_from_string
Direction direction_from_string(const std::string &text)
Get a corresponding enum value for a string which direction.
Definition: radial_kernel.hpp:51
Direction::NE
@ NE
Northeast.
pops::LogisticKernel::random
double random(Generator &generator)
Returns random value from logistic distribution Used by RadialKernel to determine location of spread.
Definition: logistic_kernel.hpp:54
lognormal_kernel.hpp
pops::LogNormalKernel::random
double random(Generator &generator)
Returns random value from log normal distribution Used by RadialKernel to determine location of sprea...
Definition: lognormal_kernel.hpp:56
pops::RadialDispersalKernel
Dispersal kernel providing all the radial kernels.
Definition: radial_kernel.hpp:94
weibull_kernel.hpp
kernel_types.hpp
Kernel types enum and helper functions.
pops::RadialDispersalKernel::RadialDispersalKernel
RadialDispersalKernel(double ew_res, double ns_res, DispersalKernelType dispersal_kernel, double distance_scale, Direction dispersal_direction=Direction::None, double dispersal_direction_kappa=0, double shape=1)
Definition: radial_kernel.hpp:115
Direction::None
@ None
No direction (non-directional)
pops::RadialDispersalKernel::von_mises
VonMisesDistribution von_mises
Definition: radial_kernel.hpp:112
Direction::S
@ S
South.
cauchy_kernel.hpp
pops::RadialDispersalKernel::lognormal_distribution
LogNormalKernel lognormal_distribution
Definition: radial_kernel.hpp:106
pops::RadialDispersalKernel::weibull_distribution
WeibullKernel weibull_distribution
Definition: radial_kernel.hpp:104
pops::RadialDispersalKernel::operator()
std::tuple< int, int > operator()(Generator &generator, int row, int col)
Generates a new position for the spread.
Definition: radial_kernel.hpp:157
pops::GammaKernel
Dispersal kernel for gamma distribution class utilized by RadialKernel and DeterministicKernel.
Definition: gamma_kernel.hpp:33
Direction
Direction
Spread direction.
Definition: utils.hpp:83