Keywords
deterministic, stochastic, vector, population, model, age-specific, survival, development, dynamic, difference equations, C, Python, R
deterministic, stochastic, vector, population, model, age-specific, survival, development, dynamic, difference equations, C, Python, R
This version of the manuscript is prepared in response to the comments and suggestions of the reviewers. We have:
See the author's detailed response to the review by Matthew Silk
Heterogeneity is inherent in most naturally occurring populations. Individuals possess or attain in time certain characteristics, which could result in differences in behaviour or response to stimuli. Time-dependent heterogeneity may result in the stratification of a population into chronological units. This could introduce time delays to certain processes and might have a strong non-linear impact on dynamics1.
For instance, distinct physiological stages emerge during insect development where each stage reacts differently to environmental factors such as temperature2. In addition, the minimum incubation period of an infection requires time delays, which is often ignored in canonical modelling approaches3. Time-dependent heterogeneity is ubiquitous in many areas including biomedical, engineering, and social sciences4. The analysis of lifetime data4, the degree day methodology5, and age- or stage-structured population dynamics modelling6 are common approaches for investigating such phenomena.
Incorporating age dependency in mathematical models can be challenging due to the need to keep track of the age of each individual in a population. A common work-around is to introduce predetermined intermittent stages to account for the different characteristics of each stage and the time it takes to pass from one to another. This approach has been extensively used in various contexts, e.g. to model animal development7, insect life cycle8,9, disease transmission10,11, and economic surplus12. Although intermittent stages are capable of representing age-structured populations to a certain extent, a large number of age classes are required for accuracy. Consequently, model development becomes a non-trivial task.
Numerous packages including popbio13, demogR14, and bayesPop15 have been implemented to facilitate modelling and analysis of age- and stage-structured projection matrix models. As a viable alternative, Kettle and Nutter implemented an R package for agestructured population dynamics, StagePop, which offers true time delays in continuous time domain using deterministic delay differential equations16.
Here, I present an alternative age-structured population dynamics model based on the population dynamics and disease-transmission models described in Erguler et al. 201617 and 201718. The approach involves automatically classifying a population into distinct age and development groups and applying a projection matrix to derive the next state. In its current form, the model is based on discrete-time difference equations. Three implementations of the model exists (the sPop packages) for three programming languages, C, Python, and R. The sPop packages provide a flexible number of age and development categories, include both deterministic and stochastic dynamics, and offer high-speed simulations to facilitate parameter inference.
The following section describes the theory behind the model and presents the use of each implementation with a commonly encountered case. The same case is modelled with each sPop package to emphasise the nuances in their usage. The Temporal resolution and accuracy section investigates the accuracy of numerical simulations with regards to different time step sizes. The Use cases section concludes with the sPop implementations of a short list of well-known mathematical models selected from a range of disciplines.
The sPop packages help to incorporate age-structured populations in discrete-time deterministic and stochastic difference equations models. The population is assumed to be in the same (heterogeneous) state shared by all individuals. Two processes determine the length of stay in this state: survival (𝒮) and development (𝒟). These processes are assumed to act in a sequential manner, where development proceeds only if survival is guaranteed for the duration of an iteration, ᴛ. Survival and development may (i) progress at a fixed propensity, (ii) delay for a given number of iterations, (iii) follow a gamma-distributed (or negative binomial-distributed) life-time, or (iv) halt for a given time period. Here, I adopt the term propensity to refer to either the rate of a deterministic process or the probability of a stochastic one.
The earlier version of the age-structured population dynamics model17 follows the degree day approach and represents progress with a physiological development unit accumulating at each iteration. The rate of accumulation can be fixed or variable in response to external or internal factors. When the value of this indicator exceeds a predefined threshold, the corresponding individuals are removed from the population (the process of survival or development is complete for them). The more recent version of the model18 employs propensity, which can be seen as the probability (or rate) of the indicator exceeding the threshold at each iteration. Exchanging the indicator with propensity aids the development of both deterministic and stochastic models with variable state duration, and is the preferred approach for the implementation of the sPop packages.
According to the model, age and development are the two counters of elapsed time, one of which (development) iterates a third counter (development cycle) on completion. Human pregnancy can be given as an analogy; a woman’s age would be tα and the stage of her pregnancy would be tδ. The population would then be comprised of a group of women in different stages of pregnancy. It is important to note that, since age and development progress in synchrony, their time units should be the same, e.g. month or day. In this analogy, birth would be triggered by tδ, which, in turn, would iterate tπ, which could be seen as the number of births each mother has given.
Although age and development advance at the same pace, progress is assessed by each counter approaching the completion of survival or development. Propensity can be assumed constant, or it can be derived from the duration of survival or development. The duration of each process can be defined as a user-supplied function, which may depend on age (tα), number of completed development cycles (tπ), the degree of completion of the present development cycle (tδ), or any other environmental factors.
Each individual is allowed to stay in the population given that neither death (𝒳 where Pr(𝒳) = 1−Pr(𝒮)) nor development occurs during an iteration. In a deterministic setup, a given fraction of the population will die (r𝒳) or survive and complete development (r𝒟) every ᴛ. In a stochastic setup, the number of individuals to die or develop is chosen from a binomial distribution, ℬ (n, p), where p is the daily probability of death (p𝒳) or development (p𝒟) and n is the size of the population. In most experimental setups, development is observed on the condition that individuals survive; therefore, this condition is implicit in the definition of development propensity, i.e. p𝒟 = Pr(D|S) per individual per ᴛ.
At each iteration, tα and tδ are incrementally adjusted to keep track of the age and the degree of development, respectively, for each individual. When a batch of individuals complete development, the indicator tπ is adjusted, tδ is reset to zero, and the batch is removed from the population. When modelling periodic development processes, such as the gonotrophic cycle or human pregnancy, the batch can be reintroduced to the population for the subsequent cycle of development.
When propensity is fixed for either 𝒳 or 𝒟, the time required for the completion of life or development follows a geometric distribution where the size of the population (n) can be described with
for the deterministic case, or with
for the stochastic case, where n0 is a user-defined initial condition.
We assumed that the survival and development processes are driven by two counters: (i) age, tα, and (ii) the degree of development, tδ. Age affects survival and the degree of development determines if development has been completed. The duration of each process can be a fixed number of iterations or can be described by a discrete negative binomial distribution or a continuous gamma distribution. In case of a negative binomial or gamma distribution, the daily propensity of death or development can be calculated as the ratio of the probability that the process is completed between iteration ᴛd and ᴛd+1 to the total probability of surviving or developing for at least ᴛd days. For instance, the daily probability of death in a stochastic setup can be written as
where x represents the iteration when death occurs, and F(·) is the cumulative distribution function of either the negative binomial distribution or the gamma distribution. The parameters of each distribution are determined from the desired mean (µ) and standard deviation (σ) of the number of iterations to complete the process. An advantage of the gamma distribution over the negative binomial is its flexibility in accommodating various combinations of mean and standard deviation. However, the negative binomial distribution is restrictive over the minimum allowed standard deviation for a given mean.
The R implementation of sPop is available on CRAN as the albopictus package (v.0.5) and on the GitHub repository https://doi.org/10.5281/ zenodo.1685054. The C and Python implementations are available as part of the albopictus package (v.1.11.0) on PyPI and the GitHub repository https://doi.org/10.5281/zenodo.1685289. The packages are implemented for R version 3.5.1 and Python version 3.7.0.
This section is reserved for outlining the use of each implementation to model the same theoretical population where both development and survival are age-dependent and gamma-distributed. In addition, the population exhibits a periodic development process with a mean duration of 50 hours and a standard deviation of 10 hours, and survival is a function of the number of development cycles,
Before we begin modelling, we load the albopictus package in R, and define the survival function as described in Equation 1.
R > library(albopictus)
R >
R > death <- function(pop) {
R + if (nrow(pop)==0)
R + return(data.frame(mean=480, sd=48.0))
R + mn <- 480.0 - (48.0 * pop$devcycle)
R + mn[mn < 240.0] <- 240.0
R + return(data.frame(mean=mn, sd=0.1*mn))
R + }
The function returns a data.frame with a desired mean and standard deviation. Next, we initiate a population by calling the initiation routine of the spop class.
R > vec <- spop(stochastic=TRUE, prob="gamma")
With this line, we construct a stochastic population model with the gamma distribution as the basis of survival and development. Setting prob to nbinom selects the negative binomial distribution instead.
In order to introduce the first batch of individuals, we use the add method.
R > add(vec) <- data.frame(number=1000)
By default, age, development cycle, and the duration of development will be set to zero for all individuals. These can be customised by supplying additional fields to the data.frame: age to set age, devcycle to set the number of development cycles, and development to set the number of iterations the current development cycle has taken.
We can directly access the population structure of the spop class to inspect the number of individuals grouped with respect to age, development cycle, and the degree of development. Here, we will use these information to calculate the mean and standard deviation of expected lifetime for each age-development group.
R > tmp <- death(vec@pop)
The following step iterates the population for one time-unit by using the iterate method.
R > iterate(vec) <- data.frame(dev_mean = 50,
R + dev_sd = 10,
R + death_mean = tmp$mean,
R + death_sd = tmp$sd)
By defining dev_mean and dev_sd, we opt to use the gamma distribution to describe the probability of development. Setting dev_sd to zero results in the gamma distribution being discarded and a fixed number of iterations (indicated by dev_mean) being assigned for development. Instead, setting dev instead of dev_mean and dev_sd results in a daily constant development probability. The same principles apply for the survival process, where we provide the mean and the standard deviation of the gamma-distribution for each age- development group as calculated by the death function. After each iteration, the age and degree of development of the population are updated and the total number of individuals completing development is recorded together with the detailed account of the corresponding age-development groups. We access these data using the developed and devtable methods, respectively. In addition, the dead method returns the number of dead individuals following an iteration.
R > d <- developed(vec)
R > add(vec) <- devtable(vec)
In this example, we assume a periodic development process; therefore, we introduce all the individuals completing development back to the population using the add method.
Finally, we read the total size of the population using the size method.
R > s <- size(vec)
In the R implementation, we also provide an accessory method, perturb, to perform the same functions as the iterate method without updating age or development. By using perturb, the structure and size of a population can be modified to model the impact of an intervention or migration. The effect is immediate and in addition to the continuing survival and development processes. For instance, perturb can be used to model population control. If a certain agent kills a fraction of a population upon delivery, perturb can be used by specifying death to remove the affected individuals from the population. Otherwise, if the effect is age-dependent, death.mean and death.sd can be specified to calculate the fraction to be removed. If there is a need to migrate a subset of a population (population A) to a different population (population B), perturb can be used by specifying an appropriate development process (dev for age-independent, dev.mean and dev.sd for age-dependent migration). This results in keeping a detailed record of the age and stage of development of the individuals removed from population A. Essentially, this is the list of individuals selected for migration, and it can be used as desired. A simple example of migration is given below.
R > A <- spop(stochastic=FALSE, prob="gamma")
R > B <- spop(stochastic=FALSE, prob="gamma")
R > add(A) <- data.frame(number=1000)
R > perturb(A) <- data.frame(dev=0.5, death=0)
R > add(B) <- devtable(A)
The above code results in the migration of 500 individuals from population A to B while freezing the age, development cycle, and development counters.
The Python implementation of the population dynamics model can be imported from the albopictus package.
Python >>> from albopictus.population import spop
We begin by declaring the survival function as in Equation 1.
Python >>> def death(pop):
Python ... if pop.shape[1]==0:
Python ... return [480.0, 48.0]
Python ... mn = 480.0 - 48.0 * pop[:,1]
Python ... mn[mn < 240.0] = 240.0
Python ... return [mn, 0.1*mn]
Unlike the R implementation, the population structure is stored in a numpy.ndarray with the following order of columns: age, development cycle, degree of development, and number. Although the initiation step is similar to the R implementation, a two-dimensional list or a numpy.ndarray should be supplied to intriduce batches of individuals to a population.
Python >>> vec = spop(stochastic=True,prob="gamma")
Python >>> vec.add( [ [0, 0, 0, 1000] ] )
By using the add method above, we introduce 1000 individuals with zero age, development cycle, and degree of development. The population structure is directly accessible, which enables us to calculate a different mean and standard deviation for the gamma-distributed development of each age-development group.
Python >>> tmp = death(vec.pop)
Next, we iterate the population for one time-unit using the iterate method.
Python >>> vec.iterate(dev_mean = 50,
Python ... dev_sd = 10,
Python ... death_mean = tmp[0],
Python ... death_sd = tmp[1])
In order to read the total number of individuals completing development, the detailed account of the corresponding age-development groups, and the total size of the population, we access the developed, devtable, and size attributes of the spop class. Please note that these attributes are overwritten each time the iterate method is called. Here, we record the total number of developed individuals and the population size, and reintroduce the developed individuals to the population for the next round of development.
Python >>> d = vec.developed
Python >>> vec.add(vec.devtable)
Python >>> s = vec.size
The Python implementation of the iterate method accepts an additional logical indicator pause to prevent updating age and development. If this parameter is supplied and if it is false, the iterate method acts as the perturb method of the R implementation.
The C implementation of the sPop package is further optimised for speed. The source code resides in the albopictus package of Python, and it needs to be compiled with the GNU Scientific Library (version 2.1 or later). We begin by locating the package directory and compiling three source files into the object code. Assuming that the file name of our model is test_spop.c, we produce the executable with the following.
$ gcc -c -o ran_gen.o ${pkgdir}/ran_gen.c
$ gcc -c -o gamma.o ${pkgdir}/gamma.c
$ gcc -c -o spop.o ${pkgdir}/spop.c
$ gcc -I${pkgdir} -lgsl -o test_spop ran_gen.o
gamma.o spop.o test_spop.c
where $pkgdir is a bash variable holding the package directory. In order to use the package, we need to include the following header files in test_spop.c.
C #include "ran_gen.h"
C #include "gamma.h"
C #include "spop.h"
The first header file defines the routines required for random number generation, and the second one defines the routines for the gamma and negative binomial distributions. The last header file defines the spop population structure and the associated functions for initialisation, modification, and garbage collection.
Each age-development group is stored in the individual_st data structure,
C typedef struct individual_st {
C unsigned int age;
C unsigned int devcycle;
C unsigned int development;
C sdnum number;
C } individual_data;
where the age, development cycle, degree of development, and the number of individuals in each age-development group are stored in age, devcycle, development, and number variables in the same order. The sdnum is a union data structure holding an unsigned int for a stochastic population or a double for a deterministic population. The spop data structure holds an array of individuals (individuals), population size (size), the number of dead and developed individuals following an iteration (dead and developed, respectively), a detailed account of developed individuals (devtable), an indicator for the probability distribution of age dependence (gamma_mode), a logical indicator for a stochastic or a deterministic model (stochastic), and two counters to manage the dynamic size of individuals (ncat and cat).
C typedef struct population_st {
C individual_data *individuals;
C sdnum size;
C sdnum dead;
C sdnum developed;
C void *devtable;
C unsigned char gamma_mode;
C unsigned char stochastic;
C unsigned int ncat;
C unsigned int cat;
C } *spop;
Following the procedure in previous sections, we begin implementing the model in test_spop.c by declaring the survival function in Equation 1.
C void death(const individual_data *ind,
C double *death_prob,
C double *death_mean,
C double *death_sd) {
C (*death_prob) = 0;
C (*death_mean) = 480.0 - (ind->devcycle > 4 ?
240.0 : 48.0 * ind->devcycle);
C (*death_sd) = 0.1 * (*death_mean);
C }
Please note that the C implementation handles a single age-development group at a time; therefore, the survival function is redesigned accordingly.
Next, we initiate a stochastic model with the gamma distribution as the basis of survival and development using the spop_init function with the first parameter set to a logical true.
C vec = spop_init(1,MODE_GAMMA_HASH);
The macro MODE_GAMMA_HASH refers to the optimised implementation of the gamma distribution. Alternatively, MODE_NBINOM_RAW and MODE_GAMMA_RAW refer to the unoptimised implementations of the negative binomial and the gamma distributions. Optimisation involves recording previously-used values in a hash table for reuse, however, is memory intensive and should be used with caution. Faster more efficient implementations of the probability distributions are the main concern for future releases.
Having initiated vec, we introduce 1000 individuals of zero age with the spop_add function.
C spop_add(vec,0,0,0,1000);
spop_add accepts parameters in the following order:
1. spop s: the spop data structure
2. unsigned int age: the age of individuals
3. unsigned int devcycle: the number of development cycles passed
4. unsigned int development: the degree of development of individuals
5. sdnum number: the number of individuals (unsigned int or double)
In order to iterate the population for one time interval, we use the spop_iterate function.
C spop_iterate(vec,
C 0,
C 50.0, 10.0,
C 0,
C 0,
C 0, 0,
C death,
C 0);
spop_iterate accepts the following parameters in the given order:
1. spop s: the spop data structure
2. double dev_prob: fixed daily development probability (priority over the other development-related parameters)
3. double dev_mean: mean development time (gamma or negative binomial)
4. double dev_sd: standard deviation of the development time
5. iter_func dev_fun: development function (similar to the death function above)
6. double death_prob: fixed daily death probability (priority over the other survival-related parameters)
7. double death_mean: mean time of death (gamma or negative binomial)
8. double death_sd: standard deviation of the time of death
9. iter_func death_fun: survival function
10. unsigned char pause: logical indicator to prevent updating age and development
Following each iteration, the list of age-development groups that completed their development is stored in the devtable variable of the spop data structure. In order to reintroduce these individuals back to the population, we use the spop_popadd function.
C spop_popadd(vec,vec->devtable);
It is possible to obtain a summary output of the population structure by using the spop_print function, which takes the spop data structure as the only parameter. spop can be recycled by emptying its contents with the spop_empty function.
C spop_empty(vec);
Finally, in order to clear the memory used by vec, we supply its address to the spop_destroy function.
C spop_destroy(&vec);
All three implementations of the model are given in Supplementary File 1–Supplementary File 3 (test_spop.R, test_spop.py, and test_spop.c. The resulting distribution of the number of individuals completing a development cycle during the first 20 days of simulation is given in Figure 1.
Five cycles of development are clearly seen from the figure, while the population survives for less than 15 days with the survival function defined in Equation 1. Blending of development cycles is apparent and progressive due to the uncertainty in the duration of development (50 hours on average with a standard deviation of 10 hours).
In the previous section, we simulated a hypothetical age-structured population using 1-hour time steps. Here, we investigate the effect of time step size to the accuracy of simulations by using a simplified version of this model. We focus on the deterministic version and assume that the default development duration is 10 (±2) days and the lifetime is 50 (±10) days. We define a scaling factor α to tune step size between days and hours. The resulting Python code for the iteration of this population (named vec) is given below.
Python >>> vec.iterate(dev_mean = 10* alpha,
Python ... dev_sd = 2*alpha,
Python ... death_mean = 50*alpha,
Python ... death_sd = 10*alpha)
In addition, we let α scale the number of iterations, which is by default 50. Consequently, when α = 1, the average lifetime is 50 and the simulation runs for 50 iterations each corresponding to 1 day. When α = 24, the average lifetime becomes 1200 and the number of iterations also becomes 1200, which implies that each iteration corresponds to 1 hour. It is straightforward to have intermediary time steps. For instance, α = 2 and α = 4 yield half-day and quarter-day iterations, respectively.
We demonstrate the effect of four time step sizes on the number of individuals completing a development cycle in Figure 2. The model yields oscillations fading in amplitude similar to the original model (Figure 1). Although the peak height decreases, the cumulative number of developed individuals agree well in each case. In the inset of Figure 2, we show that the overall numerical error increases linearly with increasing time step size.
This section describes how the Python implementation of sPop can be used to model some of the well-known population dynamics models. These models can also be constructed in R and C by following the guidelines presented in the previous section.
We begin with Nicholson’s Blowflies, a classic example of time-delayed stage-structured population model16,19. The model comprises five distinct life-stages and exhibits stable quasi-cyclic oscillations. Although, originally the model was constructed using continuous time-delay equations, we will demonstrate that the sPop model adheres well to the observed dynamics and the implementation presented in the StagePop package16. Furthermore, we will present a stochastic version of the model, which helps to improve our understanding of the observed variation.
Both the deterministic and stochastic versions of the model are presented in Supplementary File 4 (case_studies.py). The adaptation assumes fixed daily survival and strict development durations, values of which are the same as the original model (Figure 2 in Gurney et al. 198319). A scaling factor is introduced to calculate hourly instead of daily propensities to improve accuracy on a par with the continuous-time simulations.
As a result, the output of the model is almost identical to the output of the original model (compare Figure 3(a) with the Figure 3a of Gurney et al. 198319). The six peaks shown between generations 100 and 300 are matched by the stochastic version of the model (Figure3(b)). Evidently, the highest variability in stochastic simulations is in peak amplitude, whereas the frequency of the oscillations is well conserved. During each peak, two sub-peaks are observed, which are separated by a trough. The heights of each peak and trough largely vary suggesting that the two peaks may not be resolved in the observations of natural populations. Nevertheless, similar fluctuations were observed in the laboratory culture of the Australian sheep blowfly reported in Nicholson 195420 (also presented in Gurney et al. 198319 Figure 1).
Another classic example of age dependency in population dynamics was proposed by 21 as a variation of the host-parasite interaction model of 22. The Nicholson-Bailey model considers dynamics in discrete generations where parasites traverse a given area in search of a host. As a result, the number of parasites in the subsequent generation corresponds to the number of hosts parasitised. Hastings used this model for prey-predator interactions where he represented preys as hosts and predators as parasites. He introduced age-structure to the prey population and assumed that only juvenile preys are targeted by predators. Following Hastings, we use the terms host and parasite as analogous to prey and predator, respectively, regarding the emerging dynamics.
Both the original Nicholson-Bailey model and its age-structured version are implemented in Supplementary File 4 (case_studies.py). As shown in Figure 4(a), the original model without age dependency (dashed lines) exhibits oscillations with increasing amplitude around an unstable steady state. The model output matches Figure 10 in Nicholson (1935)22. Introducing age-structure with a fixed survival rate for host results in the stabilisation of dynamics as reported by Hastings (1984)21 and seen in Figure 4(a) (solid lines).
Hastings (1984)21 also discusses the disruptive effect of age-dependent host survival in stability. This is evident in Figure 4(b), where the survival imbalance between young and old individuals drives the dynamics away from the steady state, eventually rendering it unstable. When the age-dependent mortality curve is close to being horizontal, the dynamics closely resemble the Hastings’ model with no age limit (solid lines in Figure 4(a) and the dashed line in Figure 4(b)). When mortality is considerably higher in older individuals (green line in Figure 4(b)) or a strict age limit is introduced (orange line in Figure 4(b)), the stability is lost and the amplitude of oscillations increase in time.
The final case we study is the severe outbreak of bubonic plague in Eyam (Sheffield, UK) in 1665–166623. The outbreak was initially modelled by Raggett et al. 198223, and later, a simple deterministic susceptible-infectious-removed (SIR) epidemic model was developed by Brauer et al. 200124 to study the outbreak.
Although canonical SIR models are not age-structured, the underlying transmission dynamics is intricately time-dependent. This becomes clear when, for instance, the (intrinsic) incubation period is observed to be strictly more than a couple of days but not less. While a system of ordinary differential (or difference) equations describes an uninterrupted flow between the incubation period and the infectious state, the sPop age-structured model is able to track the length of the incubation period for each individual and trigger state change only for the right individuals at the right times.
An age-structured version of the SIR epidemic model where the infectious stage duration is modelled with a gamma distribution is presented in Supplementary File 4 (case_studies.py). As shown in Figure 5, the number of infectious cases with respect to the number of susceptible individuals, the S-I plane, (Figure 5(a)) and the time trajectory of the outbreak (Figure 5(b)) closely follow the data presented in Brauer et al. 200124 Table 9.1.
Figure 6 demonstrates the effect of age-structure on outbreak dynamics by comparing model output with different characteristics of the infectious period. The blue lines indicate the trajectory matching the Great Plague in Eyam. Please note that the corresponding infectious period is only slightly time-dependent where there is a minor difference between the mortalities of newly infected and long-time infectious individuals (plotted in the inset). If the rate of exit from the infectious stage is completely independent from the duration spent in the stage (as is the case with canonical SIR models), the outbreak duration increases (the green lines). In the opposite scenario, where the length of the infectious case is precise, the entire outbreak resolves rapidly as seen in the orange trajectory. Since time-dependence has a significant impact on outbreak trajectory, using realistic mathematical formulations to infer outbreak parameters, such as the incubation period and the rate of infection, becomes a critical step in developing predictive epidemic models.
The sPop packages are designed to incorporate age dependence in discrete-time population dynamics models. The underlying model incorporates survival, development, and migration processes, and it can accommodate both deterministic and stochastic dynamics. In order to promote applications, three versions of the model were implemented: the R and Python implementations are aimed at educational and introductory level use, while the C implementation offers further optimisation and high-speed simulations. This paper demonstrated that the model is capable of representing age-structured population dynamics from a range of disciplines including insect populations, host-parasite/prey-predator interactions, and infectious disease epidemiology. Future research concerns optimising to limit simulation times and implementing the model in continuous time domain for improved accuracy.
R implementation of sPop:
Available from: https://cran.r-project.org/web/packages/albopictus/
Source code: http://github.com/kerguler/albopictusR
Archived source code as at time of publication: https://doi.org/10.5281/zenodo.168505425
License: GPLv3
C and Python implementation of sPop:
Available from: https://pypi.org/project/albopictus/
Source code: https://github.com/kerguler/albopictus
Archived source code as at time of publication: https://doi.org/10.5281/zenodo.168528926
License: GPLv3
All data and source code for running the examples and plotting the figures in this manuscript are provided in the Supplementary Material:
test_spop.R: R script file for Section Implementation:R.
test_spop.py: Python script file for Section Implementation:Python.
test_spop.c: C code file for Section Implementation:C.
plot_test_spop.R: R script file for plotting Figure 1.
case_studies.py: Python script file for Section Use Cases.
The author would like to thank Murat Can Demirok for testing the packages and providing feedback, and to Johannes (Jos) Lelieveld for valuable feedback on the manuscript.
Supplementary File 1: test_spop.R.
R script file for Section Implementation:R.
Click here to access the data.
Supplementary File 2: test_spop.py.
Python script file for Section Implementation:Python.
Click here to access the data.
Supplementary File 3: test_spop.c.
C code file for Section Implementation:C.
Click here to access the data.
Supplementary File 4: case_studies.py.
Python script file for Section Use Cases.
Click here to access the data.
Supplementary File 5: plot_test_spop.R.
Python script file for Section Use Cases.
Views | Downloads | |
---|---|---|
F1000Research | - | - |
PubMed Central Data from PMC are received and updated monthly. | - | - |
Is the rationale for developing the new software tool clearly explained?
Partly
Is the description of the software tool technically sound?
Yes
Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others?
Yes
Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool?
Yes
Are the conclusions about the tool and its performance adequately supported by the findings presented in the article?
Yes
Competing Interests: No competing interests were disclosed.
Reviewer Expertise: Disease ecology; Wildlife demography; Animal social structure and behaviour
Is the rationale for developing the new software tool clearly explained?
Yes
Is the description of the software tool technically sound?
Yes
Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others?
Yes
Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool?
Yes
Are the conclusions about the tool and its performance adequately supported by the findings presented in the article?
Yes
Competing Interests: No competing interests were disclosed.
Alongside their report, reviewers assign a status to the article:
Invited Reviewers | ||
---|---|---|
1 | 2 | |
Version 3 (revision) 28 Sep 20 | ||
Version 2 (revision) 13 Dec 18 | ||
Version 1 08 Aug 18 | read | read |
Provide sufficient details of any financial or non-financial competing interests to enable users to assess whether your comments might lead a reasonable person to question your impartiality. Consider the following examples, but note that this is not an exhaustive list:
Sign up for content alerts and receive a weekly or monthly email with all newly published articles
Already registered? Sign in
The email address should be the one you originally registered with F1000.
You registered with F1000 via Google, so we cannot reset your password.
To sign in, please click here.
If you still need help with your Google account password, please click here.
You registered with F1000 via Facebook, so we cannot reset your password.
To sign in, please click here.
If you still need help with your Facebook account password, please click here.
If your email address is registered with us, we will email you instructions to reset your password.
If you think you should have received this email but it has not arrived, please check your spam filters and/or contact for further assistance.
Comments on this article Comments (1)