Skip to content

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 realization planes) or a list of (row, col) / (row, col, realization) tuples.

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

(moist: float) -> float.

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

(v0, dem_from, dem_to, angle_to, dist, moist, w_dir, w_speed) -> (time_seconds, ros).

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:

  1. 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.

  2. REDUCED OBJECT CREATION: Eliminated intermediate variables that were created just to pass to UpdateBatch constructor. Now pass sliced arrays directly.

  3. 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 realization planes) or a list of (row, col) / (row, col, realization) tuples.

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

  1. SortedDict uses bisect.insort() for O(n) insertion vs O(n log n)
  2. Critical because we insert many events per step

  3. 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