propagator.core
High-level simulation primitives and facades for running PROPAGATOR from Python.
The sections below cover the public API exposed by propagator.core along with
the supporting data models and scheduling helpers.
Public Facade
propagator.core
Package init for the wildfire propagator core.
BoundaryConditions(time, moisture=None, wind_dir=None, wind_speed=None, ignitions=None, additional_moisture=None, vegetation_changes=None)
dataclass
Boundary conditions applied at or after a given simulation time.
Attributes:
| Name | Type | Description |
|---|---|---|
time |
int
|
Simulation time the conditions refer to (seconds from simulation start). |
moisture |
Optional[NDArray[floating]]
|
Fuel moisture map (%). |
wind_dir |
Optional[NDArray[floating]]
|
Wind direction map (weather convention, degrees clockwise, north is 0). |
wind_speed |
Optional[NDArray[floating]]
|
Wind speed map (km/h). |
ignitions |
Optional[
|
npt.NDArray[np.bool_] | list[tuple[int, int] | tuple[int, int, int]] |
] |
Ignitions to enqueue. Accepts either a boolean raster (2D applies to
every realization; 3D maps explicit |
|
additional_moisture |
Optional[NDArray[floating]]
|
Extra moisture to add to fuel (%), can be sparse. |
vegetation_changes |
Optional[NDArray[floating]]
|
Raster of vegetation type overrides (NaN to skip). |
PropagatorStats(n_active, area_mean, area_50, area_75, area_90)
dataclass
Summary statistics for the current simulation state.
to_dict(c_time, ref_date)
Serialize stats with the current simulation time expressed in seconds.
Propagator(veg, dem, fuels=(lambda: FUEL_SYSTEM_LEGACY)(), cellsize=CELLSIZE, do_spotting=False, realizations=REALIZATIONS, p_time_fn=get_p_time_fn(ROS_DEFAULT), p_moist_fn=get_p_moisture_fn(MOISTURE_MODEL_DEFAULT), out_of_bounds_mode='raise')
dataclass
Stochastic cellular wildfire spread simulator.
PROPAGATOR evolves a binary fire state over a regular grid for a configurable number of realizations. Spread depends on vegetation, topography and environmental drivers (wind, moisture) through pluggable probability and travel-time functions.
Attributes:
| Name | Type | Description |
|---|---|---|
veg |
ndarray
|
2D array of vegetation codes as defined in the provided FuelSystem |
dem |
ndarray
|
2D array of elevation values (meters above sea level). |
fuels |
(FuelSystem, optional)
|
Object defining fuels types and fire propagation probability between fuel types |
cellsize |
(float, optional)
|
The size of lattice (meters). |
do_spotting |
(bool, optional)
|
Whether to enable fire-spotting in the model. |
realizations |
(int, optional)
|
Number of stochastic realizations to simulate. |
p_time_fn |
(Any, optional)
|
The function to compute the spread time (must be jit-compiled). Units are compliant with other functions. signature: (v0: float, dh: float, angle_to: float, dist: float, moist: float, w_dir: float, w_speed: float) -> tuple[float, float] |
p_moist_fn |
(Any, optional)
|
The function to compute the moisture probability (must be jit-compiled) Units are compliant with other functions. signature: (moist: float) -> float |
out_of_bounds_mode |
(Literal['ignore', 'error'], optional)
|
Whether to raise an error if out-of-bounds updates are detected. Default is "error". |
compute_fire_probability()
Return mean burn probability across realizations for each cell.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array with values in [0, 1]. |
compute_spotting_generation_probability()
Return per-cell spotting generation probability.
compute_spotting_receiving_probability()
Return per-cell spotting receiving probability.
compute_ros_max()
Return per-cell maximum Rate of Spread across realizations.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array with max RoS per cell. |
compute_arrival_time_min()
Return per-cell minimum arrival time across realizations.
compute_arrival_time_mean()
Return per-cell mean arrival time across realizations where burned.
compute_ros_mean()
Return per-cell mean Rate of Spread, ignoring zeros as no-spread.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array with mean RoS per cell. |
compute_fireline_int_max()
Return per-cell maximum fireline intensity across realizations.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array of max intensity values. |
compute_fireline_int_mean()
Return per-cell mean fireline intensity, ignoring zeros as no-spread.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array of mean intensity values. |
compute_stats(values)
Compute simple area-based stats and number of active cells.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
ndarray
|
Fire probability map in [0, 1]. |
required |
Returns:
| Type | Description |
|---|---|
PropagatorStats
|
Dataclass with counters and area summaries. |
set_boundary_conditions(boundary_condition)
Externally set boundary conditions at desired time in the scheduler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
boundary_condition
|
BoundaryConditions
|
Conditions to apply. |
required |
step(seconds=None, *, until=None)
Advance the simulation to the next scheduled time and update state.
get_output()
Assemble the current outputs and summary stats into a dataclass.
Returns: PropagatorOutput: Snapshot of fire probability, RoS, intensity, stats.
next_time()
Get the next time step.
Returns: int | None: 0 at initialization; None if no more events; otherwise the next scheduled simulation time.
PropagatorOutOfBoundsError
Bases: Exception
Custom error for out-of-bounds updates in the Propagator.
get_p_moisture_fn(moist_model_code)
Select a moisture probability correction by code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
moist_model_code
|
MoistureModel
|
The code of the moisture model to select. |
required |
Returns:
| Type | Description |
|---|---|
function with signature
|
|
get_p_time_fn(ros_model_code)
Select a rate-of-spread model by code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ros_model_code
|
RateOfSpreadModel
|
The code of the rate-of-spread model to select. |
required |
Returns:
| Type | Description |
|---|---|
function with signature
|
|
Data Models
propagator.core.models
Core wildfire propagation engine.
This module defines the main simulation primitives and the Propagator class
that evolves a fire state over a grid using wind, slope, vegetation, and
moisture inputs. Public dataclasses capture boundary conditions, actions,
summary statistics, and output snapshots suitable for CLI and IO layers.
UpdateBatch(rows=(lambda: np.empty((0,), dtype=(np.int32)))(), cols=(lambda: np.empty((0,), dtype=(np.int32)))(), realizations=(lambda: np.empty((0,), dtype=(np.int32)))(), rates_of_spread=(lambda: np.empty((0,), dtype=(np.float32)))(), fireline_intensities=(lambda: np.empty((0,), dtype=(np.float32)))())
dataclass
get_bbox()
Get bounding box, computing lazily if not yet calculated.
External code should use this instead of accessing .bbox directly to ensure the bbox is computed when needed.
extend(other)
Merge another UpdateBatch into this one.
Concatenates all arrays and invalidates the cached bounding box.
OPTIMIZATION: Previously had complex logic to merge bboxes, checking if either was None, then computing min/max of merged bounds. This was wasteful because: 1. Often the merged bbox is never used 2. If it is used, we can compute it directly from the merged arrays
New approach: Simply invalidate the bbox cache. If someone needs it later via get_bbox(), it will be computed fresh from all data.
Performance: Avoids 8 min/max operations per extend call in the common case where bbox isn't needed afterward.
UpdateBatchWithTime(times, rows, cols, realizations, rates_of_spread, fireline_intensities)
dataclass
split_by_time()
Split updates into separate batches grouped by time.
OPTIMIZATION: This function is called in the hot path (Scheduler.push_updates) and was identified as a major bottleneck. Several optimizations:
-
FAST PATH: Check if all updates are at the same time (common case). If so, avoid array indexing and just wrap the existing arrays. This happens frequently when processing a batch of cells that all spread to neighbors at the same relative time.
-
REDUCED OBJECT CREATION: Eliminated intermediate variables that were created just to pass to UpdateBatch constructor. Now pass sliced arrays directly.
-
TYPE CONVERSION: Move int() conversion outside the inner operations to reduce redundant type checking.
Note: Each UpdateBatch created here will have _bbox_computed=False, deferring expensive min/max calculations until/unless needed.
PropagatorError
Bases: Exception
Domain-specific error raised by PROPAGATOR.
BoundaryConditions(time, moisture=None, wind_dir=None, wind_speed=None, ignitions=None, additional_moisture=None, vegetation_changes=None)
dataclass
Boundary conditions applied at or after a given simulation time.
Attributes:
| Name | Type | Description |
|---|---|---|
time |
int
|
Simulation time the conditions refer to (seconds from simulation start). |
moisture |
Optional[NDArray[floating]]
|
Fuel moisture map (%). |
wind_dir |
Optional[NDArray[floating]]
|
Wind direction map (weather convention, degrees clockwise, north is 0). |
wind_speed |
Optional[NDArray[floating]]
|
Wind speed map (km/h). |
ignitions |
Optional[
|
npt.NDArray[np.bool_] | list[tuple[int, int] | tuple[int, int, int]] |
] |
Ignitions to enqueue. Accepts either a boolean raster (2D applies to
every realization; 3D maps explicit |
|
additional_moisture |
Optional[NDArray[floating]]
|
Extra moisture to add to fuel (%), can be sparse. |
vegetation_changes |
Optional[NDArray[floating]]
|
Raster of vegetation type overrides (NaN to skip). |
PropagatorStats(n_active, area_mean, area_50, area_75, area_90)
dataclass
Summary statistics for the current simulation state.
to_dict(c_time, ref_date)
Serialize stats with the current simulation time expressed in seconds.
PropagatorOutput(time, fire_probability, spotting_generation_probability, spotting_receiving_probability, mean_arrival_time, min_arrival_time, ros_mean, ros_max, fli_mean, fli_max, stats)
dataclass
Snapshot of simulation outputs at a given time step.
Simulator Implementation
propagator.core.propagator
Core wildfire propagation engine.
This module defines the main simulation primitives and the Propagator class
that evolves a fire state over a grid using wind, slope, vegetation, and
moisture inputs. Public dataclasses capture boundary conditions, actions,
summary statistics, and output snapshots suitable for CLI and IO layers.
PropagatorOutOfBoundsError
Bases: Exception
Custom error for out-of-bounds updates in the Propagator.
Propagator(veg, dem, fuels=(lambda: FUEL_SYSTEM_LEGACY)(), cellsize=CELLSIZE, do_spotting=False, realizations=REALIZATIONS, p_time_fn=get_p_time_fn(ROS_DEFAULT), p_moist_fn=get_p_moisture_fn(MOISTURE_MODEL_DEFAULT), out_of_bounds_mode='raise')
dataclass
Stochastic cellular wildfire spread simulator.
PROPAGATOR evolves a binary fire state over a regular grid for a configurable number of realizations. Spread depends on vegetation, topography and environmental drivers (wind, moisture) through pluggable probability and travel-time functions.
Attributes:
| Name | Type | Description |
|---|---|---|
veg |
ndarray
|
2D array of vegetation codes as defined in the provided FuelSystem |
dem |
ndarray
|
2D array of elevation values (meters above sea level). |
fuels |
(FuelSystem, optional)
|
Object defining fuels types and fire propagation probability between fuel types |
cellsize |
(float, optional)
|
The size of lattice (meters). |
do_spotting |
(bool, optional)
|
Whether to enable fire-spotting in the model. |
realizations |
(int, optional)
|
Number of stochastic realizations to simulate. |
p_time_fn |
(Any, optional)
|
The function to compute the spread time (must be jit-compiled). Units are compliant with other functions. signature: (v0: float, dh: float, angle_to: float, dist: float, moist: float, w_dir: float, w_speed: float) -> tuple[float, float] |
p_moist_fn |
(Any, optional)
|
The function to compute the moisture probability (must be jit-compiled) Units are compliant with other functions. signature: (moist: float) -> float |
out_of_bounds_mode |
(Literal['ignore', 'error'], optional)
|
Whether to raise an error if out-of-bounds updates are detected. Default is "error". |
compute_fire_probability()
Return mean burn probability across realizations for each cell.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array with values in [0, 1]. |
compute_spotting_generation_probability()
Return per-cell spotting generation probability.
compute_spotting_receiving_probability()
Return per-cell spotting receiving probability.
compute_ros_max()
Return per-cell maximum Rate of Spread across realizations.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array with max RoS per cell. |
compute_arrival_time_min()
Return per-cell minimum arrival time across realizations.
compute_arrival_time_mean()
Return per-cell mean arrival time across realizations where burned.
compute_ros_mean()
Return per-cell mean Rate of Spread, ignoring zeros as no-spread.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array with mean RoS per cell. |
compute_fireline_int_max()
Return per-cell maximum fireline intensity across realizations.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array of max intensity values. |
compute_fireline_int_mean()
Return per-cell mean fireline intensity, ignoring zeros as no-spread.
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array of mean intensity values. |
compute_stats(values)
Compute simple area-based stats and number of active cells.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
ndarray
|
Fire probability map in [0, 1]. |
required |
Returns:
| Type | Description |
|---|---|
PropagatorStats
|
Dataclass with counters and area summaries. |
set_boundary_conditions(boundary_condition)
Externally set boundary conditions at desired time in the scheduler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
boundary_condition
|
BoundaryConditions
|
Conditions to apply. |
required |
step(seconds=None, *, until=None)
Advance the simulation to the next scheduled time and update state.
get_output()
Assemble the current outputs and summary stats into a dataclass.
Returns: PropagatorOutput: Snapshot of fire probability, RoS, intensity, stats.
next_time()
Get the next time step.
Returns: int | None: 0 at initialization; None if no more events; otherwise the next scheduled simulation time.
Scheduler Helpers
propagator.core.scheduler
Lightweight event scheduler for propagation updates.
Stores future updates grouped by simulation time and exposes utilities to push events, pop the earliest batch, and inspect active realizations.
SchedulerEvent(updates=UpdateBatch(), moisture=None, wind_dir=None, wind_speed=None, additional_moisture=None, vegetation_changes=None)
dataclass
Represents a scheduled event in the simulation.
SortedDict()
dataclass
Sorted dictionary optimized for time-ordered event scheduling.
This data structure maintains events in sorted order by time (key) while allowing O(1) lookup and efficient insertion. It's specifically optimized for the common pattern of: 1. Inserting events at various future times 2. Always popping the earliest (minimum) event
Performance characteristics: - Insertion: O(n) with bisect.insort vs O(n log n) with naive sort - Lookup: O(1) via dict - Pop earliest: O(1) via list indexing - Memory: O(n) for both dict and sorted list
The frozen=True decorator prevents accidental modification of the data structure internals, enforcing use through the defined interface.
Scheduler(realizations)
dataclass
Lightweight event scheduler for propagation updates.
Generic over the time key type (int or float), so your inputs and outputs stay consistent.
push_updates(updates)
Add a batch of time-stamped updates to the scheduler.
This is the HOT PATH of the simulation - called once per step with all new fire spread updates. Optimizations here have outsized impact.
OPTIMIZATION NOTES: 1. split_by_time() creates separate UpdateBatch per time value - Fast path when all updates at same time (common case) - Lazy bbox calculation avoids min/max overhead
- SortedDict uses bisect.insort() for O(n) insertion vs O(n log n)
-
Critical because we insert many events per step
-
extend() merges updates efficiently without redundant bbox calculation
The flow is: UpdateBatchWithTime -> split by time -> UpdateBatch per time slot -> merge into existing events or create new ones -> bisect.insort into sorted event queue
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
updates
|
UpdateBatchWithTime
|
Batch of updates with associated ignition times |
required |
add_event(time, event)
Adds an event to the scheduler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
time
|
int
|
Time for the event |
required |
event
|
SchedulerEvent
|
New event structure |
required |