synthetic#
Synthetic scenario builders for laser-measles models.
Overview#
Every laser-measles model (ABM, Biweekly, Compartmental) requires a scenario: a Polars DataFrame with one row per geographic patch. This module provides ready-made scenario builders for testing and development. For production use, supply your own DataFrame following the schema below.
Correct import paths#
Import the module:
from laser.measles.scenarios import synthetic
scenario = synthetic.single_patch_scenario(population=50_000, mcv1_coverage=0.8)
Or import individual functions directly:
from laser.measles.scenarios.synthetic import single_patch_scenario, two_patch_scenario
from laser.measles.scenarios import single_patch_scenario # also re-exported here
NEVER write import laser_measles or from laser_measles import ....
The package is always laser.measles (dot, not underscore).
Scenario DataFrame schema#
All scenario DataFrames must contain at least these five columns:
Column |
Dtype |
Description |
|---|---|---|
id |
Utf8/str |
Unique string identifier for the patch.
Examples: |
pop |
Int64 |
Total population of the patch (integer). |
lat |
Float64 |
Latitude of the patch centroid (degrees). |
lon |
Float64 |
Longitude of the patch centroid (degrees). |
mcv1 |
Float64 |
Routine MCV1 vaccination coverage, 0.0-1.0. |
Critical schema notes:
idmust be a string (pl.Utf8). Integer IDs will fail validation.popmust be namedpop, notpopulation.mcv1must be present even when vaccination is irrelevant to your analysis (use0.0as a placeholder).Extra columns are allowed and are ignored by the model.
Building a scenario by hand (no helper function needed)#
import polars as pl
scenario = pl.DataFrame({
"id": ["patch_0", "patch_1", "patch_2"],
"pop": [200_000, 150_000, 80_000],
"lat": [40.0, 38.5, 36.0],
"lon": [4.0, 6.0, 8.0],
"mcv1": [0.85, 0.70, 0.60],
})
Available helper functions#
- single_patch_scenario(population, mcv1_coverage)
One patch. Useful for the simplest possible “hello world” run:
from laser.measles.scenarios.synthetic import single_patch_scenario scenario = single_patch_scenario(population=10_000, mcv1_coverage=0.0)
- two_patch_scenario(population, mcv1_coverage)
Two patches; the second patch has half the population of the first:
from laser.measles.scenarios.synthetic import two_patch_scenario scenario = two_patch_scenario(population=100_000, mcv1_coverage=0.8)
- two_cluster_scenario(seed, n_nodes_per_cluster, …)
100 patches arranged in two geographic clusters, with randomised populations and MCV1 coverage in a configurable range. Good for spatial spread studies:
from laser.measles.scenarios.synthetic import two_cluster_scenario scenario = two_cluster_scenario(seed=42, n_nodes_per_cluster=50)
- satellites_scenario(core_population, satellite_population, n_towns, …)
One large central city surrounded by smaller satellite towns — a classic city-and-hinterland structure:
from laser.measles.scenarios.synthetic import satellites_scenario scenario = satellites_scenario(core_population=500_000, n_towns=30, mcv1=0.5)
Connecting a scenario to a model#
Pass the DataFrame directly as the first argument to any model constructor:
from laser.measles.abm import ABMModel, ABMParams
from laser.measles.scenarios.synthetic import single_patch_scenario
scenario = single_patch_scenario(population=50_000, mcv1_coverage=0.85)
params = ABMParams(num_ticks=365, seed=42, start_time="2000-01")
model = ABMModel(scenario, params)
The same pattern applies to BiweeklyModel and CompartmentalModel.
Functions
Create a cluster of nodes with a single large node in the center (core) surrounded by smaller nodes (satellites). |
|
Generate a synthetic scenario with a single patch. |
|
Generate a synthetic scenario with two clusters of nodes. |
|
Generate a synthetic scenario with two patches where one is half the size of the other. |