Skip to content

Biomass Estimation

Estimate tree biomass (dry weight) and carbon content.

Overview

The biomass() function calculates biomass estimates by component.

import pyfia

db = pyfia.FIA("georgia.duckdb")
db.clip_by_state("GA")

# Above-ground biomass
result = pyfia.biomass(db, component="AG")

# Total biomass as carbon
carbon = pyfia.biomass(db, component="TOTAL", as_carbon=True)

Function Reference

biomass

biomass(db: Union[str, FIA], grp_by: Optional[Union[str, List[str]]] = None, by_species: bool = False, by_size_class: bool = False, land_type: str = 'forest', tree_type: str = 'live', component: str = 'AG', tree_domain: Optional[str] = None, area_domain: Optional[str] = None, plot_domain: Optional[str] = None, totals: bool = True, variance: bool = False, most_recent: bool = False) -> DataFrame

Estimate tree biomass and carbon from FIA data.

Calculates dry weight biomass (in tons) and carbon content using FIA's standard biomass equations and expansion factors. Implements two-stage aggregation following FIA methodology for statistically valid per-acre and total estimates.

PARAMETER DESCRIPTION
db

Database connection or path to FIA database. Can be either a path string to a DuckDB/SQLite file or an existing FIA connection object.

TYPE: Union[str, FIA]

grp_by

Column name(s) to group results by. Can be any column from the FIA tables used in the estimation (PLOT, COND, TREE). Common grouping columns include:

  • 'FORTYPCD': Forest type code
  • 'OWNGRPCD': Ownership group (10=National Forest, 20=Other Federal, 30=State/Local, 40=Private)
  • 'STATECD': State FIPS code
  • 'COUNTYCD': County code
  • 'UNITCD': FIA survey unit
  • 'INVYR': Inventory year
  • 'STDAGE': Stand age class
  • 'SITECLCD': Site productivity class
  • 'DSTRBCD1', 'DSTRBCD2', 'DSTRBCD3': Disturbance codes (from COND)
  • 'BALIVE': Basal area of live trees (from COND)

For complete column descriptions, see USDA FIA Database User Guide.

TYPE: str or list of str DEFAULT: None

by_species

If True, group results by species code (SPCD). This is a convenience parameter equivalent to adding 'SPCD' to grp_by.

TYPE: bool DEFAULT: False

by_size_class

If True, group results by diameter size classes. Size classes are defined as: 1.0-4.9", 5.0-9.9", 10.0-19.9", 20.0-29.9", 30.0+".

TYPE: bool DEFAULT: False

land_type

Land type to include in estimation:

  • 'forest': All forestland (land at least 10% stocked with forest trees of any size, or formerly having such tree cover)
  • 'timber': Productive timberland only (unreserved forestland capable of producing 20 cubic feet per acre per year)
  • 'all': All land conditions including non-forest

TYPE: (forest, timber, all) DEFAULT: 'forest'

tree_type

Tree type to include:

  • 'live': All live trees (STATUSCD == 1)
  • 'dead': Standing dead trees (STATUSCD == 2)
  • 'gs': Growing stock trees (live, merchantable, STATUSCD == 1 with specific quality requirements)
  • 'all': All trees regardless of status

TYPE: (live, dead, gs, all) DEFAULT: 'live'

component

Biomass component to estimate. Valid options include:

  • 'AG': Aboveground biomass (stem, bark, branches, foliage)
  • 'BG': Belowground biomass (coarse roots)
  • 'TOTAL': Total biomass (AG + BG)
  • 'BOLE': Main stem wood and bark
  • 'BRANCH': Live and dead branches
  • 'FOLIAGE': Leaves/needles
  • 'ROOTS': Coarse roots (same as BG)
  • 'STUMP': Stump biomass
  • 'SAPLING': Sapling biomass
  • 'TOP': Top and branches above merchantable height

Note: Not all components may be available for all species or regions. Check TREE table for available DRYBIO_* columns.

TYPE: str DEFAULT: 'AG'

tree_domain

SQL-like filter expression for tree-level filtering. Applied to TREE table. Example: "DIA >= 10.0 AND SPCD == 131".

TYPE: str DEFAULT: None

area_domain

SQL-like filter expression for area/condition-level filtering. Applied to COND table. Example: "OWNGRPCD == 40 AND FORTYPCD == 161".

TYPE: str DEFAULT: None

totals

If True, include population-level total estimates in addition to per-acre values. Totals are expanded using FIA expansion factors.

TYPE: bool DEFAULT: True

variance

If True, calculate and include variance and standard error estimates. Note: Currently uses simplified variance calculation (10% of estimate).

TYPE: bool DEFAULT: False

most_recent

If True, automatically filter to the most recent evaluation for each state in the database before estimation.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
DataFrame

Biomass and carbon estimates with the following columns:

  • BIO_ACRE : float Biomass per acre in tons (dry weight)
  • BIO_TOTAL : float (if totals=True) Total biomass in tons expanded to population level
  • CARB_ACRE : float Carbon per acre in tons (47% of biomass)
  • CARB_TOTAL : float (if totals=True) Total carbon in tons expanded to population level
  • BIO_ACRE_SE : float (if variance=True) Standard error of per-acre biomass estimate
  • BIO_TOTAL_SE : float (if variance=True and totals=True) Standard error of total biomass estimate
  • CARB_ACRE_SE : float (if variance=True) Standard error of per-acre carbon estimate
  • CARB_TOTAL_SE : float (if variance=True and totals=True) Standard error of total carbon estimate
  • AREA_TOTAL : float Total area (acres) represented by the estimation
  • N_PLOTS : int Number of FIA plots included in the estimation
  • N_TREES : int Number of individual tree records
  • YEAR : int Evaluation reference year (from EVALID). This represents the year of the complete statistical estimate, not individual plot measurement years (INVYR) which vary due to FIA's rotating panel design
  • [grouping columns] : various Any columns specified in grp_by or from by_species
See Also

volume : Estimate volume per acre (current inventory) tpa : Estimate trees per acre (current inventory) mortality : Estimate annual mortality using GRM tables growth : Estimate annual growth using GRM tables area : Estimate forestland area pyfia.constants.TreeStatus : Tree status code definitions pyfia.constants.OwnershipGroup : Ownership group code definitions pyfia.constants.ForestType : Forest type code definitions pyfia.utils.reference_tables : Functions for adding species/forest type names

Notes

Biomass is calculated using FIA's standard dry weight equations stored in the DRYBIO_* columns of the TREE table. These values are in pounds and are converted to tons by dividing by 2000.

Carbon content is estimated as 47% of dry biomass following IPCC guidelines and FIA standard practice. This percentage may vary slightly by species and component but 47% is the standard factor.

Evaluation Year vs. Inventory Year: The YEAR in output represents the evaluation reference year from EVALID, not individual plot inventory years (INVYR). Due to FIA's rotating panel design, plots within an evaluation are measured across multiple years (typically 5-7 year cycle), but the evaluation statistically represents forest conditions as of the reference year. For example, EVALID 482300 represents Texas forest conditions as of 2023, even though it includes plots measured 2019-2023.

The function implements two-stage aggregation following FIA methodology:

  1. Stage 1: Aggregate trees to plot-condition level to ensure each condition's area proportion is counted exactly once.
  2. Stage 2: Apply expansion factors and calculate ratio-of-means for per-acre estimates and population totals.

This approach prevents the ~20x underestimation that would occur with single-stage aggregation where each tree contributes its condition proportion to the denominator.

Required FIA tables and columns:

  • TREE: CN, PLT_CN, CONDID, STATUSCD, SPCD, DIA, TPA_UNADJ, DRYBIO_*
  • COND: PLT_CN, CONDID, COND_STATUS_CD, CONDPROP_UNADJ, OWNGRPCD, etc.
  • PLOT: CN, STATECD, INVYR, MACRO_BREAKPOINT_DIA
  • POP_PLOT_STRATUM_ASSGN: PLT_CN, STRATUM_CN
  • POP_STRATUM: CN, EXPNS, ADJ_FACTOR_*

Valid grouping columns depend on which tables are included in the estimation query. For a complete list of available columns and their meanings, refer to:

  • USDA FIA Database User Guide, Version 9.1
  • pyFIA documentation: https://mihiarc.github.io/pyfia/
  • FIA DataMart: https://apps.fs.usda.gov/fia/datamart/

Biomass components availability varies by FIA region and evaluation type. Check your database for available DRYBIO_* columns using:

import duckdb conn = duckdb.connect("your_database.duckdb") columns = conn.execute("PRAGMA table_info(TREE)").fetchall() biomass_cols = [c[1] for c in columns if 'DRYBIO' in c[1]]

Warnings

The variance calculation follows Bechtold & Patterson (2005) methodology for ratio-of-means estimation with stratified sampling. The calculation accounts for covariance between the numerator (biomass/carbon) and denominator (area). For applications requiring the most precise variance estimates, consider also validating against the FIA EVALIDator tool.

Some biomass components may not be available for all species or in all FIA regions. If a requested component is not available, the function will raise an error. Always verify component availability in your specific database.

RAISES DESCRIPTION
ValueError

If the specified biomass component column does not exist in the TREE table, or if grp_by contains invalid column names.

KeyError

If specified columns in grp_by don't exist in the joined tables.

RuntimeError

If no data matches the specified filters and domains.

Examples:

Basic aboveground biomass on forestland:

>>> results = biomass(db, component="AG", land_type="forest")
>>> if not results.is_empty():
...     print(f"Aboveground biomass: {results['BIO_ACRE'][0]:.1f} tons/acre")
...     print(f"Carbon storage: {results['CARB_ACRE'][0]:.1f} tons/acre")
... else:
...     print("No biomass data available")

Total biomass (above + below ground) by species:

>>> results = biomass(db, by_species=True, component="TOTAL")
>>> # Sort by biomass to find dominant species
>>> if not results.is_empty():
...     top_species = results.sort(by='BIO_ACRE', descending=True).head(5)
...     print("Top 5 species by biomass per acre:")
...     for row in top_species.iter_rows(named=True):
...         print(f"  SPCD {row['SPCD']}: {row['BIO_ACRE']:.1f} tons/acre")

Biomass by ownership on timberland:

>>> results = biomass(
...     db,
...     grp_by="OWNGRPCD",
...     land_type="timber",
...     component="AG",
...     tree_type="gs",
...     variance=True
... )
>>> # Display with standard errors
>>> for row in results.iter_rows(named=True):
...     ownership = {10: "National Forest", 20: "Other Federal",
...                  30: "State/Local", 40: "Private"}
...     name = ownership.get(row['OWNGRPCD'], f"Code {row['OWNGRPCD']}")
...     print(f"{name}: {row['BIO_ACRE']:.1f} ± {row['BIO_ACRE_SE']:.1f} tons/acre")

Large tree biomass by forest type:

>>> results = biomass(
...     db,
...     grp_by="FORTYPCD",
...     tree_domain="DIA >= 20.0",
...     component="AG",
...     totals=True
... )
>>> # Show both per-acre and total biomass
>>> for row in results.iter_rows(named=True):
...     print(f"Forest Type {row['FORTYPCD']}:")
...     print(f"  Per acre: {row['BIO_ACRE']:.1f} tons")
...     print(f"  Total: {row['BIO_TOTAL']/1e6:.2f} million tons")

Carbon storage by multiple grouping variables:

>>> results = biomass(
...     db,
...     grp_by=["STATECD", "OWNGRPCD"],
...     component="TOTAL",
...     most_recent=True
... )
>>> # Calculate total carbon by state
>>> state_carbon = results.group_by("STATECD").agg([
...     pl.col("CARB_TOTAL").sum()
... ])

Standing dead tree biomass:

>>> results = biomass(
...     db,
...     tree_type="dead",
...     component="AG",
...     by_size_class=True
... )
>>> print("Dead tree biomass by size class:")
>>> for row in results.iter_rows(named=True):
...     print(f"  {row['SIZE_CLASS']}: {row['BIO_ACRE']:.1f} tons/acre")
Source code in src/pyfia/estimation/estimators/biomass.py
def biomass(
    db: Union[str, FIA],
    grp_by: Optional[Union[str, List[str]]] = None,
    by_species: bool = False,
    by_size_class: bool = False,
    land_type: str = "forest",
    tree_type: str = "live",
    component: str = "AG",
    tree_domain: Optional[str] = None,
    area_domain: Optional[str] = None,
    plot_domain: Optional[str] = None,
    totals: bool = True,
    variance: bool = False,
    most_recent: bool = False,
) -> pl.DataFrame:
    """
    Estimate tree biomass and carbon from FIA data.

    Calculates dry weight biomass (in tons) and carbon content using FIA's
    standard biomass equations and expansion factors. Implements two-stage
    aggregation following FIA methodology for statistically valid per-acre
    and total estimates.

    Parameters
    ----------
    db : Union[str, FIA]
        Database connection or path to FIA database. Can be either a path
        string to a DuckDB/SQLite file or an existing FIA connection object.
    grp_by : str or list of str, optional
        Column name(s) to group results by. Can be any column from the
        FIA tables used in the estimation (PLOT, COND, TREE). Common
        grouping columns include:

        - 'FORTYPCD': Forest type code
        - 'OWNGRPCD': Ownership group (10=National Forest, 20=Other Federal,
          30=State/Local, 40=Private)
        - 'STATECD': State FIPS code
        - 'COUNTYCD': County code
        - 'UNITCD': FIA survey unit
        - 'INVYR': Inventory year
        - 'STDAGE': Stand age class
        - 'SITECLCD': Site productivity class
        - 'DSTRBCD1', 'DSTRBCD2', 'DSTRBCD3': Disturbance codes (from COND)
        - 'BALIVE': Basal area of live trees (from COND)

        For complete column descriptions, see USDA FIA Database User Guide.
    by_species : bool, default False
        If True, group results by species code (SPCD). This is a convenience
        parameter equivalent to adding 'SPCD' to grp_by.
    by_size_class : bool, default False
        If True, group results by diameter size classes. Size classes are
        defined as: 1.0-4.9", 5.0-9.9", 10.0-19.9", 20.0-29.9", 30.0+".
    land_type : {'forest', 'timber', 'all'}, default 'forest'
        Land type to include in estimation:

        - 'forest': All forestland (land at least 10% stocked with forest
          trees of any size, or formerly having such tree cover)
        - 'timber': Productive timberland only (unreserved forestland capable
          of producing 20 cubic feet per acre per year)
        - 'all': All land conditions including non-forest
    tree_type : {'live', 'dead', 'gs', 'all'}, default 'live'
        Tree type to include:

        - 'live': All live trees (STATUSCD == 1)
        - 'dead': Standing dead trees (STATUSCD == 2)
        - 'gs': Growing stock trees (live, merchantable, STATUSCD == 1 with
          specific quality requirements)
        - 'all': All trees regardless of status
    component : str, default 'AG'
        Biomass component to estimate. Valid options include:

        - 'AG': Aboveground biomass (stem, bark, branches, foliage)
        - 'BG': Belowground biomass (coarse roots)
        - 'TOTAL': Total biomass (AG + BG)
        - 'BOLE': Main stem wood and bark
        - 'BRANCH': Live and dead branches
        - 'FOLIAGE': Leaves/needles
        - 'ROOTS': Coarse roots (same as BG)
        - 'STUMP': Stump biomass
        - 'SAPLING': Sapling biomass
        - 'TOP': Top and branches above merchantable height

        Note: Not all components may be available for all species or regions.
        Check TREE table for available DRYBIO_* columns.
    tree_domain : str, optional
        SQL-like filter expression for tree-level filtering. Applied to
        TREE table. Example: "DIA >= 10.0 AND SPCD == 131".
    area_domain : str, optional
        SQL-like filter expression for area/condition-level filtering.
        Applied to COND table. Example: "OWNGRPCD == 40 AND FORTYPCD == 161".
    totals : bool, default True
        If True, include population-level total estimates in addition to
        per-acre values. Totals are expanded using FIA expansion factors.
    variance : bool, default False
        If True, calculate and include variance and standard error estimates.
        Note: Currently uses simplified variance calculation (10% of estimate).
    most_recent : bool, default False
        If True, automatically filter to the most recent evaluation for
        each state in the database before estimation.

    Returns
    -------
    pl.DataFrame
        Biomass and carbon estimates with the following columns:

        - **BIO_ACRE** : float
            Biomass per acre in tons (dry weight)
        - **BIO_TOTAL** : float (if totals=True)
            Total biomass in tons expanded to population level
        - **CARB_ACRE** : float
            Carbon per acre in tons (47% of biomass)
        - **CARB_TOTAL** : float (if totals=True)
            Total carbon in tons expanded to population level
        - **BIO_ACRE_SE** : float (if variance=True)
            Standard error of per-acre biomass estimate
        - **BIO_TOTAL_SE** : float (if variance=True and totals=True)
            Standard error of total biomass estimate
        - **CARB_ACRE_SE** : float (if variance=True)
            Standard error of per-acre carbon estimate
        - **CARB_TOTAL_SE** : float (if variance=True and totals=True)
            Standard error of total carbon estimate
        - **AREA_TOTAL** : float
            Total area (acres) represented by the estimation
        - **N_PLOTS** : int
            Number of FIA plots included in the estimation
        - **N_TREES** : int
            Number of individual tree records
        - **YEAR** : int
            Evaluation reference year (from EVALID). This represents the year
            of the complete statistical estimate, not individual plot measurement
            years (INVYR) which vary due to FIA's rotating panel design
        - **[grouping columns]** : various
            Any columns specified in grp_by or from by_species

    See Also
    --------
    volume : Estimate volume per acre (current inventory)
    tpa : Estimate trees per acre (current inventory)
    mortality : Estimate annual mortality using GRM tables
    growth : Estimate annual growth using GRM tables
    area : Estimate forestland area
    pyfia.constants.TreeStatus : Tree status code definitions
    pyfia.constants.OwnershipGroup : Ownership group code definitions
    pyfia.constants.ForestType : Forest type code definitions
    pyfia.utils.reference_tables : Functions for adding species/forest type names

    Notes
    -----
    Biomass is calculated using FIA's standard dry weight equations stored
    in the DRYBIO_* columns of the TREE table. These values are in pounds
    and are converted to tons by dividing by 2000.

    Carbon content is estimated as 47% of dry biomass following IPCC
    guidelines and FIA standard practice. This percentage may vary slightly
    by species and component but 47% is the standard factor.

    **Evaluation Year vs. Inventory Year**: The YEAR in output represents
    the evaluation reference year from EVALID, not individual plot inventory
    years (INVYR). Due to FIA's rotating panel design, plots within an
    evaluation are measured across multiple years (typically 5-7 year cycle),
    but the evaluation statistically represents forest conditions as of the
    reference year. For example, EVALID 482300 represents Texas forest
    conditions as of 2023, even though it includes plots measured 2019-2023.

    The function implements two-stage aggregation following FIA methodology:

    1. **Stage 1**: Aggregate trees to plot-condition level to ensure each
       condition's area proportion is counted exactly once.
    2. **Stage 2**: Apply expansion factors and calculate ratio-of-means
       for per-acre estimates and population totals.

    This approach prevents the ~20x underestimation that would occur with
    single-stage aggregation where each tree contributes its condition
    proportion to the denominator.

    Required FIA tables and columns:

    - TREE: CN, PLT_CN, CONDID, STATUSCD, SPCD, DIA, TPA_UNADJ, DRYBIO_*
    - COND: PLT_CN, CONDID, COND_STATUS_CD, CONDPROP_UNADJ, OWNGRPCD, etc.
    - PLOT: CN, STATECD, INVYR, MACRO_BREAKPOINT_DIA
    - POP_PLOT_STRATUM_ASSGN: PLT_CN, STRATUM_CN
    - POP_STRATUM: CN, EXPNS, ADJ_FACTOR_*

    Valid grouping columns depend on which tables are included in the
    estimation query. For a complete list of available columns and their
    meanings, refer to:

    - USDA FIA Database User Guide, Version 9.1
    - pyFIA documentation: https://mihiarc.github.io/pyfia/
    - FIA DataMart: https://apps.fs.usda.gov/fia/datamart/

    Biomass components availability varies by FIA region and evaluation type.
    Check your database for available DRYBIO_* columns using:

    >>> import duckdb
    >>> conn = duckdb.connect("your_database.duckdb")
    >>> columns = conn.execute("PRAGMA table_info(TREE)").fetchall()
    >>> biomass_cols = [c[1] for c in columns if 'DRYBIO' in c[1]]

    Warnings
    --------
    The variance calculation follows Bechtold & Patterson (2005) methodology
    for ratio-of-means estimation with stratified sampling. The calculation
    accounts for covariance between the numerator (biomass/carbon) and
    denominator (area). For applications requiring the most precise variance
    estimates, consider also validating against the FIA EVALIDator tool.

    Some biomass components may not be available for all species or in all
    FIA regions. If a requested component is not available, the function
    will raise an error. Always verify component availability in your
    specific database.

    Raises
    ------
    ValueError
        If the specified biomass component column does not exist in the
        TREE table, or if grp_by contains invalid column names.
    KeyError
        If specified columns in grp_by don't exist in the joined tables.
    RuntimeError
        If no data matches the specified filters and domains.

    Examples
    --------
    Basic aboveground biomass on forestland:

    >>> results = biomass(db, component="AG", land_type="forest")
    >>> if not results.is_empty():
    ...     print(f"Aboveground biomass: {results['BIO_ACRE'][0]:.1f} tons/acre")
    ...     print(f"Carbon storage: {results['CARB_ACRE'][0]:.1f} tons/acre")
    ... else:
    ...     print("No biomass data available")

    Total biomass (above + below ground) by species:

    >>> results = biomass(db, by_species=True, component="TOTAL")
    >>> # Sort by biomass to find dominant species
    >>> if not results.is_empty():
    ...     top_species = results.sort(by='BIO_ACRE', descending=True).head(5)
    ...     print("Top 5 species by biomass per acre:")
    ...     for row in top_species.iter_rows(named=True):
    ...         print(f"  SPCD {row['SPCD']}: {row['BIO_ACRE']:.1f} tons/acre")

    Biomass by ownership on timberland:

    >>> results = biomass(
    ...     db,
    ...     grp_by="OWNGRPCD",
    ...     land_type="timber",
    ...     component="AG",
    ...     tree_type="gs",
    ...     variance=True
    ... )
    >>> # Display with standard errors
    >>> for row in results.iter_rows(named=True):
    ...     ownership = {10: "National Forest", 20: "Other Federal",
    ...                  30: "State/Local", 40: "Private"}
    ...     name = ownership.get(row['OWNGRPCD'], f"Code {row['OWNGRPCD']}")
    ...     print(f"{name}: {row['BIO_ACRE']:.1f} ± {row['BIO_ACRE_SE']:.1f} tons/acre")

    Large tree biomass by forest type:

    >>> results = biomass(
    ...     db,
    ...     grp_by="FORTYPCD",
    ...     tree_domain="DIA >= 20.0",
    ...     component="AG",
    ...     totals=True
    ... )
    >>> # Show both per-acre and total biomass
    >>> for row in results.iter_rows(named=True):
    ...     print(f"Forest Type {row['FORTYPCD']}:")
    ...     print(f"  Per acre: {row['BIO_ACRE']:.1f} tons")
    ...     print(f"  Total: {row['BIO_TOTAL']/1e6:.2f} million tons")

    Carbon storage by multiple grouping variables:

    >>> results = biomass(
    ...     db,
    ...     grp_by=["STATECD", "OWNGRPCD"],
    ...     component="TOTAL",
    ...     most_recent=True
    ... )
    >>> # Calculate total carbon by state
    >>> state_carbon = results.group_by("STATECD").agg([
    ...     pl.col("CARB_TOTAL").sum()
    ... ])

    Standing dead tree biomass:

    >>> results = biomass(
    ...     db,
    ...     tree_type="dead",
    ...     component="AG",
    ...     by_size_class=True
    ... )
    >>> print("Dead tree biomass by size class:")
    >>> for row in results.iter_rows(named=True):
    ...     print(f"  {row['SIZE_CLASS']}: {row['BIO_ACRE']:.1f} tons/acre")
    """
    # Import validation functions
    from ...validation import (
        validate_biomass_component,
        validate_boolean,
        validate_domain_expression,
        validate_grp_by,
        validate_land_type,
        validate_tree_type,
    )

    # Validate inputs
    land_type = validate_land_type(land_type)
    tree_type = validate_tree_type(tree_type)
    component = validate_biomass_component(
        component.lower()
    ).upper()  # Normalize and convert to uppercase for column names
    grp_by = validate_grp_by(grp_by)
    tree_domain = validate_domain_expression(tree_domain, "tree_domain")
    area_domain = validate_domain_expression(area_domain, "area_domain")
    plot_domain = validate_domain_expression(plot_domain, "plot_domain")
    by_species = validate_boolean(by_species, "by_species")
    by_size_class = validate_boolean(by_size_class, "by_size_class")
    totals = validate_boolean(totals, "totals")
    variance = validate_boolean(variance, "variance")
    most_recent = validate_boolean(most_recent, "most_recent")

    # Create config
    config = {
        "grp_by": grp_by,
        "by_species": by_species,
        "by_size_class": by_size_class,
        "land_type": land_type,
        "tree_type": tree_type,
        "component": component,
        "tree_domain": tree_domain,
        "area_domain": area_domain,
        "plot_domain": plot_domain,
        "totals": totals,
        "variance": variance,
        "most_recent": most_recent,
    }

    # Create and run estimator
    estimator = BiomassEstimator(db, config)
    return estimator.estimate()

Biomass Components

Component Description FIA Column
"AG" Above-ground (default) DRYBIO_AG
"BG" Below-ground DRYBIO_BG
"TOTAL" Total biomass DRYBIO_AG + DRYBIO_BG
"STEM" Stem wood DRYBIO_STEM
"STUMP" Stump DRYBIO_STUMP
"TOP" Top and branches DRYBIO_TOP
"FOLIAGE" Foliage DRYBIO_FOLIAGE

Carbon Conversion

When as_carbon=True, biomass is multiplied by 0.47 (standard carbon fraction).

Examples

Above-Ground Biomass by Species

result = pyfia.biomass(db, component="AG", grp_by="SPCD")
result = pyfia.join_species_names(result, db)
print(result.sort("estimate", descending=True).head(10))

Total Carbon Stock

result = pyfia.biomass(
    db,
    component="TOTAL",
    as_carbon=True,
    land_type="forest"
)
print(f"Carbon: {result['estimate'][0]:,.0f} tons")

Biomass on Timberland

result = pyfia.biomass(
    db,
    component="AG",
    land_type="timber",
    tree_type="gs"
)

Biomass by Forest Type

result = pyfia.biomass(
    db,
    component="AG",
    grp_by="FORTYPGRPCD"
)
result = pyfia.join_forest_type_names(result, db)
print(result)