Model
Model is the central object in laser.cohorts. It holds the scenario, parameters, and component list, allocates all simulation arrays, and runs the tick loop.
Lifecycle
Every simulation goes through three phases:
1 2 3 4 5 | |
1. Construct
1 2 3 4 5 6 7 8 9 10 11 12 | |
scenario is a GeoDataFrame where each row is a node. Any columns you add (S, I, R, …) become the initial conditions read by each component's setup().
params is a PropertySet that must include nticks. Components may also read arbitrary keys from params (e.g. params.beta) at construction time.
2. Assign components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Assigning model.components triggers three things in order:
- State collection — each component's
statesproperty is queried; the union of all unique state names determines the compartments allocated. - Array allocation —
model.states(aStateArrayof shape(nticks+1, n_states, n_nodes)) and all node property arrays are created. - Setup — each component's
setup()is called, seeding initial conditions fromscenario.
Attempting to read model.states before assigning model.components raises AttributeError.
3. Run
1 | |
Steps the simulation for params.nticks ticks. See The tick loop below.
The tick loop
Each tick executes in this order:
1 2 3 4 5 6 7 | |
The carry-forward runs before any component sees the tick. Components read and write states[tick+1] during their step(), starting from the carried-forward values.
Accessing results
model.states is a StateArray — a NumPy array subclass that exposes named compartment slices as attributes.
1 2 3 4 5 6 7 8 9 10 | |
Node properties (e.g. per-tick flow counts recorded by components) are on model.nodes:
1 2 | |
Selective carry-forward
By default every compartment state is carried from tick t to tick t+1. Pass carry_forward_states to restrict this to a subset:
1 | |
States not in the list start at zero on each tick — they accumulate only what components write into states[tick+1] during that tick's step(). Passing an unknown state name raises ValueError when model.components is assigned.
Selective carry-forward is most useful when a custom component completely replaces a state each tick and carry-forward would interfere with that logic.
Inter-node mixing
model.network is a 2-D array of shape (n_nodes, n_nodes) whose entry [i, j] is the connectivity weight from node i to node j. The transmission components use this matrix to spread force of infection across nodes.
1 2 3 4 5 6 | |
The default is an all-zero matrix (no inter-node coupling).
Note
model.network must be assigned before model.components, because the
transmission component's setup() does not cache the network array — it
reads model.network live during each step().