paleopop
is part of the poemsverse. poems
is a spatially-explicit,
process-explicit, pattern-oriented framework for modeling population
dynamics. This extension adds functionality for modeling large
populations at generational time-steps over paleontological time-scales.
You can install the latest release of paleopop
from CRAN with:
install.packages("paleopop")
#> Installing package into '/home/runner/work/_temp/Library'
#> (as 'lib' is unspecified)
You can install the development version from GitHub with:
# install.packages("devtools")
devtools::install_github("GlobalEcologyLab/paleopop")
poems
and paleopop
are based on
R6
class objects. R is primarily a functional programming language; if
you want to simulate a population, you might use the lapply
or
replicate
functions to repeat a generative function like rnorm
. R6
creates an object-oriented programming language inside of R, so
instead of using functions on other functions, in these packages we
simulate populations using methods attached to objects. Think of R6
objects like machines, and methods like switches you can flip on the
machines.
One of the major additions in paleopop
is the PaleoRegion
R6 class,
which allows for regions that change over time due to ice sheets, sea
level, bathymetry, and so on. The plots below show the temporal mask
functionality of the PaleoRegion
object. The temporal mask indicates
cells that are occupiable at each time step with a 1 and unoccupiable
cells with a NA
. In this example, I use the temporal_mask_raster
method to show how “Ring Island” changes at time step 10 due to a drop
in sea level.
library(poems)
library(paleopop)
coordinates <- data.frame(x = rep(seq(-178.02, -178.06, -0.01), 5),
y = rep(seq(19.02, 19.06, 0.01), each = 5),
z = rep(1, 25))
template_raster <- raster::rasterFromXYZ(coordinates,
crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
sealevel_raster <- template_raster
template_raster[][c(7:9, 12:14, 17:19)] <- NA # make Ring Island
sealevel_raster[][c(7:9, 12:14, 17:18)] <- NA
raster_stack <- raster::stack(x = append(replicate(9, template_raster), sealevel_raster))
region <- PaleoRegion$new(template_raster = raster_stack)
raster::plot(region$temporal_mask_raster()[[1]], main = "Ring Island (first timestep)",
xlab = "Longitude (degrees)", ylab = "Latitude (degrees)",
colNA = "blue")
raster::plot(region$temporal_mask_raster()[[10]], main = "Ring Island (last timestep)",
xlab = "Longitude (degrees)", ylab = "Latitude (degrees)",
colNA = "blue")
paleopop
also includes the PaleoPopModel
class, which sets up the
population model structure. Here I show a very minimalist setup of a
model template using this class.
model_template <- PaleoPopModel$new(
region = region, # makes the simulation spatially explicit
time_steps = 10, # number of time steps to simulate
years_per_step = 12, # years per generational time-step
standard_deviation = 0.1, # SD of growth rate
growth_rate_max = 0.6, # maximum growth rate
harvest = F, # are the populations harvested?
populations = 17, # total occupiable cells over time
initial_abundance = seq(9000, 0, -1000), # initial pop. sizes
transition_rate = 1.0, # transition rate between generations
carrying_capacity = rep(1000, 17), # static carrying capacity
dispersal = (!diag(nrow = 17, ncol = 17))*0.05, # dispersal rates
density_dependence = "logistic", # type of density dependence
dispersal_target_k = 10, # minimum carrying capacity to attract dispersers
occupancy_threshold = 1, # lower than this # of pops. means extinction
abundance_threshold = 10, # threshold for Allee effect
results_selection = c("abundance") # what outputs do you want in results?
)
The paleopop_simulator
function accepts a PaleoPopModel object or a
named list as input to simulate populations over paleo time scales, and
the PaleoPopResults
class stores the outputs from the paleo population
simulator.
results <- paleopop_simulator(model_template)
results # examine
#> $abundance
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 88 150 258 403 606 902 1049 962 1096 1400
#> [2,] 330 563 733 794 701 781 786 865 964 1104
#> [3,] 1199 1104 991 1087 1257 1062 998 1016 1025 1055
#> [4,] 306 465 655 681 954 959 955 934 1008 813
#> [5,] 101 150 248 369 488 674 826 973 1048 1038
#> [6,] 336 468 639 687 840 929 972 957 1028 991
#> [7,] 575 634 888 929 970 907 912 1022 1058 905
#> [8,] 1123 1086 1140 1215 1140 836 955 934 938 826
#> [9,] 961 834 908 947 1045 980 964 958 1070 904
#> [10,] 0 0 0 0 0 0 0 0 0 0
#> [11,] 0 0 0 0 0 0 0 0 0 0
#> [12,] 0 0 0 0 0 0 0 0 0 0
#> [13,] 497 666 912 1033 997 972 1023 924 923 929
#> [14,] 64 92 180 258 450 552 761 1039 990 1067
#> [15,] 595 720 881 779 1016 984 933 973 1156 1091
#> [16,] 452 742 850 931 950 1050 1017 1093 1007 1046
#> [17,] 1182 1017 1151 1119 904 689 854 904 890 958
raster::plot(region$raster_from_values(results$abundance[,10]),
main = "Final abundance", xlab = "Longitude (degrees)",
ylab = "Latitude (degrees)", colNA = "blue")
A practical example of how to use paleopop
, with more complex
parameterization, can be found in the vignette.
You may cite paleopop
in publications using our software paper in
Global Ecology and Biogeography:
Pilowsky, J. A., Haythorne, S., Brown, S. C., Krapp, M., Armstrong, E., Brook, B. W., Rahbek, C., & Fordham, D. A. (2022). Range and extinction dynamics of the steppe bison in Siberia: A pattern‐oriented modelling approach. Global Ecology and Biogeography, 31(12), 2483-2497.