Skip to content

Complete a tree inventory with GDAM allometry

You are viewing in-progress documentation for v2 (Beta). Switch to the stable version for the current production release.

Some inventories arrive thin: a CHM inventory carries only x, y, and height, and an uploaded tree list carries only what your file had. That’s enough to filter and mask, but not enough to voxelize into 3D canopy fuel or to run silvicultural treatments — both need per-tree morphology (dbh, crown_ratio, fia_species_code).

GDAM (a Generalized Dendro Allometric Model) fills that gap. It takes a completed inventory and imputes the missing morphology columns from each tree’s position and height, writing a new inventory. Existing values are preserved; only missing columns are filled. This is the intended path from a CHM detection (or a coordinates-and-heights upload) to something a fire model can consume: CHM → allometry → voxelize.

  1. An API key: my-api-key.

  2. A domain: your-domain-id. See Create a domain.

  3. A completed source inventory that is missing morphology — most often a CHM inventory (x, y, height). Record its id: inventory-to-complete.

The whole flow in one script:

Complete an inventory with GDAM (create + polling)
import time
import requests
API_KEY = "my-api-key"
DOMAIN_ID = "your-domain-id"
# A completed inventory that carries x, y, height but is missing morphology —
# e.g. one detected from a CHM, or a positions-and-heights upload.
SOURCE_INVENTORY_ID = "inventory-to-complete"
BASE = "https://api-v2-prod-nyvjyh5ywa-uw.a.run.app"
HEADERS = {"api-key": API_KEY}
def poll(resource_id: str) -> dict:
while True:
r = requests.get(
f"{BASE}/domains/{DOMAIN_ID}/inventories/{resource_id}", headers=HEADERS
).json()
if r["status"] in ("completed", "failed"):
return r
time.sleep(5)
# Impute the missing dbh, crown_ratio, and fia_species_code from each tree's
# position and height. Existing columns are preserved; only missing ones are
# filled. Omit "impute_columns" to fill all three (the default).
inv = requests.post(
f"{BASE}/domains/{DOMAIN_ID}/inventories/tree/allometry/gdam",
headers=HEADERS,
json={
"name": "Tree inventory from GDAM allometry",
"source_tree_inventory_id": SOURCE_INVENTORY_ID,
},
).json()
inv = poll(inv["id"])
print(inv["id"], inv["status"]) # -> <inventory id> completed
print([c["key"] for c in inv["columns"]]) # now includes dbh, crown_ratio, species

POST to inventories/tree/allometry/gdam with source_tree_inventory_id pointing at the inventory you want to complete. That’s the only required field — by default GDAM imputes all three missing columns (dbh, crown_ratio, fia_species_code).

POST inventories/tree/allometry/gdam
curl -X 'POST' \
'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/inventories/tree/allometry/gdam' \
-H 'accept: application/json' \
-H 'api-key: my-api-key' \
-H 'Content-Type: application/json' \
-d '{
"name": "Tree inventory from GDAM allometry",
"source_tree_inventory_id": "inventory-to-complete"
}'

The 201 mints a new inventory id — record it: your-inventory-id. Poll until completed:

GET inventory status
curl -X 'GET' \
'https://api-v2-prod-nyvjyh5ywa-uw.a.run.app/domains/your-domain-id/inventories/your-inventory-id' \
-H 'accept: application/json' \
-H 'api-key: my-api-key'

GDAM keeps every tree from the source — a CHM inventory of ≈9,200 treetops comes back as ≈9,200 trees — and each row now carries x, y, height, plus the imputed dbh (cm), crown_ratio, and fia_species_code.

  • Source inventory not completed. GDAM reads the source inventory’s data — poll it to completed before creating the allometry inventory.
  • Expecting fia_status_code. GDAM imputes dbh, crown_ratio, and fia_species_code, but not tree status. That’s fine for voxelization — it treats a tree with no fia_status_code as live. If your workflow needs an explicit live/dead status, it has to be present in the source inventory (an upload that includes fia_status_code, or a TreeMap inventory); neither GDAM nor voxelization adds it.
  • Imputed, not measured. GDAM predicts morphology from position and height; it does not observe it. The DBH, crown ratio, and species are statistical estimates for trees of that height in that place — good enough to build a plausible 3D canopy, not a substitute for measured stems. When you have real DBH or crown data, upload it rather than imputing it.
  • Completing a TreeMap inventory. A TreeMap inventory already carries all seven columns, so it needs no allometry step — voxelize it directly. GDAM is for the sources that arrive thin (CHM, sparse uploads).