Note
Go to the end to download the full example code.
Run a Model¶
This example demonstrates basic usage of the Spatiocoexistence model.
Necessary imports
from spatiocoexistence import Model, Inventory
from spatiocoexistence.data import inventory_file, parameter_file
Initialize the model with inventory and parameter files This model will be simulated on a single thread. If an integer greater than 1 is used for ‘threads’, the simulation will run in parallel on that many threads.
inventory = Inventory.from_data(inventory_file)
model = Model(initial_inventory=inventory, parameters=parameter_file, threads=1)
Get the current parameter values and modify them
parameter_old = model.parameters
# update the minimal survival probability of the recruits, increase the radius to 20m and the dispersal range for seeds to 25m
model.update_parameters(
{"min_recruit_survival": 0.9, "neighborhood_radius": 20, "sigma_dispersal": 25.0}
)
print(
"Original parameters (subset):",
{
k: parameter_old[k]
for k in ["neighborhood_radius", "sigma_dispersal", "min_recruit_survival"]
},
)
print(
"Updated parameters (subset):",
{
k: model.parameters[k]
for k in ["neighborhood_radius", "sigma_dispersal", "min_recruit_survival"]
},
)
Original parameters (subset): {'neighborhood_radius': 10, 'sigma_dispersal': 14.0, 'min_recruit_survival': 0.88}
Updated parameters (subset): {'neighborhood_radius': 20, 'sigma_dispersal': 25.0, 'min_recruit_survival': 0.9}
Run a short simulation of 100 steps (each step represents 5 years)
model.step(100)
step: 1 year: 5
step: 2 year: 10
step: 3 year: 15
step: 4 year: 20
step: 5 year: 25
step: 6 year: 30
step: 7 year: 35
step: 8 year: 40
step: 9 year: 45
step: 10 year: 50
step: 11 year: 55
step: 12 year: 60
step: 13 year: 65
step: 14 year: 70
step: 15 year: 75
step: 16 year: 80
step: 17 year: 85
step: 18 year: 90
step: 19 year: 95
step: 20 year: 100
step: 21 year: 105
step: 22 year: 110
step: 23 year: 115
step: 24 year: 120
step: 25 year: 125
step: 26 year: 130
step: 27 year: 135
step: 28 year: 140
step: 29 year: 145
step: 30 year: 150
step: 31 year: 155
step: 32 year: 160
step: 33 year: 165
step: 34 year: 170
step: 35 year: 175
step: 36 year: 180
step: 37 year: 185
step: 38 year: 190
step: 39 year: 195
step: 40 year: 200
step: 41 year: 205
step: 42 year: 210
step: 43 year: 215
step: 44 year: 220
step: 45 year: 225
step: 46 year: 230
step: 47 year: 235
step: 48 year: 240
step: 49 year: 245
step: 50 year: 250
step: 51 year: 255
step: 52 year: 260
step: 53 year: 265
step: 54 year: 270
step: 55 year: 275
step: 56 year: 280
step: 57 year: 285
step: 58 year: 290
step: 59 year: 295
step: 60 year: 300
step: 61 year: 305
step: 62 year: 310
step: 63 year: 315
step: 64 year: 320
step: 65 year: 325
step: 66 year: 330
step: 67 year: 335
step: 68 year: 340
step: 69 year: 345
step: 70 year: 350
step: 71 year: 355
step: 72 year: 360
step: 73 year: 365
step: 74 year: 370
step: 75 year: 375
step: 76 year: 380
step: 77 year: 385
step: 78 year: 390
step: 79 year: 395
step: 80 year: 400
step: 81 year: 405
step: 82 year: 410
step: 83 year: 415
step: 84 year: 420
step: 85 year: 425
step: 86 year: 430
step: 87 year: 435
step: 88 year: 440
step: 89 year: 445
step: 90 year: 450
step: 91 year: 455
step: 92 year: 460
step: 93 year: 465
step: 94 year: 470
step: 95 year: 475
step: 96 year: 480
step: 97 year: 485
step: 98 year: 490
step: 99 year: 495
step: 100 year: 500
Access the updated inventory after simulation
inv = model.inventory
# Basic analyses on the resulting inventory
num_individuals = inv.x.shape[0]
mean_dbh = inv.dbh.mean()
max_species_id = inv.species.max()
abundances = inv.species_abundance()
print(f"Number of individuals after 100 steps: {num_individuals}")
print(f"Mean DBH (dm) after 100 steps: {mean_dbh:.3f}")
print("Species abundance distribution (counts per species):", abundances[0])
Number of individuals after 100 steps: 24267
Mean DBH (dm) after 100 steps: 1.274
Species abundance distribution (counts per species): 0
Show plot of the current inventory state.
inv.plot(threshold=50, filter=1.0)
/builds/heinzej/CrowdingIndex/spatiocoexistence/inventory/_plotting.py:685: RuntimeWarning: divide by zero encountered in log
log_abundance = np.log(sorted_abundance)
Demonstrate individual processes on the current state Store initial inventory size for comparison
initial_size = len(model.inventory.data)
print(f"Initial inventory size: {initial_size}")
Initial inventory size: 24267
Apply one growth update and show mean dbh change
prev_mean_dbh = model.inventory.dbh.mean()
delta_dbh = model.growth()
post_growth_mean_dbh = model.inventory.dbh.mean()
print(
f"Mean DBH before growth: {prev_mean_dbh:.3f} -> after growth: {post_growth_mean_dbh:.3f}"
)
print(f"Mean DBH increase: {delta_dbh.mean():.4f}")
Mean DBH before growth: 1.274 -> after growth: 1.383
Mean DBH increase: 0.0000
Apply mortality and report how many died Note: Dead individuals are now automatically removed from the inventory
deads_inventory = model.mortality()
print(
f"Mortality event: {deads_inventory.data.shape[0]} individuals died and were removed."
)
print(f"Inventory size after mortality: {model.inventory.data.shape[0]}")
deads_inventory.plot_map(filter=0)
Mortality event: 2263 individuals died and were removed.
Inventory size after mortality: 22004
Apply recruitment and get new recruits as an Inventory object The recruits are automatically added to the main inventory
recruits_inventory = model.recruitment()
print(f"\nRecruitment event: {len(recruits_inventory.data)} new individuals recruited")
print(f"Inventory size after recruitment: {len(model.inventory.data)}")
recruits_inventory.plot_map(filter=0, scale=10)
Recruitment event: 2614 new individuals recruited
Inventory size after recruitment: 24618
Total running time of the script: (0 minutes 10.376 seconds)