Path: blob/main/latex-templates/templates/ecology/metapopulation.tex
51 views
unlisted
\documentclass[11pt,a4paper]{article}1\usepackage[utf8]{inputenc}2\usepackage[T1]{fontenc}3\usepackage{amsmath,amssymb}4\usepackage{graphicx}5\usepackage{booktabs}6\usepackage{siunitx}7\usepackage{geometry}8\geometry{margin=1in}9\usepackage{pythontex}10\usepackage{hyperref}11\usepackage{float}12\usepackage{natbib}1314\title{Metapopulation Dynamics: Patch Occupancy Models and Spatial Population Persistence}15\author{Ecology Research Group}16\date{\today}1718\begin{document}19\maketitle2021\begin{abstract}22Metapopulation theory provides a framework for understanding how spatial population structure influences persistence in fragmented landscapes. We analyze the classical Levins model of patch occupancy dynamics, where local populations experience colonization and extinction at the patch level. Using computational simulations, we examine equilibrium occupancy patterns, extinction thresholds, and the critical colonization-extinction ratio that determines metapopulation viability. Our analysis reveals that the metapopulation equilibrium $p^* = 1 - e/c$ requires colonization rates ($c$) to exceed extinction rates ($e$) for persistence, with spatial connectivity playing a crucial role in maintaining population networks. We extend the analysis to source-sink dynamics, incidence functions dependent on patch characteristics, and extinction debt following habitat loss. Results demonstrate that metapopulations can persist regionally despite local extinctions when sufficient patch connectivity maintains colonization-extinction balance, but face collapse when habitat destruction reduces metapopulation capacity below critical thresholds.23\end{abstract}2425\section{Introduction}2627Habitat fragmentation has become one of the most pervasive threats to biodiversity, creating landscapes where species persist as collections of local populations connected by dispersal rather than as single continuous populations \citep{hanski1999metapopulation, fahrig2003effects}. Metapopulation theory, pioneered by \citet{levins1969some}, provides a mathematical framework for understanding how populations survive in fragmented landscapes through the balance of local extinction and recolonization.2829In classical metapopulation models, a species occupies a network of discrete habitat patches, each supporting a local population that faces some probability of extinction. Regional persistence depends not on the permanence of any single local population, but on the rate at which extinct patches are recolonized from occupied patches. This fundamental insight—that populations can persist regionally despite local instability—has profound implications for conservation in fragmented landscapes \citep{hanski1998metapopulation}.3031The simplest metapopulation model, proposed by Levins, tracks the fraction of occupied patches $p(t)$ through time. Occupied patches generate colonists at rate $c$ that establish new populations in empty patches, while occupied patches go extinct at rate $e$. This yields the differential equation:32\begin{equation}33\frac{dp}{dt} = cp(1-p) - ep34\end{equation}3536This deceptively simple model reveals critical thresholds for persistence and provides a foundation for understanding more complex spatial population dynamics.3738\begin{pycode}39import numpy as np40import matplotlib.pyplot as plt41from scipy.integrate import odeint42from scipy.optimize import fsolve43import matplotlib.patches as mpatches4445plt.rcParams['text.usetex'] = True46plt.rcParams['font.family'] = 'serif'47plt.rcParams['font.size'] = 104849# Levins model parameters50colonization_rate = 0.15 # colonization rate per patch51extinction_rate = 0.05 # extinction rate per patch52time_horizon = 200 # years5354# Initial conditions for different scenarios55initial_occupancy_low = 0.156initial_occupancy_high = 0.957\end{pycode}5859\section{The Levins Metapopulation Model}6061The Levins model describes metapopulation dynamics in terms of patch occupancy rather than population sizes. Let $p(t)$ represent the fraction of patches occupied at time $t$. The model assumes:6263\begin{enumerate}64\item All patches are identical and equally connected65\item Colonization rate is proportional to both occupied patches (source of colonists) and empty patches (targets for colonization)66\item Extinction occurs at constant rate $e$ per occupied patch67\item Dynamics are much faster at the patch level than at the metapopulation level68\end{enumerate}6970\subsection{Model Derivation and Equilibrium}7172The rate of change in patch occupancy has two components:73\begin{itemize}74\item \textbf{Colonization}: Empty patches $(1-p)$ are colonized at rate $cp$, where $c$ is the colonization coefficient75\item \textbf{Extinction}: Occupied patches $p$ go extinct at rate $e$76\end{itemize}7778This yields:79\begin{equation}80\frac{dp}{dt} = \underbrace{cp(1-p)}_{\text{colonization}} - \underbrace{ep}_{\text{extinction}}81\end{equation}8283At equilibrium, $\frac{dp}{dt} = 0$, giving:84\begin{equation}85cp^*(1-p^*) = ep^*86\end{equation}8788This has two solutions:89\begin{enumerate}90\item $p^* = 0$ (extinction)91\item $p^* = 1 - \frac{e}{c}$ (coexistence)92\end{enumerate}9394The coexistence equilibrium exists only when $c > e$, revealing a critical threshold: \textbf{the colonization rate must exceed the extinction rate for metapopulation persistence}.9596\begin{pycode}97# Levins model differential equation98def levins_model(p, t, c, e):99"""100Levins metapopulation model101102Parameters:103p : float - fraction of patches occupied104t : float - time105c : float - colonization rate106e : float - extinction rate107108Returns:109dpdt : float - rate of change in patch occupancy110"""111dpdt = c * p * (1 - p) - e * p112return dpdt113114# Time array115time_points = np.linspace(0, time_horizon, 1000)116117# Solve for different initial conditions118trajectory_low = odeint(levins_model, initial_occupancy_low, time_points,119args=(colonization_rate, extinction_rate))120trajectory_high = odeint(levins_model, initial_occupancy_high, time_points,121args=(colonization_rate, extinction_rate))122123# Calculate equilibrium124equilibrium_occupancy = 1 - extinction_rate / colonization_rate125126# Extinction threshold (c = e)127extinction_threshold = extinction_rate128129# Create figure showing Levins model dynamics130fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))131132# Panel A: Time series from different initial conditions133ax1.plot(time_points, trajectory_low, 'b-', linewidth=2, label='Initial $p_0 = 0.1$')134ax1.plot(time_points, trajectory_high, 'r-', linewidth=2, label='Initial $p_0 = 0.9$')135ax1.axhline(equilibrium_occupancy, color='black', linestyle='--', linewidth=1.5,136label=f'Equilibrium $p^* = {equilibrium_occupancy:.3f}$')137ax1.set_xlabel('Time (years)', fontsize=12)138ax1.set_ylabel('Patch Occupancy Fraction $p(t)$', fontsize=12)139ax1.set_title('Levins Model: Convergence to Equilibrium', fontsize=13, weight='bold')140ax1.legend(loc='best', fontsize=10)141ax1.grid(True, alpha=0.3)142ax1.set_xlim(0, time_horizon)143ax1.set_ylim(0, 1)144145# Panel B: Phase portrait showing dp/dt vs p146p_range = np.linspace(0, 1, 200)147dpdt_range = colonization_rate * p_range * (1 - p_range) - extinction_rate * p_range148149ax2.plot(p_range, dpdt_range, 'darkgreen', linewidth=2.5)150ax2.axhline(0, color='black', linestyle='-', linewidth=0.8)151ax2.axvline(equilibrium_occupancy, color='red', linestyle='--', linewidth=1.5,152label=f'Stable equilibrium $p^* = {equilibrium_occupancy:.3f}$')153ax2.axvline(0, color='gray', linestyle='--', linewidth=1.5, alpha=0.5,154label='Unstable equilibrium (extinction)')155ax2.fill_between(p_range, 0, dpdt_range, where=(dpdt_range > 0),156alpha=0.2, color='green', label='$dp/dt > 0$ (increasing)')157ax2.fill_between(p_range, 0, dpdt_range, where=(dpdt_range < 0),158alpha=0.2, color='red', label='$dp/dt < 0$ (decreasing)')159ax2.set_xlabel('Patch Occupancy $p$', fontsize=12)160ax2.set_ylabel('Rate of Change $dp/dt$', fontsize=12)161ax2.set_title('Phase Portrait: Colonization-Extinction Balance', fontsize=13, weight='bold')162ax2.legend(loc='best', fontsize=9)163ax2.grid(True, alpha=0.3)164165plt.tight_layout()166plt.savefig('metapopulation_levins_dynamics.pdf', dpi=300, bbox_inches='tight')167plt.close()168\end{pycode}169170\begin{figure}[H]171\centering172\includegraphics[width=0.98\textwidth]{metapopulation_levins_dynamics.pdf}173\caption{Levins metapopulation model dynamics with colonization rate $c = \py{colonization_rate}$ and extinction rate $e = \py{extinction_rate}$. \textbf{Left panel}: Time trajectories from different initial occupancy levels converge to the stable equilibrium $p^* = \py{f'{equilibrium_occupancy:.3f}'}$, demonstrating that metapopulation persistence depends on the colonization-extinction balance rather than initial conditions. \textbf{Right panel}: Phase portrait showing the rate of change in patch occupancy as a function of current occupancy. The system has two equilibria: an unstable extinction state at $p = 0$ and a stable coexistence equilibrium at $p^* = 1 - e/c = \py{f'{equilibrium_occupancy:.3f}'}$. Green shading indicates regions where patch occupancy increases (colonization exceeds extinction), while red shading shows where occupancy decreases. The stable equilibrium represents a balance where colonization of empty patches exactly compensates for extinction of occupied patches.}174\end{figure}175176\subsection{Extinction Threshold and Metapopulation Capacity}177178The critical condition for persistence, $c > e$, can be interpreted in terms of metapopulation capacity. When colonization rates fall below extinction rates, the only stable equilibrium is complete extinction. This threshold has important conservation implications: habitat destruction that reduces connectivity (and thus colonization rates) can push metapopulations below the extinction threshold even when suitable habitat remains.179180\begin{pycode}181# Analyze extinction threshold182colonization_range = np.linspace(0, 0.3, 100)183equilibria = np.zeros_like(colonization_range)184185for i, c in enumerate(colonization_range):186if c > extinction_rate:187equilibria[i] = 1 - extinction_rate / c188else:189equilibria[i] = 0 # extinction190191# Create threshold analysis figure192fig, ax = plt.subplots(figsize=(10, 6))193194# Plot equilibrium occupancy vs colonization rate195ax.plot(colonization_range, equilibria, 'b-', linewidth=3, label='Equilibrium occupancy $p^*$')196ax.axvline(extinction_rate, color='red', linestyle='--', linewidth=2,197label=f'Extinction threshold $c = e = {extinction_rate}$')198ax.axhline(equilibrium_occupancy, color='green', linestyle=':', linewidth=2,199label=f'Current equilibrium $p^* = {equilibrium_occupancy:.3f}$')200201# Shade regions202ax.fill_between(colonization_range, 0, 1,203where=(colonization_range <= extinction_rate),204alpha=0.2, color='red', label='Extinction region ($c < e$)')205ax.fill_between(colonization_range, 0, equilibria,206where=(colonization_range > extinction_rate),207alpha=0.2, color='green', label='Persistence region ($c > e$)')208209ax.set_xlabel('Colonization Rate $c$ (per patch per year)', fontsize=12)210ax.set_ylabel('Equilibrium Patch Occupancy $p^*$', fontsize=12)211ax.set_title('Extinction Threshold: Metapopulation Viability vs Colonization Rate',212fontsize=13, weight='bold')213ax.legend(loc='lower right', fontsize=10)214ax.grid(True, alpha=0.3)215ax.set_xlim(0, 0.3)216ax.set_ylim(0, 1)217218# Add annotation219ax.annotate('Metapopulation\ncollapse',220xy=(extinction_rate * 0.5, 0.05), fontsize=11,221ha='center', color='darkred', weight='bold')222ax.annotate('Stable\npersistence',223xy=(0.22, 0.8), fontsize=11,224ha='center', color='darkgreen', weight='bold')225226plt.tight_layout()227plt.savefig('metapopulation_extinction_threshold.pdf', dpi=300, bbox_inches='tight')228plt.close()229230# Calculate some key metrics231critical_ratio = colonization_rate / extinction_rate232doubling_time_approx = np.log(2) / (colonization_rate - extinction_rate)233\end{pycode}234235\begin{figure}[H]236\centering237\includegraphics[width=0.85\textwidth]{metapopulation_extinction_threshold.pdf}238\caption{Extinction threshold in the Levins metapopulation model showing equilibrium patch occupancy as a function of colonization rate. When colonization rate $c$ exceeds extinction rate $e = \py{extinction_rate}$, the metapopulation persists at equilibrium occupancy $p^* = 1 - e/c$. Below this critical threshold (red shaded region), the only stable state is complete extinction ($p^* = 0$). The current parameter set yields a colonization-extinction ratio of $c/e = \py{f'{critical_ratio:.2f}'}$, supporting metapopulation persistence at $p^* = \py{f'{equilibrium_occupancy:.3f}'}$ occupancy. This demonstrates that habitat fragmentation affecting colonization rates can drive metapopulation collapse even when local extinction rates remain constant, a phenomenon critical to understanding species decline in fragmented landscapes.}239\end{figure}240241\section{Patch Size Effects and Incidence Functions}242243Real metapopulations violate the Levins assumption of patch homogeneity. Larger patches typically support larger populations with lower extinction probabilities, while isolation reduces colonization probability. These effects can be captured through \textbf{incidence functions} that predict patch occupancy based on patch characteristics.244245\subsection{Area-Dependent Extinction and Colonization}246247Extinction probability typically decreases with patch area (larger populations are more stable), while colonization probability increases with patch connectivity. We can model these effects as:248249\begin{align}250\text{Extinction rate: } & e_i = e_0 \cdot A_i^{-x} \\251\text{Colonization rate: } & c_i = c_0 \cdot S_i \cdot A_i^{y}252\end{align}253254where $A_i$ is patch area, $S_i$ is a connectivity metric, and $x, y$ are scaling exponents.255256\begin{pycode}257# Simulate patch network with heterogeneous sizes258np.random.seed(42)259num_patches = 50260patch_areas = np.random.gamma(2, 2, num_patches) # heterogeneous patch sizes261patch_distances = np.random.uniform(0.5, 5, num_patches) # isolation distances262263# Area-dependent extinction rates (smaller patches = higher extinction)264extinction_exponent = 0.5265baseline_extinction = 0.1266patch_extinction_rates = baseline_extinction * patch_areas**(-extinction_exponent)267268# Distance-dependent colonization (isolated patches = lower colonization)269distance_decay = 0.5270baseline_colonization = 0.2271patch_connectivity = np.exp(-distance_decay * patch_distances)272patch_colonization_rates = baseline_colonization * patch_connectivity * patch_areas**0.3273274# Calculate expected incidence (equilibrium occupancy probability) for each patch275patch_incidence = np.zeros(num_patches)276for i in range(num_patches):277if patch_colonization_rates[i] > patch_extinction_rates[i]:278patch_incidence[i] = 1 - patch_extinction_rates[i] / patch_colonization_rates[i]279else:280patch_incidence[i] = 0281282# Sort by patch area for visualization283sort_idx = np.argsort(patch_areas)284sorted_areas = patch_areas[sort_idx]285sorted_incidence = patch_incidence[sort_idx]286sorted_extinction = patch_extinction_rates[sort_idx]287sorted_colonization = patch_colonization_rates[sort_idx]288289# Create incidence function plot290fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 10))291292# Panel A: Extinction rate vs patch area293ax1.scatter(patch_areas, patch_extinction_rates, c='red', s=60, alpha=0.6, edgecolors='darkred')294area_range = np.linspace(0.5, max(patch_areas), 100)295predicted_extinction = baseline_extinction * area_range**(-extinction_exponent)296ax1.plot(area_range, predicted_extinction, 'r--', linewidth=2,297label=f'$e(A) = {baseline_extinction:.2f} \\cdot A^{{-{extinction_exponent}}}$')298ax1.set_xlabel('Patch Area (ha)', fontsize=11)299ax1.set_ylabel('Extinction Rate (per year)', fontsize=11)300ax1.set_title('A) Area-Dependent Extinction', fontsize=12, weight='bold')301ax1.legend(loc='upper right', fontsize=10)302ax1.grid(True, alpha=0.3)303304# Panel B: Colonization rate vs isolation305ax2.scatter(patch_distances, patch_colonization_rates, c='blue', s=60, alpha=0.6, edgecolors='darkblue')306dist_range = np.linspace(min(patch_distances), max(patch_distances), 100)307predicted_connectivity = np.exp(-distance_decay * dist_range)308ax2.plot(dist_range, baseline_colonization * predicted_connectivity * np.mean(patch_areas)**0.3,309'b--', linewidth=2, label=f'$c(d) \\propto e^{{-{distance_decay} d}}$')310ax2.set_xlabel('Isolation Distance (km)', fontsize=11)311ax2.set_ylabel('Colonization Rate (per year)', fontsize=11)312ax2.set_title('B) Distance-Dependent Colonization', fontsize=12, weight='bold')313ax2.legend(loc='upper right', fontsize=10)314ax2.grid(True, alpha=0.3)315316# Panel C: Incidence function317ax3.scatter(sorted_areas, sorted_incidence, c=sorted_incidence, cmap='RdYlGn',318s=80, alpha=0.7, edgecolors='black', vmin=0, vmax=1)319ax3.axhline(0.5, color='gray', linestyle='--', linewidth=1, alpha=0.5)320ax3.set_xlabel('Patch Area (ha)', fontsize=11)321ax3.set_ylabel('Occupancy Probability (Incidence)', fontsize=11)322ax3.set_title('C) Incidence Function: Occupancy vs Area', fontsize=12, weight='bold')323ax3.grid(True, alpha=0.3)324ax3.set_ylim(-0.05, 1.05)325326# Panel D: Colonization-extinction ratio327ce_ratio = patch_colonization_rates / patch_extinction_rates328ax4.scatter(patch_areas, ce_ratio, c=patch_incidence, cmap='RdYlGn',329s=80, alpha=0.7, edgecolors='black', vmin=0, vmax=1)330ax4.axhline(1, color='red', linestyle='--', linewidth=2, label='Extinction threshold ($c/e = 1$)')331ax4.set_xlabel('Patch Area (ha)', fontsize=11)332ax4.set_ylabel('Colonization/Extinction Ratio ($c/e$)', fontsize=11)333ax4.set_title('D) Viability Threshold by Patch Size', fontsize=12, weight='bold')334ax4.legend(loc='upper left', fontsize=10)335ax4.grid(True, alpha=0.3)336ax4.set_yscale('log')337338plt.tight_layout()339plt.savefig('metapopulation_incidence_functions.pdf', dpi=300, bbox_inches='tight')340plt.close()341342# Calculate summary statistics343mean_patch_area = np.mean(patch_areas)344viable_patch_fraction = np.sum(patch_incidence > 0) / num_patches345mean_incidence = np.mean(patch_incidence[patch_incidence > 0])346\end{pycode}347348\begin{figure}[H]349\centering350\includegraphics[width=0.98\textwidth]{metapopulation_incidence_functions.pdf}351\caption{Incidence functions showing how patch characteristics affect metapopulation dynamics in a heterogeneous landscape of \py{num_patches} habitat patches. \textbf{Panel A}: Extinction rate decreases with patch area following a power law $e(A) \propto A^{-0.5}$, as larger patches support larger, more stable populations. \textbf{Panel B}: Colonization rate declines exponentially with isolation distance due to reduced dispersal success. \textbf{Panel C}: Equilibrium occupancy probability (incidence) increases with patch area, with small or isolated patches showing near-zero occupancy while large, connected patches approach certainty of occupancy. \textbf{Panel D}: The colonization-extinction ratio $c/e$ determines patch viability; patches below the threshold (red line, $c/e = 1$) cannot sustain populations independently. In this simulated landscape, \py{f'{viable_patch_fraction*100:.1f}'}\% of patches have positive incidence, with mean occupancy probability \py{f'{mean_incidence:.3f}'} for viable patches, demonstrating that landscape heterogeneity creates a gradient of patch quality rather than uniform occupancy patterns.}352\end{figure}353354\section{Source-Sink Dynamics and Rescue Effects}355356In heterogeneous landscapes, some patches may have negative intrinsic growth rates (sinks) but persist through immigration from high-quality patches (sources). This \textbf{source-sink dynamics} extends classical metapopulation theory by recognizing that occupied patches may depend on dispersal for persistence, not just recolonization after extinction.357358\subsection{The Rescue Effect}359360High immigration rates can reduce effective extinction probability through demographic rescue, where immigrants prevent small populations from stochastic extinction. This creates a positive feedback: high patch occupancy increases connectivity, which reduces extinction rates, which maintains high occupancy.361362\begin{pycode}363# Source-sink metapopulation model364def source_sink_dynamics(state, t, patch_quality, connectivity_matrix, base_extinction):365"""366Metapopulation model with source-sink dynamics and rescue effect367368Parameters:369state : array - occupancy probability for each patch370t : float - time371patch_quality : array - intrinsic growth rate for each patch372connectivity_matrix : array - dispersal connectivity between patches373base_extinction : float - baseline extinction rate374375Returns:376dpdt : array - rate of change for each patch377"""378n_patches = len(state)379dpdt = np.zeros(n_patches)380381for i in range(n_patches):382# Colonization from all occupied patches383colonization = 0384for j in range(n_patches):385if i != j:386colonization += connectivity_matrix[j, i] * state[j]387388# Extinction with rescue effect (immigration reduces extinction)389immigration = np.sum(connectivity_matrix[:, i] * state)390rescue_factor = 1 - 0.7 * min(immigration, 1) # immigration reduces extinction391extinction = base_extinction * rescue_factor392393# Dynamics including patch quality394if state[i] > 0.01: # if occupied395dpdt[i] = colonization * (1 - state[i]) + patch_quality[i] * state[i] - extinction * state[i]396else:397dpdt[i] = colonization * (1 - state[i])398399return dpdt400401# Create patch network with sources and sinks402n_patches_network = 20403patch_quality_gradient = np.linspace(-0.05, 0.1, n_patches_network) # some negative (sinks)404405# Connectivity matrix (distance-based dispersal)406connectivity_strength = 0.08407connectivity_matrix = np.zeros((n_patches_network, n_patches_network))408for i in range(n_patches_network):409for j in range(n_patches_network):410if i != j:411distance = abs(i - j)412connectivity_matrix[i, j] = connectivity_strength * np.exp(-0.3 * distance)413414# Simulate dynamics415time_network = np.linspace(0, 300, 1000)416initial_state = np.random.uniform(0.3, 0.7, n_patches_network)417trajectory_network = odeint(source_sink_dynamics, initial_state, time_network,418args=(patch_quality_gradient, connectivity_matrix, 0.08))419420# Identify sources and sinks at equilibrium421equilibrium_state = trajectory_network[-1, :]422source_patches = patch_quality_gradient > 0423sink_patches = patch_quality_gradient < 0424425# Create source-sink visualization426fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 10))427428# Panel A: Patch quality gradient429patch_ids = np.arange(n_patches_network)430colors = ['red' if q < 0 else 'green' for q in patch_quality_gradient]431ax1.bar(patch_ids, patch_quality_gradient, color=colors, alpha=0.6, edgecolor='black')432ax1.axhline(0, color='black', linestyle='-', linewidth=1)433ax1.set_xlabel('Patch ID', fontsize=11)434ax1.set_ylabel('Intrinsic Growth Rate $r_i$', fontsize=11)435ax1.set_title('A) Source-Sink Gradient', fontsize=12, weight='bold')436ax1.grid(True, alpha=0.3, axis='y')437sink_patch = mpatches.Patch(color='red', alpha=0.6, label='Sink patches ($r < 0$)')438source_patch = mpatches.Patch(color='green', alpha=0.6, label='Source patches ($r > 0$)')439ax1.legend(handles=[source_patch, sink_patch], loc='lower right')440441# Panel B: Occupancy time series for sources vs sinks442source_mean = np.mean(trajectory_network[:, source_patches], axis=1)443sink_mean = np.mean(trajectory_network[:, sink_patches], axis=1)444ax2.plot(time_network, source_mean, 'g-', linewidth=2.5, label='Source patches (mean)')445ax2.plot(time_network, sink_mean, 'r-', linewidth=2.5, label='Sink patches (mean)')446ax2.set_xlabel('Time (years)', fontsize=11)447ax2.set_ylabel('Mean Patch Occupancy', fontsize=11)448ax2.set_title('B) Source vs Sink Dynamics', fontsize=12, weight='bold')449ax2.legend(loc='best', fontsize=10)450ax2.grid(True, alpha=0.3)451ax2.set_ylim(0, 1)452453# Panel C: Equilibrium occupancy vs patch quality454ax3.scatter(patch_quality_gradient[source_patches], equilibrium_state[source_patches],455c='green', s=100, alpha=0.7, edgecolors='black', label='Source patches')456ax3.scatter(patch_quality_gradient[sink_patches], equilibrium_state[sink_patches],457c='red', s=100, alpha=0.7, edgecolors='black', label='Sink patches')458ax3.axvline(0, color='black', linestyle='--', linewidth=1.5)459ax3.set_xlabel('Intrinsic Growth Rate $r_i$', fontsize=11)460ax3.set_ylabel('Equilibrium Occupancy Probability', fontsize=11)461ax3.set_title('C) Occupancy vs Patch Quality', fontsize=12, weight='bold')462ax3.legend(loc='best', fontsize=10)463ax3.grid(True, alpha=0.3)464465# Panel D: Connectivity network diagram466ax4.set_xlim(-1, n_patches_network)467ax4.set_ylim(-0.5, 1.5)468y_pos = equilibrium_state469for i in range(n_patches_network):470color = 'green' if patch_quality_gradient[i] > 0 else 'red'471ax4.scatter(i, 1, s=y_pos[i]*500, c=color, alpha=0.7, edgecolors='black', linewidth=2)472473# Draw connections474for j in range(i+1, min(i+4, n_patches_network)):475if connectivity_matrix[i, j] > 0.01:476ax4.plot([i, j], [1, 1], 'gray', alpha=0.3, linewidth=connectivity_matrix[i, j]*50)477478ax4.set_xlabel('Patch Position', fontsize=11)479ax4.set_title('D) Network Structure (circle size = occupancy)', fontsize=12, weight='bold')480ax4.set_yticks([])481ax4.grid(True, alpha=0.3, axis='x')482483plt.tight_layout()484plt.savefig('metapopulation_source_sink.pdf', dpi=300, bbox_inches='tight')485plt.close()486487# Calculate source-sink statistics488source_occupancy = np.mean(equilibrium_state[source_patches])489sink_occupancy = np.mean(equilibrium_state[sink_patches])490num_sinks = np.sum(sink_patches)491num_sources = np.sum(source_patches)492\end{pycode}493494\begin{figure}[H]495\centering496\includegraphics[width=0.98\textwidth]{metapopulation_source_sink.pdf}497\caption{Source-sink metapopulation dynamics in a landscape with heterogeneous patch quality. \textbf{Panel A}: Patch quality gradient showing \py{num_sources} source patches (positive intrinsic growth, green) and \py{num_sinks} sink patches (negative intrinsic growth, red) where local populations cannot persist without immigration. \textbf{Panel B}: Time series showing source patches maintain higher mean occupancy (\py{f'{source_occupancy:.3f}'}) than sink patches (\py{f'{sink_occupancy:.3f}'}), but sinks persist through continuous immigration rather than going extinct. \textbf{Panel C}: Equilibrium occupancy increases with patch quality, but sink patches show non-zero occupancy due to rescue effects from dispersal. \textbf{Panel D}: Network connectivity structure where circle size represents occupancy probability and gray lines show dispersal connections. This demonstrates that metapopulation persistence depends not only on suitable habitat area but on spatial configuration that allows source populations to subsidize demographic sinks, a critical consideration for reserve network design.}498\end{figure}499500\section{Extinction Debt and Habitat Loss}501502When habitat destruction reduces the number of patches, metapopulation occupancy does not decline instantly to the new equilibrium. Instead, there is a transient period during which patch occupancy exceeds the sustainable level for the reduced habitat network. This creates an \textbf{extinction debt}: species that appear viable are actually committed to future decline.503504\begin{pycode}505# Simulate habitat loss scenario506def habitat_loss_dynamics(t):507"""508Simulate gradual habitat loss reducing colonization rate509"""510if t < 100:511return colonization_rate # initial rate512elif t < 120:513# Gradual habitat loss over 20 years514loss_fraction = (t - 100) / 20515return colonization_rate * (1 - 0.6 * loss_fraction)516else:517return colonization_rate * 0.4 # 60% habitat loss518519def levins_habitat_loss(p, t, e):520"""Levins model with time-varying colonization due to habitat loss"""521c_t = habitat_loss_dynamics(t)522dpdt = c_t * p * (1 - p) - e * p523return dpdt524525# Simulate extinction debt526time_extinction_debt = np.linspace(0, 300, 2000)527initial_p = equilibrium_occupancy528trajectory_habitat_loss = odeint(levins_habitat_loss, initial_p, time_extinction_debt,529args=(extinction_rate,))530531# Calculate new equilibrium after habitat loss532new_colonization = colonization_rate * 0.4533if new_colonization > extinction_rate:534new_equilibrium = 1 - extinction_rate / new_colonization535else:536new_equilibrium = 0537538# Calculate extinction debt (difference between current and equilibrium occupancy)539extinction_debt = np.zeros_like(time_extinction_debt)540for i, t in enumerate(time_extinction_debt):541if t < 100:542target_equilibrium = equilibrium_occupancy543else:544target_equilibrium = new_equilibrium545extinction_debt[i] = max(0, trajectory_habitat_loss[i, 0] - target_equilibrium)546547# Time to half-life of debt548if new_equilibrium > 0:549half_debt_occupancy = (trajectory_habitat_loss[2000, 0] + new_equilibrium) / 2550half_life_idx = np.where(trajectory_habitat_loss[1000:, 0] < half_debt_occupancy)[0]551if len(half_life_idx) > 0:552half_life_time = time_extinction_debt[1000 + half_life_idx[0]] - 120553else:554half_life_time = np.inf555else:556half_life_time = np.inf557558# Create extinction debt figure559fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))560561# Panel A: Occupancy trajectory with habitat loss562ax1.plot(time_extinction_debt, trajectory_habitat_loss, 'b-', linewidth=2.5, label='Patch occupancy $p(t)$')563ax1.axhline(equilibrium_occupancy, color='green', linestyle='--', linewidth=2,564label=f'Pre-disturbance equilibrium $p^* = {equilibrium_occupancy:.3f}$')565ax1.axhline(new_equilibrium, color='red', linestyle='--', linewidth=2,566label=f'Post-loss equilibrium $p^* = {new_equilibrium:.3f}$')567ax1.axvline(100, color='orange', linestyle=':', linewidth=2, alpha=0.7,568label='Habitat loss begins')569ax1.axvline(120, color='orange', linestyle=':', linewidth=2, alpha=0.7)570ax1.fill_between([100, 120], 0, 1, alpha=0.1, color='orange', label='Habitat loss period')571ax1.set_xlabel('Time (years)', fontsize=12)572ax1.set_ylabel('Patch Occupancy Fraction $p(t)$', fontsize=12)573ax1.set_title('A) Extinction Debt Following Habitat Loss', fontsize=13, weight='bold')574ax1.legend(loc='upper right', fontsize=10)575ax1.grid(True, alpha=0.3)576ax1.set_xlim(0, 300)577ax1.set_ylim(0, 1)578579# Annotate regions580ax1.annotate('Stable state', xy=(50, equilibrium_occupancy + 0.05),581fontsize=10, ha='center', color='green', weight='bold')582ax1.annotate('Transient excess\n(extinction debt)',583xy=(180, (trajectory_habitat_loss[1200, 0] + new_equilibrium) / 2),584fontsize=10, ha='center', color='red', weight='bold',585bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))586587# Panel B: Extinction debt magnitude over time588ax2.fill_between(time_extinction_debt, 0, extinction_debt, alpha=0.4, color='red',589label='Extinction debt (excess occupancy)')590ax2.plot(time_extinction_debt, extinction_debt, 'r-', linewidth=2)591ax2.axvline(100, color='orange', linestyle=':', linewidth=2, alpha=0.7)592ax2.axvline(120, color='orange', linestyle=':', linewidth=2, alpha=0.7)593ax2.set_xlabel('Time (years)', fontsize=12)594ax2.set_ylabel('Extinction Debt\n(Occupancy - Equilibrium)', fontsize=12)595ax2.set_title('B) Magnitude of Extinction Debt', fontsize=13, weight='bold')596ax2.grid(True, alpha=0.3)597ax2.set_xlim(0, 300)598ax2.legend(loc='upper right', fontsize=10)599600# Add half-life annotation if calculable601if half_life_time < 200:602ax2.annotate(f'Half-life: {half_life_time:.1f} years',603xy=(120 + half_life_time, extinction_debt[1000 + half_life_idx[0]]),604xytext=(180, 0.25), fontsize=10,605arrowprops=dict(arrowstyle='->', color='black', lw=1.5),606bbox=dict(boxstyle='round', facecolor='yellow', alpha=0.7))607608plt.tight_layout()609plt.savefig('metapopulation_extinction_debt.pdf', dpi=300, bbox_inches='tight')610plt.close()611612# Calculate debt statistics613max_debt = np.max(extinction_debt)614debt_at_200yrs = extinction_debt[np.argmin(np.abs(time_extinction_debt - 200))]615\end{pycode}616617\begin{figure}[H]618\centering619\includegraphics[width=0.95\textwidth]{metapopulation_extinction_debt.pdf}620\caption{Extinction debt dynamics following habitat loss in a Levins metapopulation. At year 100, habitat destruction begins, reducing colonization rate by 60\% over a 20-year period (orange shaded region). \textbf{Panel A}: Patch occupancy (blue line) declines gradually from the original equilibrium $p^* = \py{f'{equilibrium_occupancy:.3f}'}$ toward the new sustainable level $p^* = \py{f'{new_equilibrium:.3f}'}$. The delayed response creates a transient period where current occupancy exceeds the carrying capacity of the degraded landscape, representing populations "committed to extinction" despite appearing viable. \textbf{Panel B}: The magnitude of extinction debt (red shading) peaks immediately after habitat loss at \py{f'{max_debt:.3f}'} and decays slowly as patches go extinct. After 200 years, an extinction debt of \py{f'{debt_at_200yrs:.3f}'} remains, indicating that habitat loss effects can persist for centuries. This delayed response has critical implications for conservation: species may appear stable for decades after habitat destruction while actually undergoing cryptic decline toward a lower equilibrium.}621\end{figure}622623\section{Metapopulation Capacity and Reserve Networks}624625The concept of \textbf{metapopulation capacity} $\lambda_M$ extends the Levins model to realistic landscapes by incorporating spatial structure. The metapopulation capacity is the dominant eigenvalue of the colonization-extinction matrix for the patch network, providing a threshold condition for persistence analogous to $c > e$ in the simple Levins model.626627For persistence, the metapopulation capacity must exceed the extinction rate: $\lambda_M > e$. This allows quantitative assessment of reserve network designs.628629\begin{pycode}630# Simulate reserve network design scenarios631np.random.seed(123)632633def calculate_metapopulation_capacity(areas, distances, colonization_coef, distance_decay):634"""635Calculate metapopulation capacity for a patch network636637Based on Hanski & Ovaskainen (2000) formula:638Capacity is largest eigenvalue of M where M_ij = A_i^α A_j^β exp(-d_ij/δ)639"""640n = len(areas)641M = np.zeros((n, n))642643for i in range(n):644for j in range(n):645if i != j:646# Colonization from j to i647M[i, j] = colonization_coef * areas[i]**0.5 * areas[j]**0.5 * \648np.exp(-distance_decay * distances[i, j])649650eigenvalues = np.linalg.eigvals(M)651capacity = np.max(np.real(eigenvalues))652return capacity653654# Scenario 1: Current reserve network (moderate fragmentation)655n_reserves_current = 15656reserve_areas_current = np.random.gamma(3, 2, n_reserves_current)657658# Generate distance matrix659reserve_positions = np.random.uniform(0, 50, n_reserves_current)660distance_matrix_current = np.abs(reserve_positions[:, np.newaxis] - reserve_positions[np.newaxis, :])661662capacity_current = calculate_metapopulation_capacity(reserve_areas_current, distance_matrix_current,663colonization_coef=0.15, distance_decay=0.2)664665# Scenario 2: Further fragmentation (smaller, more isolated reserves)666reserve_areas_fragmented = reserve_areas_current * 0.5 # halve areas667distance_matrix_fragmented = distance_matrix_current * 1.5 # increase isolation668669capacity_fragmented = calculate_metapopulation_capacity(reserve_areas_fragmented,670distance_matrix_fragmented,671colonization_coef=0.15, distance_decay=0.2)672673# Scenario 3: Adding corridors (reduced effective distance)674distance_matrix_corridors = distance_matrix_current * 0.7 # corridors reduce effective distance675676capacity_corridors = calculate_metapopulation_capacity(reserve_areas_current,677distance_matrix_corridors,678colonization_coef=0.15, distance_decay=0.2)679680# Scenario 4: Larger reserves (double area)681reserve_areas_enlarged = reserve_areas_current * 2682683capacity_enlarged = calculate_metapopulation_capacity(reserve_areas_enlarged,684distance_matrix_current,685colonization_coef=0.15, distance_decay=0.2)686687# Create comparison figure688scenarios = ['Current\nNetwork', 'Fragmentation\n(50% area)',689'Add Corridors\n(30% closer)', 'Enlarge Reserves\n(2x area)']690capacities = [capacity_current, capacity_fragmented, capacity_corridors, capacity_enlarged]691colors_scenario = ['gray', 'red', 'green', 'blue']692693fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))694695# Panel A: Metapopulation capacity comparison696bars = ax1.bar(scenarios, capacities, color=colors_scenario, alpha=0.7, edgecolor='black', linewidth=2)697ax1.axhline(extinction_rate, color='red', linestyle='--', linewidth=2.5,698label=f'Extinction threshold $\\lambda_M = e = {extinction_rate:.2f}$')699ax1.set_ylabel('Metapopulation Capacity $\\lambda_M$', fontsize=12)700ax1.set_title('A) Reserve Network Scenarios', fontsize=13, weight='bold')701ax1.legend(loc='upper left', fontsize=10)702ax1.grid(True, alpha=0.3, axis='y')703ax1.set_ylim(0, max(capacities) * 1.2)704705# Add viability labels706for i, (cap, scenario) in enumerate(zip(capacities, scenarios)):707if cap > extinction_rate:708label = 'VIABLE'709color = 'green'710else:711label = 'EXTINCT'712color = 'red'713ax1.text(i, cap + 0.005, label, ha='center', fontsize=9, weight='bold', color=color)714715# Panel B: Reserve network spatial layout (current vs fragmented)716ax2_inset = ax2.inset_axes([0.05, 0.55, 0.4, 0.4])717718# Main plot: current network719for i in range(n_reserves_current):720circle_size = reserve_areas_current[i] * 100721ax2.scatter(reserve_positions[i], 1, s=circle_size, c='gray', alpha=0.6,722edgecolors='black', linewidth=1.5)723724# Draw connections for strong links725for j in range(i+1, n_reserves_current):726connection_strength = 0.15 * reserve_areas_current[i]**0.5 * \727reserve_areas_current[j]**0.5 * \728np.exp(-0.2 * distance_matrix_current[i, j])729if connection_strength > 0.05:730ax2.plot([reserve_positions[i], reserve_positions[j]], [1, 1],731'gray', alpha=0.3, linewidth=connection_strength*30)732733ax2.set_xlim(-5, 55)734ax2.set_ylim(0.5, 1.5)735ax2.set_xlabel('Spatial Position (km)', fontsize=11)736ax2.set_title('B) Current Network Connectivity', fontsize=12, weight='bold')737ax2.set_yticks([])738ax2.text(25, 1.3, f'$\\lambda_M = {capacity_current:.3f}$', fontsize=12, ha='center',739bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.7))740741# Inset: fragmented network742for i in range(n_reserves_current):743circle_size = reserve_areas_fragmented[i] * 100744ax2_inset.scatter(reserve_positions[i], 1, s=circle_size, c='red', alpha=0.6,745edgecolors='darkred', linewidth=1)746747ax2_inset.set_xlim(-5, 55)748ax2_inset.set_ylim(0.5, 1.5)749ax2_inset.set_title('Fragmented (smaller, isolated)', fontsize=9)750ax2_inset.set_xticks([])751ax2_inset.set_yticks([])752ax2_inset.text(25, 1.25, f'$\\lambda_M = {capacity_fragmented:.3f}$', fontsize=9, ha='center',753bbox=dict(boxstyle='round', facecolor='pink', alpha=0.7))754755plt.tight_layout()756plt.savefig('metapopulation_capacity_scenarios.pdf', dpi=300, bbox_inches='tight')757plt.close()758759# Calculate relative changes760capacity_change_fragmented = ((capacity_fragmented - capacity_current) / capacity_current) * 100761capacity_change_corridors = ((capacity_corridors - capacity_current) / capacity_current) * 100762capacity_change_enlarged = ((capacity_enlarged - capacity_current) / capacity_current) * 100763\end{pycode}764765\begin{figure}[H]766\centering767\includegraphics[width=0.98\textwidth]{metapopulation_capacity_scenarios.pdf}768\caption{Metapopulation capacity ($\lambda_M$) for alternative reserve network designs. \textbf{Panel A}: Comparison of four management scenarios showing how landscape configuration affects viability. The current network maintains $\lambda_M = \py{f'{capacity_current:.3f}'}$ above the extinction threshold ($e = \py{extinction_rate}$), ensuring metapopulation persistence. Fragmenting reserves by reducing area 50\% causes a \py{f'{abs(capacity_change_fragmented):.1f}'}\% decline to $\lambda_M = \py{f'{capacity_fragmented:.3f}'}$, potentially pushing the metapopulation below viability. Adding habitat corridors that reduce effective isolation by 30\% increases capacity by \py{f'{capacity_change_corridors:.1f}'}\% to $\lambda_M = \py{f'{capacity_corridors:.3f}'}$, while doubling reserve areas yields a \py{f'{capacity_change_enlarged:.1f}'}\% increase to $\lambda_M = \py{f'{capacity_enlarged:.3f}'}$. \textbf{Panel B}: Spatial configuration of the current reserve network (circle size proportional to area, gray lines show strong connectivity). Inset shows the fragmented scenario with smaller, more isolated patches and reduced connectivity. This demonstrates that metapopulation viability depends on the entire landscape configuration, not just total habitat area, with corridors and patch size having quantifiable effects on persistence probability.}769\end{figure}770771\section{Results Summary}772773Our computational analysis of metapopulation dynamics reveals fundamental principles governing population persistence in fragmented landscapes:774775\begin{enumerate}776\item \textbf{Colonization-Extinction Balance}: The Levins model equilibrium $p^* = 1 - e/c$ demonstrates that metapopulation persistence requires colonization rate ($c = \py{colonization_rate}$) to exceed extinction rate ($e = \py{extinction_rate}$), yielding equilibrium occupancy of \py{f'{equilibrium_occupancy:.3f}'} for our parameter set.777778\item \textbf{Extinction Threshold}: Metapopulations face an abrupt transition to extinction when the colonization-extinction ratio falls below unity ($c/e < 1$). Our current system maintains $c/e = \py{f'{critical_ratio:.2f}'}$, well above the critical threshold.779780\item \textbf{Patch Heterogeneity}: In realistic landscapes with heterogeneous patch sizes and isolation, incidence functions show that \py{f'{viable_patch_fraction*100:.1f}'}\% of patches support viable populations, with mean equilibrium occupancy of \py{f'{mean_incidence:.3f}'} for occupied patches.781782\item \textbf{Source-Sink Dynamics}: High-quality source patches (mean occupancy \py{f'{source_occupancy:.3f}'}) subsidize demographic sinks (mean occupancy \py{f'{sink_occupancy:.3f}'}), demonstrating that regional persistence can exceed predictions based on local population viability alone.783784\item \textbf{Extinction Debt}: Following 60\% habitat loss, the metapopulation carries an extinction debt that peaks at \py{f'{max_debt:.3f}'} excess occupancy and persists for centuries (debt of \py{f'{debt_at_200yrs:.3f}'} after 200 years), indicating delayed responses to environmental change.785786\item \textbf{Metapopulation Capacity}: Reserve network design critically affects viability through metapopulation capacity $\lambda_M$. Fragmenting the current network reduces capacity by \py{f'{abs(capacity_change_fragmented):.1f}'}\%, while corridors increase it by \py{f'{capacity_change_corridors:.1f}'}\% and larger reserves by \py{f'{capacity_change_enlarged:.1f}'}\%.787\end{enumerate}788789\begin{pycode}790# Generate summary table791print(r'\begin{table}[H]')792print(r'\centering')793print(r'\caption{Key Metapopulation Dynamics Parameters and Results}')794print(r'\begin{tabular}{@{}lcc@{}}')795print(r'\toprule')796print(r'\textbf{Parameter/Result} & \textbf{Value} & \textbf{Interpretation} \\')797print(r'\midrule')798print(f"Colonization rate $c$ & {colonization_rate:.3f} yr$^{{-1}}$ & Patch colonization coefficient \\\\")799print(f"Extinction rate $e$ & {extinction_rate:.3f} yr$^{{-1}}$ & Local extinction probability \\\\")800print(f"Equilibrium occupancy $p^*$ & {equilibrium_occupancy:.3f} & Levins model equilibrium \\\\")801print(f"$c/e$ ratio & {critical_ratio:.2f} & Exceeds threshold (viable) \\\\")802print(r'\midrule')803print(f"Viable patch fraction & {viable_patch_fraction*100:.1f}\\% & Heterogeneous landscape \\\\")804print(f"Source patch occupancy & {source_occupancy:.3f} & High-quality patches \\\\")805print(f"Sink patch occupancy & {sink_occupancy:.3f} & Immigration-dependent \\\\")806print(r'\midrule')807print(f"Max extinction debt & {max_debt:.3f} & Post-habitat loss \\\\")808print(f"Debt at 200 years & {debt_at_200yrs:.3f} & Long-term legacy \\\\")809print(r'\midrule')810print(f"Current $\\lambda_M$ & {capacity_current:.3f} & Viable network \\\\")811print(f"Fragmented $\\lambda_M$ & {capacity_fragmented:.3f} & Reduced viability \\\\")812print(f"Corridor effect & +{capacity_change_corridors:.1f}\\% & Improved connectivity \\\\")813print(r'\bottomrule')814print(r'\end{tabular}')815print(r'\end{table}')816\end{pycode}817818\section{Conclusions}819820This computational analysis demonstrates that metapopulation persistence in fragmented landscapes depends fundamentally on the balance between colonization and extinction at the patch scale. The classical Levins model reveals that regional persistence requires colonization rates to exceed extinction rates ($c > e$), yielding an equilibrium occupancy of $p^* = \py{f'{equilibrium_occupancy:.3f}'}$ for our parameter set with $c = \py{colonization_rate}$ and $e = \py{extinction_rate}$. This threshold structure implies that habitat loss reducing colonization rates can trigger abrupt metapopulation collapse when the colonization-extinction ratio falls below unity, even when substantial habitat remains.821822Extensions to heterogeneous landscapes reveal that patch-specific characteristics create incidence functions where only \py{f'{viable_patch_fraction*100:.1f}'}\% of patches maintain positive equilibrium occupancy. Source-sink dynamics demonstrate that high-quality patches (mean occupancy \py{f'{source_occupancy:.3f}'}) can subsidize populations in demographic sinks (occupancy \py{f'{sink_occupancy:.3f}'}), extending metapopulation range beyond areas capable of supporting self-sustaining populations. However, this spatial subsidy depends on maintained connectivity, which habitat fragmentation systematically erodes.823824Perhaps most critically for conservation, the extinction debt phenomenon shows that metapopulation responses to habitat loss are delayed, not instantaneous. Following 60\% habitat destruction in our simulation, excess occupancy peaked at \py{f'{max_debt:.3f}'} and persisted for centuries (debt \py{f'{debt_at_200yrs:.3f}'} after 200 years), indicating that species may appear stable for decades while undergoing cryptic decline toward lower equilibria. This temporal lag complicates conservation assessment and may lead to systematic underestimation of extinction risk.825826The metapopulation capacity framework provides a quantitative tool for reserve network design, showing that current configuration maintains $\lambda_M = \py{f'{capacity_current:.3f}'}$ above the extinction threshold. However, further fragmentation reducing patch areas by 50\% would decrease capacity by \py{f'{abs(capacity_change_fragmented):.1f}'}\%, potentially pushing the system below viability. Conversely, habitat corridors reducing effective isolation increase capacity by \py{f'{capacity_change_corridors:.1f}'}\%, demonstrating that connectivity restoration can be as effective as habitat expansion for metapopulation conservation.827828These results underscore that persistence in fragmented landscapes requires not just sufficient total habitat area, but appropriate spatial configuration maintaining colonization-extinction balance across patch networks. Conservation strategies must account for metapopulation dynamics when designing reserves, prioritizing both patch size (to reduce extinction rates) and connectivity (to maintain colonization rates) to ensure long-term population viability.829830\bibliographystyle{ecology}831\begin{thebibliography}{99}832833\bibitem{levins1969some}834Levins, R. (1969). Some demographic and genetic consequences of environmental heterogeneity for biological control. \textit{Bulletin of the Entomological Society of America}, 15(3), 237--240.835836\bibitem{hanski1999metapopulation}837Hanski, I. (1999). \textit{Metapopulation Ecology}. Oxford University Press, Oxford.838839\bibitem{fahrig2003effects}840Fahrig, L. (2003). Effects of habitat fragmentation on biodiversity. \textit{Annual Review of Ecology, Evolution, and Systematics}, 34, 487--515.841842\bibitem{hanski1998metapopulation}843Hanski, I. (1998). Metapopulation dynamics. \textit{Nature}, 396(6706), 41--49.844845\bibitem{hanski2000metapopulation}846Hanski, I., \& Ovaskainen, O. (2000). The metapopulation capacity of a fragmented landscape. \textit{Nature}, 404(6779), 755--758.847848\bibitem{tilman1994habitat}849Tilman, D., May, R. M., Lehman, C. L., \& Nowak, M. A. (1994). Habitat destruction and the extinction debt. \textit{Nature}, 371(6492), 65--66.850851\bibitem{pulliam1988sources}852Pulliam, H. R. (1988). Sources, sinks, and population regulation. \textit{American Naturalist}, 132(5), 652--661.853854\bibitem{brown2001turnover}855Brown, J. H., \& Kodric-Brown, A. (1977). Turnover rates in insular biogeography: effect of immigration on extinction. \textit{Ecology}, 58(2), 445--449.856857\bibitem{harrison1991local}858Harrison, S. (1991). Local extinction in a metapopulation context: an empirical evaluation. \textit{Biological Journal of the Linnean Society}, 42(1-2), 73--88.859860\bibitem{hanski1994practical}861Hanski, I., Pakkala, T., Kuussaari, M., \& Lei, G. (1995). Metapopulation persistence of an endangered butterfly in a fragmented landscape. \textit{Oikos}, 72(1), 21--28.862863\bibitem{sjogren1991extinction}864Sj\"ogren-Gulve, P. (1994). Distribution and extinction patterns within a northern metapopulation of the pool frog, \textit{Rana lessonae}. \textit{Ecology}, 75(5), 1357--1367.865866\bibitem{moilanen1998metapopulation}867Moilanen, A. (1999). Patch occupancy models of metapopulation dynamics: efficient parameter estimation using implicit statistical inference. \textit{Ecology}, 80(3), 1031--1043.868869\bibitem{etienne2004estimating}870Etienne, R. S., ter Braak, C. J., \& Vos, C. C. (2004). Application of stochastic patch occupancy models to real metapopulations. In I. Hanski \& O. E. Gaggiotti (Eds.), \textit{Ecology, Genetics and Evolution of Metapopulations} (pp. 105--132). Academic Press.871872\bibitem{ovaskainen2002metapopulation}873Ovaskainen, O., \& Hanski, I. (2002). Transient dynamics in metapopulation response to perturbation. \textit{Theoretical Population Biology}, 61(3), 285--295.874875\bibitem{wahlberg2002metapopulation}876Wahlberg, N., Klemetti, T., \& Hanski, I. (2002). Dynamic populations in a dynamic landscape: the metapopulation structure of the marsh fritillary butterfly. \textit{Ecography}, 25(2), 224--232.877878\bibitem{clinchy2002predator}879Clinchy, M., Haydon, D. T., \& Smith, A. T. (2002). Pattern does not equal process: what does patch occupancy really tell us about metapopulation dynamics? \textit{The American Naturalist}, 159(4), 351--362.880881\bibitem{keyghobadi2005metapopulation}882Keyghobadi, N., Roland, J., \& Strobeck, C. (2005). Genetic differentiation and gene flow among populations of the alpine butterfly, \textit{Parnassius smintheus}, vary with landscape connectivity. \textit{Molecular Ecology}, 14(7), 1897--1909.883884\bibitem{matter2003determinants}885Matter, S. F. (2003). Determinants of local extinction and colonization in a metapopulation of the checkered white butterfly \textit{Pontia protodice}. \textit{Oecologia}, 135(2), 151--156.886887\bibitem{kindvall1996habitat}888Kindvall, O. (1996). Habitat heterogeneity and survival in a bush cricket metapopulation. \textit{Ecology}, 77(1), 207--214.889890\bibitem{fleishman2002influence}891Fleishman, E., Ray, C., Sj\"ogren-Gulve, P., Boggs, C. L., \& Murphy, D. D. (2002). Assessing the roles of patch quality, area, and isolation in predicting metapopulation dynamics. \textit{Conservation Biology}, 16(3), 706--716.892893\end{thebibliography}894895\end{document}896897898