CoolFace
Datasetpublic

torq1/fire-fusion-wa-4000m

FireFusion WA 4000m Daily spatio-temporal datacube for wildfire ignition and cause prediction over Washington State, an envelope spanning the Puget lowlands east to the Idaho border. Ten geospatial products spanning terrain, fuels, weather, human activity, lightning, and fire history are aggregated onto a single daily 4km by 4km grid covering every fire season 2003-2020. Daily fire-season coverage, May 1 - Oct 31 of every year 2003-2020; the window contains every recorded… See the full description on the dataset page: https://huggingface.co/datasets/torq1/fire-fusion-wa-4000m.

sourceHugging Facemitupdated 2mo agoView on Hugging Face
0likes9.4kdownloads
Dataset Card

FireFusion WA 4000m

Daily spatio-temporal datacube for wildfire ignition and cause prediction over Washington State, an envelope spanning the Puget lowlands east to the Idaho border. Ten geospatial products spanning terrain, fuels, weather, human activity, lightning, and fire history are aggregated onto a single daily 4km by 4km grid covering every fire season 2003-2020.

  • —Daily fire-season coverage, May 1 - Oct 31 of every year 2003-2020; the window contains every recorded ignition.
  • —38 input channels (25 from source processors, 13 derived), distilled from 51 grid layers built from 10 sources.
  • —Compilable dataset and train-ready splits. Every layer is resampled onto the daily grid and interpolated to 4 km; the splits are additionally normalized.
  • —Custom derived features: Per-cause ignition KDEs, 3x3 cell 7d rolling fire occurrence, NDVI anomalies, 2 and 5-day cumulative precipitation, 100 and 1000-hr dead fuel moisture, decayed lightning load, Fosberg FWI.
  • —Circular quantities (N/S and E/W aspect and wind-direction components, day-of-year) decomposed into orthogonal components, so no channel carries 0/360 discontinuities.
  • —Labels for ignition within a 7-day horizon and its cause class.
  • —Mask layers (water, active fire, usable cause) marking exactly the cells each prediction head is supervised on.

Built by Tanner O'Rourke as part of FireFusion, independent research conducted on multi-source wildfire ignition modeling. The full pipeline, from raw-source extraction to model training, is at FireFusionNet. If this work is useful to you, a star on the repository helps it reach more people. Feel free to reach out!

bibtex
@misc{orourke2026firefusion,
  author = {O'Rourke, Tanner},
  title  = {FireFusion: multi-source datacubes and a spatiotemporal ConvFormer for wildfire ignition prediction},
  year   = {2026},
  url    = {https://github.com/tannerorourke/FireFusionNet}
}

Files

  • —dataset.zarr: The primary artifact, cut prior to compilation. Includes no statistical normalization: all data-estimated transforms (z-score, min-max, scale) are deferred to compile, leaving only deterministic steps (clip, log1p, to_sin, per_area). Statistics are fit on train years alone, so the published values sit in native units, free of split-boundary leakage. Same daily supervised grid, split-agnostic; 2.3 GB on disk. The dataset includes 46 channel variables versus the splits' 38, the extra eight being raw layers that derived channels are built from, kept for provenance (lf_aspect and wind_dir before their component decomposition, modis_ndvi before anomaly calculation, plus modis_water_mask, rh_max, usfs_burn_occ, usfs_burn_cause, and usfs_perimeter). Split compilation drops them.
  • —dataset_manifest.json: channel order, transforms, normalization steps and class balance for dataset.zarr.
  • —schema.parquet: one row per stored variable (role, dims, dtype, source, normalization, description). Zarr is not previewable in the Hub's dataset viewer, so this table is what the viewer renders.
  • —Splits: These are suggested, balancing positive label counts against training data size; they are not the only choice. To cut your own, see Compiling.
  • —train.zarr: Years 2003-2016, 2576 days, 2.4GB
  • —eval.zarr: Years 2017-2018, 368 days, 347MB
  • —test.zarr: Years 2019-2020, 368 days, 353MB

Loading

`dataset.zarr`: Features are held as named variables rather than a stacked tensor, so a channel loads independently of the rest.

python
ds = xr.open_zarr("dataset.zarr")             # 3312 days, no split boundary

vpd = ds["vpd_max"]                           # (3312, 102, 109) float32
window = ds[["temp_max", "wind_mph", "lightning_load"]].isel(time=slice(0, 10))
y, cause = ds["ign_next"], ds["ign_next_cause"]

# stack an arbitrary channel set into a model-shaped tensor
chans = ["temp_max", "vpd_max", "lf_elevation"]
X = ds[chans].to_array("channel").transpose("time", "channel", "y", "x")

Splits: Each split is compressed to zarr and holds X, a stacked tensor along with labels and masks.

python
import numpy as np
import xarray as xr

ds = xr.open_zarr("train.zarr")              # local path, or an fsspec URL
x = ds["X"].isel(time=slice(0, 10))          # (10, 38, 102, 109)
vpd = ds["X"].sel(channel="vpd_max")         # the channel coord carries the 38 names
y = ds["ign_next"].isel(time=9)

# the time axis skips the off-season, so build windows within a contiguous block
days = np.asarray(ds.indexes["time"], dtype="datetime64[D]")
block = np.concatenate([[0], np.cumsum(np.diff(days).astype(int) != 1)])
# a length-W window at t is valid iff block[t] == block[t + W - 1]

Compiling

To cut your own splits, run the compile stage of the FireFusionNet repo: set train_yrs / eval_yrs / test_yrs in fire_fusion/config/dataset_config.py and run compile against the stored dataset.zarr. Every statistic refits on the years you name.

bash
python -m fire_fusion.dataset.build --dataset wa4000 --stage compile

Words of wisdom:

  • —Download before compiling; streaming is for inspection only. Split X is chunked (16, 38, 102, 109), the full grid in one spatial chunk, about 27 MB decompressed and ~15 MB on the wire. A 10-day window spans one or two chunks, so a train epoch of full-grid windows moves on the order of 56 GB, roughly 23x the cost of downloading the 2.4 GB train split once.
  • —Order any custom splits chronologically (train earliest) to avoid future leakage.

Sources and Channels

Ten source products resolve into 51 grid layers and then 38 model channels. The mapping is many-to-many: raw variables to many channels (e.g., precipitation -> daily, 2d, 5d totals), many sources to one channel (e.g., dead fuel moisture). In-depth extraction and feature details can be found in the repo's README and SOURCING.md.

Between the raw data point and the channel, each layer goes through pre-clipping, reprojection, and interpolation onto the master daily grid. Interpolation and resampling choices are documented per source in SOURCING.md.

[image]

Feature notes:

  • —The four kde_* channels are fire-history kernel density estimators in events per km², with a 20 km smoothing radius and a 365-day decay half-life. The per_area step is what puts them in those units; the raw accumulator is mass per cell and would rescale with cell size.
  • —100hr and 1000hr dead fuel moisture are calculated using the National Fire Danger Rating System (NFDRS) 100h and 1000h dead fuel moisture equations.
  • —ndvi_anomaly: NDVI minus its day-of-year climatology, averaged over the train years. No held-out day contributes to the mean it is measured against.
  • —dataset.zarr carries a fourth cause class DEBRIS. The splits fold DEBRIS into INDUSTRIAL, since each is a few hundred cases against five figures for lightning and human causes. Each manifest logs this as n_cause_classes: in dataset.zarr, ign_next_cause runs 0-3 with DEBRIS held separate and dataset_manifest.json records n_cause_classes: 4; the splits run 0-2 with manifest.json recording 3. Regroup them by re-running compile against the published cube.

Grid Details

The grid covers the statewide extraction envelope, latitude 45.5 to 49.0 and longitude -122.5 to -117.0. The north edge clamps to the 49th parallel, where the US sources stop.

Stats:

  • —CRS: EPSG:32610 (UTM Zone 10N)
  • —Resolution: 4000 m
  • —Grid (y, x): 102 x 109
  • —Latitude: 45.5 to 49.0
  • —Longitude: -122.5 to -117.0
  • —Season: May 1 - Oct 31, each year 2003-2020
  • —Supervised days/year: 184
  • —Supervised Days total: 3312

Labels:

  • —ign_next (binary, int8): 1 if a clear cell burns within the next 7 days, else 0.
  • —ign_next_cause (categorical, int8): cause id of the earliest such ignition, else -1.
IDCauseTrain positives
0NATURAL_LIGHTNING14,912
1HUMAN6,630
2INDUSTRIAL (includes debris)780

A 1-day horizon (fire at cell (i, j) at timestep t+1, "tomorrow") is extremely imbalanced; the horizon is configurable at compile.

Masks:

  • —land_mask (binary, uint8): 1 on land, derived from the MODIS deep-water flag
  • —no_act_fire_mask (binary, uint8): 1 where the cell is not already burning
  • —valid_cause_mask (binary, uint8): 1 where ign_next_cause carries a usable label

Time axis:

The time axis is not contiguous: only in-season days are included. Within a year, it runs May 1 to Oct 31 day-by-day, then jumps to the next May. Every day with an active fire in the record falls inside the window. The manifests record time.season_months = [5, 10] and time.contiguous = false.

Halo days:

Each year is built from a single block running March 22 to November 10, deliberately wider than the window. This halo, a 40-day lead and a 10-day trail, lets temporal derivations enter the supervised window with real history instead of restarting at zero. Every backward-looking channel (decayed lightning load, 2 and 5-day cumulative precipitation, the per-cause ignition KDEs) is computed on the wider index, and the halo is dropped before any normalization statistic or class balance is taken, so those describe exactly the days that ship. The 40-day lead is sized by the longest backward operator in the pipeline, the lightning-load IIR, which decays below 0.1% there.

Halo days are never supervised and never scored. They survive only in the build-time staging cube (cube.zarr), which is not distributed, and are absent from every artifact listed above. A sliding-window loader must still avoid building any window that straddles the year-to-year gap. See Loading.

State that legitimately spans years decays by elapsed time, not by index position. The per-cause ignition KDEs apply a 365-day half-life to the true day count between consecutive entries, so a multi-year prior crosses the roughly 4.5-month off-season gap correctly attenuated instead of stepping across it as a single day.

234 days are extracted per year against the 184 that are supervised. Over 2003-2020 that is 4212 days extracted and 3312 published.

Class Imbalance:

Ignition is heavily imbalanced: `ign_pos_weight` = 944.85 on the train split, so positives are ~1.1e-3 of supervised cell-days. Restricting to the fire season removes winter cell-days that are near-uniformly negative, so this is a fire-season base rate and not an annual one. Losses should apply land_mask and no_act_fire_mask; the cause head should additionally apply valid_cause_mask.

Class balance is not identical across resolutions; ignition prevalence per cell rises with cell size. A larger cell covers more ground, so the chance that a given cell-day contains an ignition grows with its area. See manifest for exact values.


Schema

Both artifact forms carry the same values at the same dtypes. They differ in that (1) the splits drop the eight provenance layers (46 channel variables down to 38), and (2) dataset.zarr keeps name addressable per-channel variables while the splits form to one stacked 38 channel tensor X for direct model consumption, leaving only labels and masks as named variables.

dtype follows a variable's role:

  • —all feature channels are float32
  • —labels are int8 (-1 is the no-cause sentinel in ign_next_cause)
  • —masks and the raw fire/water flags are uint8

The full per-variable table ships as schema.parquet and backs the dataset viewer.

Coordinates (shared by all artifacts):

CoordinatedtypeNotes
timedatetime64[ns]supervised days only, not contiguous (see Time axis)
y, xfloat64UTM Zone 10N cell centres, metres
channelstrsplits only; the 38 channel names, X's order (alphabetical)
burn_causestrdataset.zarr only; the 4 raw cause classes

`dataset.zarr` (51 variables)

VariablesCountDimsdtype
feature channels42(time, y, x)float32
usfs_burn_occ, usfs_perimeter, modis_water_mask3(time, y, x)uint8
usfs_burn_cause1(time, burn_cause, y, x)uint8
labels: ign_next, ign_next_cause2(time, y, x)int8
masks: land_mask, no_act_fire_mask, valid_cause_mask3(time, y, x)uint8

Splits (`train.zarr`, `eval.zarr`, `test.zarr`)

Six variables each:

  • —X (time, channel, y, x), float32: the 38 model channels stacked alphabetically; the channel coordinate carries the names. Chunked (16, 38, 102, 109), the full grid in one spatial chunk.
  • —The two labels (int8) and three masks (uint8) keep their named (time, y, x) form, chunked (64, 102, 109).

Store configuration

Every variable in every artifact is Blosc-compressed (zstd level 5, byte shuffle). dataset.zarr is chunked (16, 102, 109): 16 days, full grid, so a channel-day never spans chunks. The manifests carry the cube-level metadata: dataset_manifest.json records grid bounds, the channel list, deterministic norm steps, and n_cause_classes: 4; the splits' shared manifest.json records channel order, the full per-channel norm chain (deterministic steps plus train-fit statistics), split years and day counts, ign_pos_weight, and per-cause positive counts.

FireFusion collection

All FireFusion datasets carry identical channels, labels, masks, and split years. Three are statewide; cascades500 covers only the Eastern Cascades sub-region.

TierResolutionGrid (y, x)Extent
wa4000 (this one)4000 m102 x 109Washington State
wa20002000 m204 x 217Washington State
wa10001000 m407 x 433Washington State
cascades500500 m544 x 544Eastern Cascades