@@ -55,6 +55,31 @@ std::vector<int> draw_n_from_v(std::vector<int> v, unsigned n, Generator& genera
5555 return v;
5656}
5757
58+ /* * Draws n elements from a cohort of rasters. Expects n to be equal or less than
59+ * sum of cohorts at cell (i, j).
60+ */
61+ template <typename Generator, typename IntegerRaster, typename RasterIndex = int >
62+ std::vector<int > draw_n_from_cohorts (
63+ std::vector<IntegerRaster>& cohorts,
64+ int n,
65+ RasterIndex row,
66+ RasterIndex col,
67+ Generator& generator)
68+ {
69+ std::vector<int > categories;
70+ unsigned index = 0 ;
71+ for (auto & raster : cohorts) {
72+ categories.insert (categories.end (), raster (row, col), index);
73+ index += 1 ;
74+ }
75+ std::vector<int > draw = draw_n_from_v (categories, n, generator);
76+ std::vector<int > cohort_counts;
77+ for (index = 0 ; index < cohorts.size (); index++) {
78+ cohort_counts.push_back (std::count (draw.begin (), draw.end (), index));
79+ }
80+ return cohort_counts;
81+ }
82+
5883/* * The type of a epidemiological model (SI or SEI)
5984 */
6085enum class ModelType
@@ -207,6 +232,67 @@ class Simulation
207232 }
208233 }
209234
235+ /* * Removes percentage of exposed and infected
236+ *
237+ * @param infected Currently infected hosts
238+ * @param susceptible Currently susceptible hosts
239+ * @param mortality_tracker_vector Hosts that are infected at a specific time step
240+ * @param exposed Exposed hosts per cohort
241+ * @param total_exposed Total exposed in all exposed cohorts
242+ * @param survival_rate Raster between 0 and 1 representing pest survival rate
243+ * @param suitable_cells used to run model only where host are known to occur
244+ */
245+ void remove_percentage (
246+ IntegerRaster& infected,
247+ IntegerRaster& susceptible,
248+ std::vector<IntegerRaster>& mortality_tracker_vector,
249+ std::vector<IntegerRaster>& exposed,
250+ IntegerRaster& total_exposed,
251+ const FloatRaster& survival_rate,
252+ const std::vector<std::vector<int >>& suitable_cells)
253+ {
254+ for (auto indices : suitable_cells) {
255+ int i = indices[0 ];
256+ int j = indices[1 ];
257+ if (survival_rate (i, j) < 1 ) {
258+ int removed = 0 ;
259+ // remove percentage of infestation/infection in the infected class
260+ int removed_infected =
261+ infected (i, j) - std::lround (infected (i, j) * survival_rate (i, j));
262+ infected (i, j) -= removed_infected;
263+ removed += removed_infected;
264+ // remove the removed infected from mortality cohorts
265+ if (removed_infected > 0 ) {
266+ std::vector<int > mortality_draw = draw_n_from_cohorts (
267+ mortality_tracker_vector, removed_infected, i, j, generator_);
268+ int index = 0 ;
269+ for (auto & raster : mortality_tracker_vector) {
270+ raster (i, j) -= mortality_draw[index];
271+ index += 1 ;
272+ }
273+ }
274+ // remove the same percentage for total exposed and remove randomly from
275+ // each cohort
276+ int total_removed_exposed =
277+ total_exposed (i, j)
278+ - std::lround (total_exposed (i, j) * survival_rate (i, j));
279+ total_exposed (i, j) -= total_removed_exposed;
280+ removed += total_removed_exposed;
281+ if (total_removed_exposed > 0 ) {
282+ std::vector<int > exposed_draw = draw_n_from_cohorts (
283+ exposed, total_removed_exposed, i, j, generator_);
284+ int index = 0 ;
285+ for (auto & raster : exposed) {
286+ raster (i, j) -= exposed_draw[index];
287+ index += 1 ;
288+ }
289+ }
290+ // move infested/infected host back to susceptible pool
291+ susceptible (i, j) += removed;
292+ }
293+ }
294+ }
295+
210296 /* * kills infected hosts based on mortality rate and timing. In the last year
211297 * of mortality tracking the first index all remaining tracked infected hosts
212298 * are removed. In indexes that are in the mortality_time_lag no mortality occurs.
@@ -347,43 +433,26 @@ class Simulation
347433 resistant_moved = std::count (draw.begin (), draw.end (), 4 );
348434
349435 if (exposed_moved > 0 ) {
436+ std::vector<int > exposed_draw = draw_n_from_cohorts (
437+ exposed, exposed_moved, row_from, col_from, generator_);
350438 int index = 0 ;
351439 for (auto & raster : exposed) {
352- auto exposed_count = raster (row_from, col_from);
353- exposed_categories.insert (
354- exposed_categories.end (), exposed_count, index);
355-
356- index += 1 ;
357- }
358- std::vector<int > exposed_draw =
359- draw_n_from_v (exposed_categories, exposed_moved, generator_);
360- index = 0 ;
361- for (auto & raster : exposed) {
362- auto exposed_moved_in_cohort =
363- std::count (exposed_draw.begin (), exposed_draw.end (), index);
364- raster (row_from, col_from) -= exposed_moved_in_cohort;
365- raster (row_to, col_to) += exposed_moved_in_cohort;
440+ raster (row_from, col_from) -= exposed_draw[index];
441+ raster (row_to, col_to) += exposed_draw[index];
366442 index += 1 ;
367443 }
368444 }
369-
370445 if (infected_moved > 0 ) {
371- std::vector<int > mortality_categories;
446+ std::vector<int > mortality_draw = draw_n_from_cohorts (
447+ mortality_tracker_vector,
448+ infected_moved,
449+ row_from,
450+ col_from,
451+ generator_);
372452 int index = 0 ;
373453 for (auto & raster : mortality_tracker_vector) {
374- auto mortality_count = raster (row_from, col_from);
375- mortality_categories.insert (
376- mortality_categories.end (), mortality_count, index);
377- index += 1 ;
378- }
379- std::vector<int > mortality_draw =
380- draw_n_from_v (mortality_categories, infected_moved, generator_);
381- index = 0 ;
382- for (auto & raster : mortality_tracker_vector) {
383- auto mortality_moved_in_cohort =
384- std::count (mortality_draw.begin (), mortality_draw.end (), index);
385- raster (row_from, col_from) -= mortality_moved_in_cohort;
386- raster (row_to, col_to) += mortality_moved_in_cohort;
454+ raster (row_from, col_from) -= mortality_draw[index];
455+ raster (row_to, col_to) += mortality_draw[index];
387456 index += 1 ;
388457 }
389458 }
0 commit comments