Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/v2/guides/inventories.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,16 +190,16 @@ background job — `wait()` before reading data back:
## Impute missing morphology with GDAM

An uploaded inventory may carry only some columns — coordinates and heights,
say, without diameters or species. `create_tree_inventory_from_gdam` fills in
the missing morphology (`dbh`, `crown_ratio`, `fia_species_code`,
say, without diameters or species. `create_tree_inventory_with_gdam_allometry`
fills in the missing morphology (`dbh`, `crown_ratio`, `fia_species_code`,
`crown_base_height`) for a completed inventory using GDAM allometry, producing
a new inventory:

```python
sparse = ff.inventories.create_tree_inventory_from_file(domain, "stems.csv")
sparse.wait()

full = ff.inventories.create_tree_inventory_from_gdam(domain, sparse)
full = ff.inventories.create_tree_inventory_with_gdam_allometry(domain, sparse)
full.wait()
```

Expand All @@ -214,13 +214,13 @@ imputed species, dbh, crown ratio and height instead, pass

Voxelization and canopy grids need a `crown_base_height` (m) for every tree.
To compute it for an inventory that already has species, dbh, crown ratio
and height, use `create_tree_inventory_from_crown_base_height`:
and height, use `create_tree_inventory_with_crown_base_height_allometry`:

```python
trees = ff.inventories.create_tree_inventory_from_file(domain, "plot_trees.csv")
trees.wait()

inventory = ff.inventories.create_tree_inventory_from_crown_base_height(
inventory = ff.inventories.create_tree_inventory_with_crown_base_height_allometry(
domain, trees
)
inventory.wait()
Expand Down Expand Up @@ -404,7 +404,7 @@ trees = ff.inventories.create_tree_inventory_from_chm_grid(domain, chm)
trees.wait()

crowns = ff.features.create_crown_feature_from_chm(domain, trees, chm)
full = ff.inventories.create_tree_inventory_from_gdam(domain, trees)
full = ff.inventories.create_tree_inventory_with_gdam_allometry(domain, trees)
ff.wait_all([crowns, full])

voxels = full.voxelize(
Expand Down
2 changes: 1 addition & 1 deletion fastfuels_sdk/v2/grids.py
Original file line number Diff line number Diff line change
Expand Up @@ -1599,7 +1599,7 @@ def create_canopy_fuel_grid_from_inventory(
UnprocessableEntityException
If the inventory lacks a column the request needs, such as
``crown_base_height`` (see
:func:`fastfuels_sdk.v2.inventories.create_tree_inventory_from_crown_base_height`).
:func:`fastfuels_sdk.v2.inventories.create_tree_inventory_with_crown_base_height_allometry`).

Examples
--------
Expand Down
23 changes: 12 additions & 11 deletions fastfuels_sdk/v2/inventories.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@
"create_tree_inventory_from_chm_grid",
"create_tree_inventory_from_pim_chm_fusion",
"create_tree_inventory_from_file",
"create_tree_inventory_from_gdam",
"create_tree_inventory_from_crown_base_height",
"create_tree_inventory_with_gdam_allometry",
"create_tree_inventory_with_crown_base_height_allometry",
"list_inventories",
"get_inventory",
"ChmInventoryCrownSegmentation",
Expand Down Expand Up @@ -718,8 +718,9 @@ def voxelize(
longer exists, or the inventory has no ``tree_id`` column or
lacks the columns voxelization needs (``x``, ``y``, ``height``,
``dbh``, ``crown_base_height`` and ``fia_species_code``, with no
empty values; see :func:`create_tree_inventory_from_gdam` and
:func:`create_tree_inventory_from_crown_base_height`).
empty values; see
:func:`create_tree_inventory_with_gdam_allometry` and
:func:`create_tree_inventory_with_crown_base_height_allometry`).

Examples
--------
Expand Down Expand Up @@ -1395,7 +1396,7 @@ def create_tree_inventory_from_file(
return Inventory._from_model(created.inventory)


def create_tree_inventory_from_gdam(
def create_tree_inventory_with_gdam_allometry(
domain,
source_inventory,
impute_columns: Optional[list] = None,
Expand Down Expand Up @@ -1472,12 +1473,12 @@ def create_tree_inventory_from_gdam(
... domain, "stems.csv" # x, y, height only
... )
>>> sparse.wait()
>>> full = ff.inventories.create_tree_inventory_from_gdam(domain, sparse)
>>> full = ff.inventories.create_tree_inventory_with_gdam_allometry(domain, sparse)
>>> full.wait()

Compute crown base heights with an equation instead of GDAM:

>>> full = ff.inventories.create_tree_inventory_from_gdam(
>>> full = ff.inventories.create_tree_inventory_with_gdam_allometry(
... domain, sparse, crown_base_height_model="fia_national_logit_2026"
... )
"""
Expand All @@ -1500,7 +1501,7 @@ def create_tree_inventory_from_gdam(
return Inventory._from_model(expect(response, HTTPStatus.CREATED))


def create_tree_inventory_from_crown_base_height(
def create_tree_inventory_with_crown_base_height_allometry(
domain,
source_inventory,
model=None,
Expand Down Expand Up @@ -1531,7 +1532,7 @@ def create_tree_inventory_from_crown_base_height(
``height`` for every tree, and ``fia_species_code``, ``dbh`` and
``crown_ratio`` for every tree unless ``model`` is "gdam". To fill
those columns and the crown base height in one request, use
:func:`create_tree_inventory_from_gdam` instead.
:func:`create_tree_inventory_with_gdam_allometry` instead.
model : str, Mapping, or crown base height model, optional
The crown base height model, by name: "fia_national_logit_2026",
"monleon_2004_eq1", "monleon_2004_eq2", "toney_reeves_2009",
Expand Down Expand Up @@ -1571,14 +1572,14 @@ def create_tree_inventory_from_crown_base_height(
... domain, "plot_trees.csv" # x, y, height, dbh, crown_ratio, species
... )
>>> trees.wait()
>>> inventory = ff.inventories.create_tree_inventory_from_crown_base_height(
>>> inventory = ff.inventories.create_tree_inventory_with_crown_base_height_allometry(
... domain, trees
... )
>>> inventory.wait()

Recompute every tree's crown base height with a regional equation:

>>> inventory = ff.inventories.create_tree_inventory_from_crown_base_height(
>>> inventory = ff.inventories.create_tree_inventory_with_crown_base_height_allometry(
... domain, trees, model="toney_reeves_2009", overwrite=True
... )
"""
Expand Down
6 changes: 3 additions & 3 deletions fastfuels_sdk/v2/v2_api_design.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,9 @@ later merges). Each new resource/endpoint kept to the settled rules above.
re-derive) + the `ff.basal_area_treatment`/`ff.diameter_treatment` builders
(`treatments.py`). The former #333 fork-safety blocker for both in-place
processing paths is fixed.
- **GDAM** — `create_tree_inventory_from_gdam(domain, source_inventory,
impute_columns=)`. A *create* (new inventory) → a function in the
`create_tree_inventory_from_*` family, **not** a method — same call as the
- **GDAM** — `create_tree_inventory_with_gdam_allometry(domain,
source_inventory, impute_columns=)`. A *create* (new inventory) → a function
in the `create_tree_inventory_*` family, **not** a method — same call as the
fbfm40-lookup precedent (derive-a-new-resource = function).
- **Grid** gained `duplicate` (byte-copy clone, mirrors `Inventory.duplicate`),
`apply_modifications` (in-place re-derive; grid `modifications` list is *not*
Expand Down
30 changes: 15 additions & 15 deletions tests/v2/test_inventories.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
_build_crown_base_height_model,
_build_fusion_method,
create_tree_inventory_from_chm_grid,
create_tree_inventory_from_crown_base_height,
create_tree_inventory_with_crown_base_height_allometry,
create_tree_inventory_from_file,
create_tree_inventory_from_gdam,
create_tree_inventory_with_gdam_allometry,
create_tree_inventory_from_pim_chm_fusion,
create_tree_inventory_from_pim_grid,
get_inventory,
Expand Down Expand Up @@ -452,11 +452,11 @@ def test_create_from_csv(self, real_dispatch, test_domain, tmp_path):
inventory.delete()


class TestCreateTreeInventoryFromGdam:
class TestCreateTreeInventoryWithGdamAllometry:
def test_create_returns_new_pending_inventory(
self, test_domain, completed_tree_inventory
):
imputed = create_tree_inventory_from_gdam(
imputed = create_tree_inventory_with_gdam_allometry(
test_domain,
completed_tree_inventory,
impute_columns=["dbh", "crown_ratio"],
Expand All @@ -469,20 +469,20 @@ def test_create_returns_new_pending_inventory(
imputed.delete()

def test_accepts_inventory_id_string(self, test_domain, completed_tree_inventory):
imputed = create_tree_inventory_from_gdam(
imputed = create_tree_inventory_with_gdam_allometry(
test_domain, completed_tree_inventory.id
)
assert imputed.domain_id == test_domain.id
imputed.delete()


class TestCreateTreeInventoryFromCrownBaseHeight:
class TestCreateTreeInventoryWithCrownBaseHeightAllometry:
def test_create_returns_new_pending_inventory(
self, test_domain, completed_tree_inventory
):
# The PIM fixture already has a crown base height for every tree, so
# the API requires overwrite=True.
inventory = create_tree_inventory_from_crown_base_height(
inventory = create_tree_inventory_with_crown_base_height_allometry(
test_domain,
completed_tree_inventory,
model="toney_reeves_2009",
Expand Down Expand Up @@ -533,7 +533,7 @@ def test_rejects_unknown(self, value):
_build_crown_base_height_model(value, "crown_base_height_model")


class TestCreateTreeInventoryFromCrownBaseHeightRequest:
class TestCreateTreeInventoryWithCrownBaseHeightAllometryRequest:
@pytest.fixture
def captured(self, monkeypatch):
captured = {}
Expand All @@ -552,7 +552,7 @@ def fake_create(domain_id, *, client, body):
return captured

def test_defaults(self, captured):
inventory = create_tree_inventory_from_crown_base_height(
inventory = create_tree_inventory_with_crown_base_height_allometry(
"domain-id", "inventory-id"
)
assert isinstance(inventory, Inventory)
Expand All @@ -565,7 +565,7 @@ def test_defaults(self, captured):
}

def test_all_fields(self, captured):
create_tree_inventory_from_crown_base_height(
create_tree_inventory_with_crown_base_height_allometry(
SimpleNamespace(id="domain-id"),
SimpleNamespace(id="inventory-id"),
model="gdam",
Expand All @@ -586,13 +586,13 @@ def test_all_fields(self, captured):

def test_rejects_unknown_model_before_request(self, captured):
with pytest.raises(ValueError, match="model must be"):
create_tree_inventory_from_crown_base_height(
create_tree_inventory_with_crown_base_height_allometry(
"domain-id", "inventory-id", model="cruz_2003"
)
assert captured == {}


class TestCreateTreeInventoryFromGdamRequest:
class TestCreateTreeInventoryWithGdamAllometryRequest:
@pytest.fixture
def captured(self, monkeypatch):
captured = {}
Expand All @@ -611,7 +611,7 @@ def fake_create(domain_id, *, client, body):
return captured

def test_defaults(self, captured):
create_tree_inventory_from_gdam("domain-id", "inventory-id")
create_tree_inventory_with_gdam_allometry("domain-id", "inventory-id")
assert captured["body"] == {
"source_tree_inventory_id": "inventory-id",
"overwrite": False,
Expand All @@ -620,7 +620,7 @@ def test_defaults(self, captured):
}

def test_crown_base_height_model_and_overwrite(self, captured):
create_tree_inventory_from_gdam(
create_tree_inventory_with_gdam_allometry(
"domain-id",
"inventory-id",
impute_columns=["dbh", "crown_base_height"],
Expand Down Expand Up @@ -1058,7 +1058,7 @@ def test_voxelize_with_crown_feature(
):
# A CHM inventory has only x, y, height; GDAM imputes the rest and
# keeps tree_id, so its trees still match the crowns.
inventory = create_tree_inventory_from_gdam(
inventory = create_tree_inventory_with_gdam_allometry(
test_domain, completed_chm_inventory, name="throwaway_gdam"
)
inventory.wait()
Expand Down
Loading