25/01/2018
We have been focussing on IPMs for populations structured by a single state variable. However, in many populations…
What matters here is that individual state is not not specified by just one number. These 'other states' can be discrete or continuous.
What kinds of attributes might we consider alongside an attribute such as 'size'?
Are these discrete or continuous?
What kinds of attributes might we consider alongside a typical attribute such as 'size'?
Of course, we don't have to only work with 'size'.
These may seem to be very different kinds of models, but they can all be viewed examples of the general IPM.
We'll review the deterministic, linear version, but keep in mind that the material Eelke, Mark and Steve will / have been covering can be developed for general IPMs.
The space of individual states \(\textbf{Z}\) can include a set of discrete points \(\mathbf{D} = \{ z_1 , \cdots z_D \}\) and a set of continuous domains \(\mathbf{C} = \{ \textbf{Z} _{D + 1} ,\textbf{Z} _{D + 2} , \cdots \textbf{Z} _{D + C} \}\).
Each continuous domain is either a closed interval \([L_j,U_j]\) or a closed finite rectangle in \(d\)-dimensional space.
To simplify life, each set in \(\mathbf{D}\) or \(\mathbf{C}\) will be called a component and denoted \(\textbf{Z}_j ,j = 1,2, \cdots , M = D + C\).
For example, \(\textbf{Z}_1\) and \(\textbf{Z}_2\) might represent different sexes, different colour morphs, maturation states (juvenile vs adult), or environmental states, within which individuals are classified by size.
The population state \(n(z,t)\) also consists of a set of \(M\) components:
Discrete values \(n_j(t), j = 1, 2, · · · , D\) giving the total number of individuals in each discrete component.
Continuous functions \(n_j(z_j , t), j = D+1, D+2,···, M\) giving the state distribution on the continuous components.
The total number of individuals in continuous component \(j\) is given by:
\[ \int_{Z_j} n_j (z_j , t) dz_j \]
Transitions within and among components are described by a set of kernel components \(K_{ij} , 1 ≤ i, j ≤ M\). Four kinds of transition:
Continuous to Continuous: \(K_{ij} = K_{ij}(z′,z)\) is a bivariate kernel, just like the ones you've already seen. These are typically fecundity or survival-growth kernels.
Discrete to Discrete: \(K_{ij}\) is just a number, such as the proportion of seeds in the seed bank that fail to survive and fail to germinate.
Discrete to Continuous: \(K_{ij} = k_{ij}(z′)\) is a state distribution, such as the size distribution of seedlings derived from germinating seeds.
Continuous to Discrete: \(K_{ij} = k_{ij}(z)\), is a function that describes the state-dependent contribution individuals to a discrete state, such as the number of seeds produced by an adult plant of size \(z\).
Once we have drawn the diagram it's easy(ish) to write down the IPM. For the seed bank we have: \[ B(t+1) = s_B \left[ (1-\gamma)B(t) + \delta \int\limits_L^U{p_b(z)b(z) n(z,t) \; dz} \right]. \] For rosettes there are now three pathways: survival of established rosettes, new recruits from new seeds, and new recruits from old seeds: \[ \begin{eqnarray} n(z',t+1) &=& \int\limits_L^U{G(z',z) s(z) n(z,t) \; dz} \nonumber \\ &+& c_0(z')p_r \left [(1-\delta) \int\limits_L^U{p_b(z)b(z) n(z,t) \; dz} + \gamma B(t) \right]. \end{eqnarray} \]
The key message is that the structure of the equations corresponds to the diagram.
The general IPM is a flexible and parsimonious framework for populations with complex demography. This is where the IPM framework really starts to shine! You already know the 'workflow':
Decide what your individual state variables are.
Write down the life cycle.
Organise the data to reflect the conditioning of events in the life cycle.
Let the data 'speak':
The model follows from your conceptualisation of life cycle and the results of statistical data analysis. This is best learned by example…
Many parameters to build one of these…
IPM version requires someting like 10-20 parameters
We're going to learn about age-size IPMs by working through an extended exercise. The code will be provided as we step through the exercise. Open this page in your browser:
http://rpubs.com/dzchilds/age-size-ipm-exercise
You should bookmark this. I will update the page with R code as we work through the exercise. You'll need to refresh your browser each time I do this to see each new block of code.
All organisms age (sadly). Many processes play out as organisms get older:
…and of course, there are heterogeneities within each age class, which is why we want to be able to combine age with size, lay date, your-favourite-variable.
The general form of a deterministic age-size IPM can be written:
\[ \begin{eqnarray} n_0(z',t + 1) &=& \sum\limits_{a = 0}^M {\int\limits_{Z} F_a(z',z)n_a(z,t) \, dz} \\ n_a(z',t + 1) &=& \int\limits_{Z} P_{a - 1}(z',z)n_{a - 1}(z,t) dz \quad a = 1,2, \ldots ,M \end{eqnarray} \] This assumes a maximum age beyond which no individual lives. If we want to include a maximum 'greybeard' class this adds one more equation to the model:
\[ n_{M+1}(z',t + 1) = \int\limits_Z{\left[P_{M}(z',z)n_{M}(z,t) + P_{M+1}(z',z)n_{M+1}(z,t)\right] \, dz} \] It's often a good idea to include this extra class because organisms don't really have a maximum age, but data from older individuals is limited.
A model system for population ecology and evolution:
A model system for population ecology and evolution:
A model system for population ecology and evolution:
A model system for population ecology and evolution:
Ignore the role of age for now. We just want to focus on the life cycle and census points.
What kind of census is this?
But there's a small snag. We only weigh lambs (not established ewes) in the spring…
The solution to this problem is to collapse the survival-growth components of established individuals into a single summer-summer transition. This leads to the following model.
\[ \begin{aligned} n(z', t+1) &= \int\limits_Z [P(z',z) + F(z',z)]n(z,t) dz\\ P(z',z) &= s_w^E(z)G^E(z',z) \\ F(z',z) &= s_w^E(z)p_b(z) \int\limits_Z [s_s^L(z^*)G_s^L(z',z^*)C_0^*(z^*,z)/2] dz^* \end{aligned} \]
We could build this model using the Soay data, but it's a bit of a pain as we have to do the integration to build \(F(z',z)\).
There are a couple of ways to simplify the model:
This leads to the following (much simpler) IPM for the Soays.
\[ \begin{aligned} n(z', t+1) &= \int\limits_Z [P(z',z) + F(z',z)]n(z,t) dz\\ P(z',z) &= s(z)G(z',z) \\ F(z',z) &= s(z)p_b(z)p_r(z)C_0(z',z)/2 \end{aligned} \]
In effect, we "do the integration" during the statistical analysis.
Simple. Separate survival-growth and fecundity processes, and project the age-specific size distributions, \(n_a(z,t)\):
\[ \begin{eqnarray} n_0(z',t + 1) &=& \sum\limits_{a = 0}^M {\int\limits_{Z} [s(z, a)p_b(z, a)p_r(z, a)C_0(z',z, a)/2] n_a(z,t) \, dz} \\ n_a(z',t + 1) &=& \int\limits_{Z} s(z, a)G(z',z, a)n_{a - 1}(z,t) dz \quad a = 1,2, \ldots ,M \end{eqnarray} \]
We can also add the 'greybeard class' if we want it (we will).
Assume…
(log) size- and age-structured demography
female only (males don't matter)
deterministic and density independent
age 0 individuals ('summer lambs') never reproduce
Start a new script.
Use read.csv to read in the soay_demog_data.csv file.
Use the View function to examine the data set.
| z | a | Surv | z1 | Repr | Sex | Recr | Rcsz |
|---|---|---|---|---|---|---|---|
| 2.39 | 0 | 0 | NA | NA | NA | NA | NA |
| 2.76 | 0 | 1 | 2.86 | 0 | NA | NA | NA |
| 3.14 | 4 | 1 | 3.29 | 1 | 0 | NA | NA |
| 2.95 | 1 | 1 | 2.93 | 1 | 1 | 0 | NA |
| 2.96 | 5 | 1 | 2.98 | 1 | 1 | 1 | 2.7 |
z: Female size at time t (log body mass)z1: Female size at time t+1 (log body mass)a: Female age at time t (years)Surv: Survival (1 = survived)Repr: Reproduction (1 = survived)Sex: Offspring sex (1 = female)Recr: Offspring recruitment (1 = female)RcSz: Offspring size at recruitment variableBe sure to condition your analysis on the correct subset of data:
repr_data <- subset(sim_data, Surv==1 & a>0)
Fit the model (or models) needed to assess which variables matter:
mod_repr <- glm(Repr ~ z + a, family = binomial, data = repr_data)
Assess which variables are significant using your favourite model selection tool. Dylan likes car::Anova…
Over to you. You need to fit five models:
# survival mod_surv <- glm(Surv ~ <define me>, family = binomial, data = <make me>) # growth mod_grow <- lm(z1 ~ <define me>, data = <make me>) # reproduction mod_repr <- glm(Repr ~ <define me>, family = binomial, data = <make me>) # offspring recruitment mod_recr <- glm(Recr ~ <define me>, family = binomial, data = <make me>) # offspring size (summer) mod_rcsz <- lm(Rcsz ~ <define me>, data = <make me>)
Next, is a bit of simple house keeping. We need to store the model coefficients in a vector.
m_par <-
c(
surv = coef(mod_surv),
grow = coef(mod_grow),
grow_sd = summary(mod_grow)$sigma,
repr = coef(mod_repr),
recr = coef(mod_recr),
rcsz = coef(mod_rcsz),
rcsz_sd = summary(mod_rcsz)$sigma
)
# clean up the names -- make the intercept labels shorter
names(m_par) <-
sub(pattern = "(Intercept)", replace = "int",
x = names(m_par), fixed = TRUE)
# clean up the names -- replace . with underscores
names(m_par) <-
sub(pattern = ".", replace = "_",
x = names(m_par), fixed = TRUE)
Here's an example – probability of reproduction
pb_z <- function(z, a, m_par){
if (a==0) {
p <- 0
} else {
linear_p <- m_par["repr_int"] + m_par["repr_z"] * z + m_par["repr_a"] * a
p <- 1 / (1 + exp(-linear_p))
}
return(p)
}
Over to you. You need to define five functions:
# Growth kernel
g_z1z <- function(z1, z, a, m_par){
<define me>
}
# Survival function, logistic regression
s_z <- function(z, a, m_par){
<define me>
}
# Reproduction function, logistic regression
pb_z <- function(z, a, m_par){
<define me>
}
# Recruitment function, logistic regression
pr_z <- function(a, m_par) {
<define me>
}
# Recruit size kernel
c_z1z <- function(z1, z, a, m_par){
<define me>
}
Now define the \(F\) and \(P\) age-specific kernel functions:
# Define the survival-growth kernel
P_z1z <- function (z1, z, a, m_par) {
<define me>
}
# Define the reproduction kernel
F_z1z <- function (z1, z, a, m_par) {
<define me>
}
Remember…
\[ \begin{eqnarray} P_a(z',z) &=& s(z, a)G(z',z, a)\\ F_a(z',z) &=& s(z, a)p_b(z, a)p_r(z, a)C_0(z',z, a)/2 \end{eqnarray} \]
How do we implement an age-size model? Recall the model:
\[ \begin{eqnarray} n_0(z',t + 1) &=& \sum\limits_{a = 0}^M {\int\limits_{Z} F_a(z',z)n_a(z,t) \, dz} \\ n_a(z',t + 1) &=& \int\limits_{Z} P_{a - 1}(z',z)n_{a - 1}(z,t) dz \quad a = 1,2, \ldots ,M \end{eqnarray} \]
The integrals are all one-dimensional, and can be handled in the usual way by the midpoint rule. How do we "put it all together" so that we can iterate the model? There are several options:
Embed the iteration matrices for each \(F_a(z',z)\) and \(P_a(z',z)\) into one big, ordinary matrix. This is not efficient because most elements of this matrix will be zero.
Embed the iteration matrices for each \(F_a(z',z)\) and \(P_a(z',z)\) into one block-sparse matrix. This is more efficient, but taking care of the indexing can be error prone.
Work with a set of age-specific matrices stored in a list. This is more computationally efficient, it's easier and safer to code (and works well for other kinds of general IPM)
We're going to use #3.
# Calculate the 'stuff' we need for integration
mk_intpar <- function(m, L, U, M) {
<body>
}
# make initial state distribution
mk_init_nt0 <- function(i_par) {
<body>
}
# Build the list of age/process specific iteration matrices
mk_age_IPM <- function(i_par, m_par) {
<body>
}
I'll give you these. Copy them to the end of your script. Then add the next two lines, run everything, and then spend some time looking at i_par, IPM_sys and x:
i_par <- mk_intpar(m = 200, M = 20, L = 1.6, U = 3.7) IPM_sys <- mk_age_IPM(i_par, m_par) x <- mk_init_nt0(i_par)
If we iterate an age-size IPM it will converge to a stable age-size distribution, \(w_a(z)\), with the population growing at a constant rate \(\lambda\). This means we can always calculate \(w_a(z)\) and \(\lambda\) by iteration once we know how to implement the model.
What about reproductive value? We need 'the transpose iteration'. With a finite maximum age \(M\), the transpose iteration is \[ v_a(t + 1) = P_a^T v_{a + 1}(t) + F_a^T v_0 (t), \quad a=0,1,2,\cdots,M \] Here \(K_a^T\) represents the transpose kernel \(K_a^T(z',z) = K_a(z,z')\). In practice this is done with the transposes of the iteration matrices for \(P\) and \(F\).
For the greybeard age-class \(M+1\), if the model includes one, \[ v_{M+1}(t + 1) = P_{M+1}^T v_{M + 1}(t) + F_a^T v_0 (t). \]
# 'right' iterate one time step
r_iter <- function(x, F, P) {
<body>
return(xnew)
}
# 'left' iterate one time step
l_iter <- function(x, F, P) {
<body>
return(xnew)
}
See if you can code the r_iter function. Remember, x is the list of age-specific size distributions, F and P are lists of age-specific kernels.
See if you can calculate lambda by iteration and produce the following plots of \(w_a(z)\) and \(v_a(z)\).
Hint: You need to write code to iterate the model using mk_intpar, mk_age_IPM and mk_init_nt0. You'll need two versions, one that uses r_iter (\(w_a(z)\)) and another that uses l_iter (\(v_a(z)\)).
The long-run, generation-to-generation growth rate \(R_0\) for an age-size IPM is calculated in the same way as for a simple IPM. We add up the expected offspring production in each year of life from a cohort with size distribution \(n_0(z)\) at birth using the 'next generation kernel' \(R\). If individuals do not live beyond age \(M\), then \(R\) is \[ (F_0+F_1P_0+F_2P_1P_0+F_3P_2P_1P_0+ \cdots +F_MP_{M-1} \cdots P_0) = \left(F_0 + \sum\limits_{a=1}^M F_a\prod\limits_{m=0}^{a-1}P_m\right) \] If individuals beyond age \(M\) are lumped into an "\(M+1\) or older" class, then \(R\) includes an extra term: \[ F_{M+1}(I+P_{M+1}+P_{M+1}^2+ \cdots )\prod\limits_{m=0}^{M}P_m = F_{M+1}(I-P_{M+1})^{-1}\prod\limits_{m=0}^{M}P_m. \]
\(R_0\) is the dominant eigenvalue of the \(R\) kernel. How do we do this?
We need a new function to do generation-to-generation iteration:
matmulR <- function(x, IPM_sys, n_iter=100) {
with(IPM_sys, {
xtot <- rep(0, length(x))
for (ia in seq_len(n_iter)) {
if (ia < na) {
Pnow <- P[[ia]]
Fnow <- F[[ia]]
} else {
Pnow <- P[[na]]
Fnow <- F[[na]]
}
xtot <- Fnow %*% x + xtot
x <- Pnow %*% x
}
xtot
})
}
Write some R code that uses the matmulR function to compute the 'next generation' \(n_0(z)\) and \(R_0\) by iteration.
We don't have to use iteration. Applied mathematicians working on sparse linear systems have worked out efficient methods to calculate eigenvalues.
# using igraph package for convenience library(igraph) # use igraph::arpack to compute just the leading eig val/vec arpack( matmulR, extra = IPM_sys, complex = FALSE, options = list(n = IPM_sys$m, nev = 1) )$val[1]
"Does age matter?" is a poorly defined question… Let's think about population growth.
One simple way to address this question is to build a size-only model (i.e. ignores age), then compare this to the age-size model.
Do this now: compare the size-only predictions of \(\lambda\), \(R_0\) and generation time (\(T\)) to those from the age-size model.
What do you think is causing the discrepancy?
I'll leave this code in the answers file.
Bruno, John F., Stephen P. Ellner, Ivana Vu, Kiho Kim, and C. Drew Harvell. 2011. “Impacts of Aspergillosis on Sea Fan Coral Demography: Modeling a Moving Target.” Ecological Monographs 81 (1): 123–39.
Childs, D. Z., T. N. Coulson, J. M. Pemberton, T. H. Clutton-Brock, and M. Rees. 2011. “Predicting Trait Values and Measuring Selection in Complex Life Histories: Reproductive Allocation Decisions in Soay Sheep.” Ecology Letters 14 (10): 985–92.
Childs, D. Z., M. Rees, K. E. Rose, P. J. Grubb, and S. P. Ellner. 2003. “Evolution of Complex Flowering Strategies: An Age- and Size-Structured Integral Projection Model.” Proceedings of the Royal Society of London Series B-Biological Sciences 270 (1526): 1829–38.
Childs, Dylan Z, Ben C Sheldon, and Mark Rees. 2016. “The Evolution of Labile Traits in Sex-and Age-Structured Populations.” Journal of Animal Ecology 85 (2). Wiley Online Library: 329–42.
Eager, Eric Alan, Chirakkal V. Haridas, Diana Pilson, Richard Rebarber, and Brigitte Tenhumberg. 2013. “Disturbance Frequency and Vertical Distribution of Seeds Affect Long-Term Population Dynamics: A Mechanistic Seed Bank Model.” Amercian Naturalist 182 (2): 180–90. doi:10.1086/670987.
Jongejans, Eelke, Katriona Shea, Olav Skarpaas, Dave Kelly, and Stephen P. Ellner. 2011. “Importance of Individual and Environmental Variation for Invasive Species Spread: A Spatial Integral Projection Model.” Ecology 92 (1): 86–97.
Metcalf, C Jessica E, Andrea L Graham, Micaela Martinez-Bakker, and Dylan Z Childs. 2016. “Opportunities and Challenges of Integral Projection Models for Modelling Host–parasite Dynamics.” Journal of Animal Ecology 85 (2). Wiley Online Library: 343–55.
Metcalf, C. J. E., C. C. Horvitz, S. Tuljapurkar, and D. A. Clark. 2009. “A Time to Grow and a Time to Die: A New Way to Analyze the Dynamics of Size, Light, Age, and Death of Tropical Trees.” Ecology 90: 2766–78.
Metcalf, C. J. E., K. E. Rose, D. Z. Childs, A. W. Sheppard, P. J. Grubb, and M. Rees. 2008. “Evolution of Flowering Decisions in a Stochastic, Density-Dependent Environment.” Proceedings of the National Academy of Sciences of the United States of America 105 (30): 10466–70. doi:Doi 10.1073/Pnas.0800777105.
Moore, Jacob L., Romuald N. Lipcius, Brandon Puckett, and Sebastian J. Schreiber. 2016. “The Demographic Consequences of Growing Older and Bigger in Oyster Populations.” Ecological Applications 26 (7): 2206–17. doi:10.1002/eap.1374.
Rees, M., D. Z. Childs, C. J. E. Metcalf, K. E. Rose, A. W. Sheppard, and P. J. Grubb. 2006. “Seed Dormancy and Delayed Flowering in Monocarpic Plants: Selective Interactions in a Stochastic Environment.” The American Naturalist 168 (2): E53–E71. doi:10.1086/505762.
Valpine, Perry de. 2009. “Stochastic Development in Biologically Structured Population Models.” Ecology 90 (10): 2889–2901. doi:10.1890/08-0703.1.
Wilber, Mark Q., Kate E. Langwig, Auston Marm Kilpatrick, Hamish I. McCallum, and Cheryl J. Briggs. 2016. “Integral Projection Models for Host–parasite Systems with an Application to Amphibian Chytrid Fungus.” Methods in Ecology and Evolution 7 (10): 1182–94. doi:10.1111/2041-210X.12561.