pops-core  0.9
PoPS (Pest or Pathogen Spread) Model Core C++ library
quarantine.hpp
Go to the documentation of this file.
1 /*
2  * PoPS model - Quarantine escape computation
3  *
4  * Copyright (C) 2020 by the authors.
5  *
6  * Authors: Anna Petrasova <akratoc ncsu edu>
7  *
8  * The code contained herein is licensed under the GNU General Public
9  * License. You may obtain a copy of the GNU General Public License
10  * Version 2 or later at the following locations:
11  *
12  * http://www.opensource.org/licenses/gpl-license.html
13  * http://www.gnu.org/copyleft/gpl.html
14  */
15 
16 #ifndef POPS_QUARANTINE_HPP
17 #define POPS_QUARANTINE_HPP
18 
19 #include <tuple>
20 #include <map>
21 #include <vector>
22 #include <limits>
23 #include <type_traits>
24 #include <sstream>
25 #include <iomanip>
26 
27 #include "utils.hpp"
28 
29 namespace pops {
30 
31 std::ostream& operator<<(std::ostream& os, const Direction& obj)
32 {
33  os << static_cast<std::underlying_type<Direction>::type>(obj);
34  return os;
35 }
36 
37 typedef std::tuple<double, Direction> DistDir;
38 typedef std::tuple<bool, DistDir> EscapeDistDir;
39 typedef std::vector<EscapeDistDir> EscapeDistDirs;
40 
44 template<typename IntegerRaster, typename RasterIndex = int>
46 {
47 private:
48  RasterIndex width_;
49  RasterIndex height_;
50  // the west-east resolution of the pixel
51  double west_east_resolution_;
52  // the north-south resolution of the pixel
53  double north_south_resolution_;
54  unsigned num_steps;
55  std::vector<BBoxInt> boundaries;
56  // mapping between quarantine areas is from map and index
57  std::map<int, int> boundary_id_idx_map;
58  std::vector<EscapeDistDir> escape_dist_dirs;
59 
65  void quarantine_boundary(
66  const IntegerRaster& quarantine_areas,
67  const std::vector<std::vector<int>>& suitable_cells)
68  {
69  int n, s, e, w;
70  int idx = 0;
71  for (auto indices : suitable_cells) {
72  int i = indices[0];
73  int j = indices[1];
74  auto value = quarantine_areas(i, j);
75  if (value > 0) {
76  auto search = boundary_id_idx_map.find(value);
77  int bidx;
78  if (search == boundary_id_idx_map.end()) {
79  boundary_id_idx_map.insert(std::make_pair(value, idx));
80  boundaries.push_back(
81  std::make_tuple(height_ - 1, 0, 0, width_ - 1));
82  bidx = idx;
83  ++idx;
84  }
85  else
86  bidx = search->second;
87  std::tie(n, s, e, w) = boundaries.at(bidx);
88  if (i < n)
89  n = i;
90  if (i > s)
91  s = i;
92  if (j > e)
93  e = j;
94  if (j < w)
95  w = j;
96  boundaries.at(bidx) = std::make_tuple(n, s, e, w);
97  }
98  }
99  }
108  DistDir
109  closest_direction(RasterIndex i, RasterIndex j, const BBoxInt boundary) const
110  {
111  int n, s, e, w;
112  int mindist = std::numeric_limits<int>::max();
113  std::tie(n, s, e, w) = boundary;
114  DistDir closest;
115  if ((i - n) * north_south_resolution_ < mindist) {
116  mindist = (i - n) * north_south_resolution_;
117  closest = std::make_tuple(mindist, Direction::N);
118  }
119  if ((s - i) * north_south_resolution_ < mindist) {
120  mindist = (s - i) * north_south_resolution_;
121  closest = std::make_tuple(mindist, Direction::S);
122  }
123  if ((e - j) * west_east_resolution_ < mindist) {
124  mindist = (e - j) * west_east_resolution_;
125  closest = std::make_tuple(mindist, Direction::E);
126  }
127  if ((j - w) * west_east_resolution_ < mindist) {
128  mindist = (j - w) * west_east_resolution_;
129  closest = std::make_tuple(mindist, Direction::W);
130  }
131  return closest;
132  }
133 
134 public:
136  const IntegerRaster& quarantine_areas,
137  double ew_res,
138  double ns_res,
139  unsigned num_steps,
140  const std::vector<std::vector<int>>& suitable_cells)
141  : width_(quarantine_areas.cols()),
142  height_(quarantine_areas.rows()),
143  west_east_resolution_(ew_res),
144  north_south_resolution_(ns_res),
145  num_steps(num_steps),
146  escape_dist_dirs(
147  num_steps,
148  std::make_tuple(
149  false,
150  std::make_tuple(std::numeric_limits<double>::max(), Direction::None)))
151  {
152  quarantine_boundary(quarantine_areas, suitable_cells);
153  }
154 
155  QuarantineEscape() = delete;
156 
163  const IntegerRaster& infected,
164  const IntegerRaster& quarantine_areas,
165  unsigned step,
166  const std::vector<std::vector<int>>& suitable_cells)
167  {
168 
169  DistDir min_dist_dir =
170  std::make_tuple(std::numeric_limits<double>::max(), Direction::None);
171  for (auto indices : suitable_cells) {
172  int i = indices[0];
173  int j = indices[1];
174  if (!infected(i, j))
175  continue;
176  int area = quarantine_areas(i, j);
177  if (area == 0) {
178  escape_dist_dirs.at(step) = std::make_tuple(
179  true, std::make_tuple(std::nan(""), Direction::None));
180  return;
181  }
182  double dist;
183  Direction dir;
184  int bindex = boundary_id_idx_map[area];
185  std::tie(dist, dir) = closest_direction(i, j, boundaries.at(bindex));
186  if (dist < std::get<0>(min_dist_dir)) {
187  min_dist_dir = std::make_tuple(dist, dir);
188  }
189  }
190  escape_dist_dirs.at(step) = std::make_tuple(false, min_dist_dir);
191  }
196  const EscapeDistDir escape_info(unsigned step) const
197  {
198  return escape_dist_dirs.at(step);
199  }
200 
204  bool escaped(unsigned step) const
205  {
206  return std::get<0>(escape_dist_dirs.at(step));
207  }
208 
214  double distance(unsigned step) const
215  {
216  auto dist_dir = std::get<1>(escape_dist_dirs.at(step));
217  return std::get<0>(dist_dir);
218  }
219 
224  Direction direction(unsigned step) const
225  {
226  auto dist_dir = std::get<1>(escape_dist_dirs.at(step));
227  return std::get<1>(dist_dir);
228  }
229 };
230 
235 template<typename IntegerRaster>
237  const std::vector<QuarantineEscape<IntegerRaster>> escape_infos, unsigned step)
238 {
239  bool escape;
240  DistDir distdir;
241  int escapes = 0;
242  for (const auto& item : escape_infos) {
243  std::tie(escape, distdir) = item.escape_info(step);
244  escapes += escape;
245  }
246  return (double)escapes / escape_infos.size();
247 }
248 
255 template<typename IntegerRaster>
256 std::vector<DistDir> distance_direction_to_quarantine(
257  const std::vector<QuarantineEscape<IntegerRaster>> escape_infos, unsigned step)
258 {
259  bool escape;
260  DistDir distdir;
261  std::vector<DistDir> distances_directions;
262  for (const auto& item : escape_infos) {
263  std::tie(escape, distdir) = item.escape_info(step);
264  distances_directions.push_back(distdir);
265  }
266 
267  return distances_directions;
268 }
269 
277 template<typename IntegerRaster>
279  const std::vector<QuarantineEscape<IntegerRaster>> escape_infos, unsigned num_steps)
280 {
281  std::stringstream ss;
282  ss << std::setprecision(1) << std::fixed;
283  ss << "step,escape_probability";
284  for (unsigned i = 0; i < escape_infos.size(); i++)
285  ss << ",dist" << i << ",dir" << i;
286  ss << "\n";
287  for (unsigned step = 0; step < num_steps; step++) {
288  ss << step;
289  ss << "," << quarantine_escape_probability(escape_infos, step);
290  std::vector<DistDir> dists_dirs =
291  distance_direction_to_quarantine(escape_infos, step);
292  double dist;
293  Direction dir;
294  for (unsigned i = 0; i < dists_dirs.size(); i++) {
295  std::tie(dist, dir) = dists_dirs.at(i);
296  if (std::isnan(dist))
297  ss << ",,";
298  else
299  ss << "," << dist << "," << dir;
300  }
301  ss << "\n";
302  }
303  return ss.str();
304 }
305 } // namespace pops
306 #endif // POPS_QUARANTINE_HPP
pops::write_quarantine_escape
std::string write_quarantine_escape(const std::vector< QuarantineEscape< IntegerRaster >> escape_infos, unsigned num_steps)
Writes quarantine escape summary for all steps into a string.
Definition: quarantine.hpp:278
pops::QuarantineEscape::escape_info
const EscapeDistDir escape_info(unsigned step) const
Computes escape info (if escaped, distance and direction if not escaped) for certain action step.
Definition: quarantine.hpp:196
pops::quarantine_escape_probability
double quarantine_escape_probability(const std::vector< QuarantineEscape< IntegerRaster >> escape_infos, unsigned step)
Reports probability of escaping quarantine based on multiple runs for certain step.
Definition: quarantine.hpp:236
pops::QuarantineEscape::distance
double distance(unsigned step) const
Returns minimum distance to quarantine boundary bbox.
Definition: quarantine.hpp:214
utils.hpp
BBoxInt
std::tuple< int, int, int, int > BBoxInt
Definition: utils.hpp:61
indices
Definition: utils.hpp:97
pops::QuarantineEscape
Class storing and computing quarantine escap metrics for one simulation.
Definition: quarantine.hpp:45
Direction::W
@ W
West.
pops::QuarantineEscape::infection_escape_quarantine
void infection_escape_quarantine(const IntegerRaster &infected, const IntegerRaster &quarantine_areas, unsigned step, const std::vector< std::vector< int >> &suitable_cells)
Computes whether infection in certain step escaped from quarantine areas and if not,...
Definition: quarantine.hpp:162
pops::QuarantineEscape::QuarantineEscape
QuarantineEscape(const IntegerRaster &quarantine_areas, double ew_res, double ns_res, unsigned num_steps, const std::vector< std::vector< int >> &suitable_cells)
Definition: quarantine.hpp:135
pops::QuarantineEscape::direction
Direction direction(unsigned step) const
Returns the direction (N, S, E, W, None) of the minimum distance to quarantine boundary bbox.
Definition: quarantine.hpp:224
pops::DistDir
std::tuple< double, Direction > DistDir
Definition: quarantine.hpp:37
pops
Definition: cauchy_kernel.hpp:25
pops::QuarantineEscape::escaped
bool escaped(unsigned step) const
Returns true if infection escaped the quarantine boundary.
Definition: quarantine.hpp:204
Direction::E
@ E
East.
pops::EscapeDistDir
std::tuple< bool, DistDir > EscapeDistDir
Definition: quarantine.hpp:38
pops::QuarantineEscape::QuarantineEscape
QuarantineEscape()=delete
pops::DispersalKernelType::None
@ None
No dispersal kernel (no spread)
pops::distance_direction_to_quarantine
std::vector< DistDir > distance_direction_to_quarantine(const std::vector< QuarantineEscape< IntegerRaster >> escape_infos, unsigned step)
Reports minimum distances to quarantine boundary (bbox) and associated distances for each run for cer...
Definition: quarantine.hpp:256
Direction::N
@ N
North.
pops::EscapeDistDirs
std::vector< EscapeDistDir > EscapeDistDirs
Definition: quarantine.hpp:39
pops::operator<<
std::ostream & operator<<(std::ostream &os, const Date &d)
Definition: date.hpp:109
Direction::None
@ None
No direction (non-directional)
Direction::S
@ S
South.
Direction
Direction
Spread direction.
Definition: utils.hpp:83