Create 1-hour dead fuel moisture grids
You are viewing in-progress documentation for v2 (Beta). Switch to the stable version for the current production release.
The Fosberg endpoint estimates 1-hour dead fuel moisture content (DFMC) — the moisture in the fine dead fuels that drive fire spread — across a domain. It is a derived grid: it takes no raster of its own, but combines two grids you have already built, plus a handful of weather and scenario numbers.
| Input | Band it reads | What it contributes |
|---|---|---|
| Topography grid (2D) | slope, aspect (degrees) | terrain geometry |
| Surface irradiance grid (2D) | irradiance.surface.relative | shading, as 1 − irradiance |
The one endpoint, grids/fuel-moisture/dead/fosberg, reads those two grids at
each cell, applies the Fosberg & Deeming (1971) model with your reference
weather, and writes a single 2D fuel_moisture.dead.1hr band — a percent of
oven-dry fuel weight — on the topography grid’s lattice. This guide builds one,
walks each input, and then shows how the weather inputs move the result.
Prerequisites
Section titled “Prerequisites”-
An API key. my-api-key.
-
A domain. your-domain-id.
-
A completed 2D topography grid with
slopeandaspectbands. your-topography-grid-id. Build one from 3DEP requesting"bands": ["slope", "aspect"]. Fosberg reads both in degrees. -
A completed leaflux surface irradiance grid with an
irradiance.surface.relativeband. your-irradiance-grid-id. Build one from solar irradiance requesting"bands": ["irradiance.surface.relative"]. Fosberg reads it as shading: a cell where relative irradiance is0.2is0.8shaded, and shaded fuel holds more moisture.
The whole flow — create, poll, and read the band back — in one script:
"""Create a Fosberg 1-hr dead fuel moisture grid, poll it, and read it back.
Point the two source grids at a completed 2D topography grid (slope + aspect)and a completed leaflux surface irradiance grid on the same domain."""import numpy as npimport fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
topography = ff.get_grid("your-domain-id", "your-topography-grid-id")irradiance = ff.get_grid("your-domain-id", "your-irradiance-grid-id")
# 1. Create the grid and poll it to completed.grid = ff.grids.create_dead_fuel_moisture_grid_from_fosberg( topography, irradiance, dry_bulb_temp=75, # Fahrenheit relative_humidity=30, # percent time=1200, # HHMM, 0800-1959 month="June",)grid.wait()
# 2. Read the 2D band back as one (y, x) array — the SDK fetches every chunk# and places it at its offset for you.moisture = grid.to_numpy("fuel_moisture.dead.1hr")
# 3. Values are 1-hr dead fuel moisture content, percent of oven-dry weight.cells = moisture[np.isfinite(moisture)]print(f"1-hr DFMC (%): min {cells.min():.1f}, mean {cells.mean():.1f}, max {cells.max():.1f}")Create the grid
Section titled “Create the grid”Post the two source grid ids and the reference weather. The response is a
pending Grid; poll it to completed as with any other grid.
curl -X 'POST' \ 'https://api-v2-prod-782971006568.us-west1.run.app/domains/your-domain-id/grids/fuel-moisture/dead/fosberg' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "source_topography_grid_id": "your-topography-grid-id", "source_irradiance_grid_id": "your-irradiance-grid-id", "dry_bulb_temp": 75, "relative_humidity": 30, "time": 1200, "month": "June"}'import fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
topography = ff.get_grid("your-domain-id", "your-topography-grid-id")irradiance = ff.get_grid("your-domain-id", "your-irradiance-grid-id")
# Temperature is Fahrenheit (the Fosberg tables are Fahrenheit); `time` is a# 24-hour HHMM clock value restricted to 0800-1959. `month` selects the seasonal# correction table; `elevation` defaults to "near" (no correction).grid = ff.grids.create_dead_fuel_moisture_grid_from_fosberg( topography, irradiance, dry_bulb_temp=75, relative_humidity=30, time=1200, month="June",){ "id": "your-moisture-grid-id", "domain_id": "your-domain-id", "name": "", "description": "", "status": "pending", "progress": null, "created_on": "{{CREATED_ON}}", "modified_on": "{{MODIFIED_ON}}", "checksum": "9d03b10c60ea4f4cb87ae69aa736cf9a", "source": { "name": "fosberg", "source_topography_grid_id": "your-topography-grid-id", "source_topography_grid_checksum": "a1b2a5c7388642c5b3f9b93c3400a026", "source_irradiance_grid_id": "your-irradiance-grid-id", "source_irradiance_grid_checksum": "9f75efe7249d49c395a64ac148b5a945", "dry_bulb_temp": 75.0, "relative_humidity": 30.0, "time": 1200, "month": "June", "elevation": "near" }, "modifications": [], "bands": [ { "key": "fuel_moisture.dead.1hr", "name": "1-hour Dead Fuel Moisture", "description": "1-hour timelag dead fuel moisture content from the Fosberg & Deeming (1971) model, as a percent of oven-dry fuel weight.", "type": "continuous", "unit": "%", "index": 0, "nodata": null, "summary": null } ], "georeference": null, "error": null, "chunks": { "shape": [512, 512], "count": null, "count_by_axis": null }, "tags": []}Each input is worth a deliberate choice:
| Field | Required | What it is |
|---|---|---|
source_topography_grid_id | yes | The 2D topography grid — slope + aspect in degrees. |
source_irradiance_grid_id | yes | The leaflux surface irradiance grid — irradiance.surface.relative. |
dry_bulb_temp | yes | Dry-bulb air temperature in °F, at least 10. |
relative_humidity | yes | Relative humidity as a percent, 0–100. |
time | yes | Local time of day as a 24-hour HHMM integer (e.g. 1200 for noon). |
month | yes | Full month name ("June") — picks the seasonal correction table. |
elevation | no | below | near | above, default near. |
name, description, tags | no | Optional metadata. |
Poll to completion
Section titled “Poll to completion”Record the id as your-moisture-grid-id and poll it. Because Fosberg is
a 2D derivation, the completed grid is genuinely two-dimensional —
georeference.shape is (y, x), and it exports and reads back as a plain
raster.
curl -X 'GET' \ 'https://api-v2-prod-782971006568.us-west1.run.app/domains/your-domain-id/grids/your-moisture-grid-id' \ -H 'accept: application/json' \ -H 'api-key: my-api-key'{ "id": "your-moisture-grid-id", "domain_id": "your-domain-id", "name": "", "description": "", "status": "completed", "progress": { "percent": 100, "message": "Complete" }, "created_on": "{{CREATED_ON}}", "modified_on": "{{MODIFIED_ON}}", "checksum": "9d03b10c60ea4f4cb87ae69aa736cf9a", "source": { "relative_humidity": 30.0, "name": "fosberg", "time": 1200, "source_irradiance_grid_checksum": "9f75efe7249d49c395a64ac148b5a945", "month": "June", "elevation": "near", "source_irradiance_grid_id": "your-irradiance-grid-id", "source_topography_grid_id": "your-topography-grid-id", "dry_bulb_temp": 75.0, "source_topography_grid_checksum": "a1b2a5c7388642c5b3f9b93c3400a026" }, "modifications": [], "bands": [ { "key": "fuel_moisture.dead.1hr", "name": "1-hour Dead Fuel Moisture", "description": "1-hour timelag dead fuel moisture content from the Fosberg & Deeming (1971) model, as a percent of oven-dry fuel weight.", "type": "continuous", "unit": "%", "index": 0, "nodata": null, "summary": { "type": "continuous", "count": 289068, "nodata_count": 0, "min": 5.0, "max": 8.0, "mean": 5.669323480980254, "std": 1.2245687359440054 } } ], "georeference": { "crs": "EPSG:32611", "transform": [2.0, 0.0, 720226.0, 0.0, -2.0, 5190646.0], "shape": [442, 654] }, "error": null, "chunks": { "shape": [512, 512], "count": 2, "count_by_axis": { "y": 1, "x": 2 } }, "tags": []}The completed grid inherits the topography grid’s lattice — same crs,
transform, and shape ([442, 654] here: a 442 × 654 grid of 2 m cells). The
source block records both input grids and every weather input, with the source
grids’ checksums, so the grid is reproducible and you can tell if a source has
changed since.
Read the moisture surface
Section titled “Read the moisture surface”Fetch the fuel_moisture.dead.1hr band the same way as any other 2D grid — per
band, per chunk — using the loop in
Fetch and stream grid data.
Every cell carries a value; read it dense.

The Fosberg grid is the shading map, turned into moisture. Left: shading,
1 − irradiance.surface.relative, from the source irradiance grid. Right: the
1-hour DFMC it drives. Exposed fuel sits at the 5 % base for this weather;
shaded fuel — under crowns and on shaded slopes — reads about 3 points wetter.
The values are quantized because the model is a lookup table.
The values are a percent of oven-dry fuel weight, so 5 means the fuel weighs 5 %
more than it would bone-dry. Low single digits are dry, fire-ready fuels; the
wetter, shaded cells are correspondingly harder to ignite.
Move the weather
Section titled “Move the weather”The two source grids fix the spatial pattern — where it is shaded, steep, or
sun-facing. The weather inputs set the level. Raising relative_humidity
lifts the whole field toward wetter fuel; lowering it, or raising
dry_bulb_temp, dries everything out. The shaded-versus-exposed structure stays
put underneath.

The same scene at three relative humidities, everything else held fixed. The whole surface shifts drier to wetter as humidity climbs, while the shaded-patch pattern set by terrain and canopy stays the same. Temperature works the same way in reverse — hotter air dries the fuel.
For a named grid with an elevation correction — a hot, dry August afternoon on a site above the reference weather station — pass the full request:
curl -X 'POST' \ 'https://api-v2-prod-782971006568.us-west1.run.app/domains/your-domain-id/grids/fuel-moisture/dead/fosberg' \ -H 'accept: application/json' \ -H 'api-key: my-api-key' \ -H 'Content-Type: application/json' \ -d '{ "name": "Peak burn-period 1-hr DFMC", "description": "Midday August dead fuel moisture for the burn window.", "tags": ["fuel-moisture", "surface-fuel"], "source_topography_grid_id": "your-topography-grid-id", "source_irradiance_grid_id": "your-irradiance-grid-id", "dry_bulb_temp": 82, "relative_humidity": 20, "time": 1400, "month": "August", "elevation": "above"}'import fastfuels_sdk.v2 as ff
ff.set_api_key("my-api-key")
topography = ff.get_grid("your-domain-id", "your-topography-grid-id")irradiance = ff.get_grid("your-domain-id", "your-irradiance-grid-id")
# A hot, dry August afternoon on a site 1000-2000 ft above the reference weather# station. `elevation` is a Fosberg correction category relative to the station,# not the topography elevation band.grid = ff.grids.create_dead_fuel_moisture_grid_from_fosberg( topography, irradiance, dry_bulb_temp=82, relative_humidity=20, time=1400, month="August", elevation="above", name="Peak burn-period 1-hr DFMC", description="Midday August dead fuel moisture for the burn window.", tags=["fuel-moisture", "surface-fuel"],){ "id": "your-moisture-grid-id", "domain_id": "your-domain-id", "name": "Peak burn-period 1-hr DFMC", "description": "Midday August dead fuel moisture for the burn window.", "status": "pending", "progress": null, "created_on": "{{CREATED_ON}}", "modified_on": "{{MODIFIED_ON}}", "checksum": "2cbe6a1cdbe54f7db3a3666d3efd8476", "source": { "name": "fosberg", "source_topography_grid_id": "your-topography-grid-id", "source_topography_grid_checksum": "a1b2a5c7388642c5b3f9b93c3400a026", "source_irradiance_grid_id": "your-irradiance-grid-id", "source_irradiance_grid_checksum": "9f75efe7249d49c395a64ac148b5a945", "dry_bulb_temp": 82.0, "relative_humidity": 20.0, "time": 1400, "month": "August", "elevation": "above" }, "modifications": [], "bands": [ { "key": "fuel_moisture.dead.1hr", "name": "1-hour Dead Fuel Moisture", "description": "1-hour timelag dead fuel moisture content from the Fosberg & Deeming (1971) model, as a percent of oven-dry fuel weight.", "type": "continuous", "unit": "%", "index": 0, "nodata": null, "summary": null } ], "georeference": null, "error": null, "chunks": { "shape": [512, 512], "count": null, "count_by_axis": null }, "tags": ["fuel-moisture", "surface-fuel"]}How the model works
Section titled “How the model works”The endpoint calls the Fosberg & Deeming (1971) 1-hour timelag model. “1-hour timelag” is the class of fine dead fuels — cured grass, litter, and twigs under about ¼ inch — that gain or shed moisture within roughly an hour of a change in the weather, which is why so much of fire behavior tracks them.
The model reads a reference fuel moisture from a dry-bulb-temperature × relative-humidity table, then applies additive corrections for the month, time of day, slope, aspect, and whether the fuel is shaded — the two source grids supply slope, aspect, and shading per cell, and the request supplies the rest. Slope is classed internally by percent grade, so the API converts your topography grid’s degrees before the lookup. The result is a percent of oven-dry weight.
Common pitfalls
Section titled “Common pitfalls”- Passing Celsius for
dry_bulb_temp. It is Fahrenheit. A Celsius value is in range but wrong —20(°C, a mild day) is read as 20 °F. - A
timeoutside0800–1959. The model has no night-time table; a value outside the window, or with minutes past59, is rejected. - Source grids on different lattices. Slope, aspect, and shading are read at the same cell, so the topography and irradiance grids must share one x/y lattice. Align the topography grid to the irradiance grid before this request.
- A source grid still
pending. Poll both source grids tocompletedfirst; Fosberg reads their data, not just their metadata. - Confusing
elevationwith the terrain.elevationis abelow/near/aboveweather correction relative to the reporting station — not the topography grid’s elevation band. - Reusing a grid after rebuilding a source. The
sourceblock records each source grid’s checksum. If you rebuild the topography or irradiance grid, rebuild the moisture grid too.