Live Tree Carbon Estimation¶
Estimate live tree carbon using the NSVB biomass framework with species-specific carbon fractions.
Overview¶
The live_tree() function recomputes above-ground live tree biomass from scratch using the National Scale Volume and Biomass (NSVB) framework of Westfall et al. (2023, GTR-WO-104) and converts to carbon via species-specific S10a carbon fractions. This produces carbon estimates that align with the EPA NGHGI LULUCF live tree pool and match FIADB's pre-computed CARBON_AG column for NSVB-era inventories (September 2023 onward).
import pyfia
db = pyfia.FIA("georgia.duckdb")
db.clip_by_state("GA")
db.clip_most_recent(eval_type="VOL")
# Above-ground live tree carbon
result = pyfia.live_tree(db, pool="ag")
# Total carbon (AG + BG bridge)
total = pyfia.live_tree(db, pool="total")
Function Reference¶
live_tree
¶
live_tree(db: str | FIA, pool: str = 'ag', grp_by: str | list[str] | None = None, by_species: bool = False, by_size_class: bool = False, land_type: str = 'forest', tree_domain: str | None = None, area_domain: str | None = None, plot_domain: str | None = None, totals: bool = True, variance: bool = False, most_recent: bool = False) -> DataFrame
Estimate live tree carbon from FIA data using the NSVB framework.
Recomputes above-ground live tree biomass from scratch using the
National Scale Volume and Biomass (NSVB) framework of Westfall et al.
(2023, GTR-WO-104) — the same framework USDA FIA uses to populate the
FIADB CARBON_AG column for inventories from September 2023 onward.
Species-specific live carbon fractions from Table S10a (GTR-WO-104)
replace the flat ~0.47 multiplier used by pyfia.biomass(), producing
carbon estimates that align with the EPA NGHGI LULUCF live tree pool.
Belowground carbon is bridged directly to the FIADB pre-computed
TREE.CARBON_BG column; a native NSVB coarse-root model is
deferred.
| 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:
|
pool
|
Live tree carbon pool to estimate:
TYPE:
|
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:
For complete column descriptions, see USDA FIA Database User Guide.
TYPE:
|
by_species
|
If True, group results by species code (SPCD). Convenience parameter
equivalent to adding 'SPCD' to
TYPE:
|
by_size_class
|
If True, group results by diameter size classes (1.0-4.9", 5.0-9.9", 10.0-19.9", 20.0-29.9", 30.0+ in).
TYPE:
|
land_type
|
Land type to include in estimation:
TYPE:
|
tree_domain
|
SQL-like filter expression for tree-level filtering. Example:
TYPE:
|
area_domain
|
SQL-like filter expression for area/condition-level filtering.
Example:
TYPE:
|
plot_domain
|
SQL-like filter expression for plot-level filtering.
TYPE:
|
totals
|
If True, include population-level total estimates in addition to per-acre values.
TYPE:
|
variance
|
If True, calculate and include variance and standard error estimates following Bechtold & Patterson (2005).
TYPE:
|
most_recent
|
If True, automatically filter to the most recent EXPVOL evaluation for each state in the database before estimation.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
DataFrame
|
Live tree carbon estimates with the following columns:
|
See Also
biomass : Estimate tree biomass (dry weight) using FIA's pre-computed DRYBIO columns.
pyfia.estimation.estimators.carbon.carbon : Legacy carbon estimator that reads the
FIADB CARBON_AG / CARBON_BG columns directly. live_tree is the
NSVB-native alternative; both should agree at the tree level for NSVB-era
inventories (Sep 2023 and later).
pyfia.carbon.nsvb.equations.compute_nsvb_biomass : The vectorized NSVB biomass
pipeline this function wraps.
Notes
NSVB Pipeline
For each live tree the function predicts:
- Stem inside-bark wood volume (S1a)
- Stem bark volume (S2a)
- Stem bark biomass (S6a)
- Branch biomass (S7a)
- Total AGB (S8a), predicted directly from D and H
The first four are summed and harmonized proportionally to the
directly-predicted total AGB (which becomes the truth), yielding
w_wood + w_bark + w_branch == agb by construction. Cull-reduced
wood weight uses the Harmon et al. (2011) DECAYCD=3 density
proportions (0.54 hardwood, 0.92 softwood). The hardwood/softwood
split is the SPCD < 300 rule, which is consistent with the
NSVB Model 2 k constant selection and correctly classifies
SPCD=10 (fir spp.) as softwood despite S10a's misclassification.
Carbon = AGB × species-specific S10a fraction. Species missing from S10a fall back to the S10a arithmetic mean (~0.4741), with a warn-once log entry.
Belowground Bridge
The current implementation does not include the Heath et al. (2009)
coarse-root model. When pool in ('bg', 'total'), the function reads
FIADB TREE.CARBON_BG directly and adds it to the estimate. A native
NSVB BG model is deferred.
EVALID Handling
If no EVALID is set on the database and most_recent=True, the
function auto-selects the most recent EXPVOL evaluation. For explicit
control, call db.clip_by_evalid(...) before calling
live_tree.
Examples:
Above-ground live tree carbon per acre on forestland:
>>> results = live_tree(db, pool="ag")
>>> print(f"Carbon: {results['CARBON_ACRE'][0]:.1f} tons/acre")
Total live tree carbon (AG + BG bridge) by ownership group:
>>> results = live_tree(db, pool="total", grp_by="OWNGRPCD")
>>> for row in results.iter_rows(named=True):
... print(f"OWNGRPCD {row['OWNGRPCD']}: {row['CARBON_ACRE']:.2f} tons/acre")
Above-ground carbon by species on timberland with standard errors:
>>> results = live_tree(
... db,
... pool="ag",
... by_species=True,
... land_type="timber",
... variance=True,
... )
Large live tree carbon (≥ 20" DBH) by forest type:
>>> results = live_tree(
... db,
... pool="ag",
... grp_by="FORTYPCD",
... tree_domain="DIA >= 20.0",
... totals=True,
... )
Source code in src/pyfia/carbon/live_tree.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | |
Carbon Pools¶
| Pool | Description | Method |
|---|---|---|
"ag" |
Above-ground (default) | NSVB pipeline: stem wood + bark + branches, harmonized to total AGB, then multiplied by species-specific S10a carbon fractions |
"bg" |
Below-ground (coarse roots) | Bridge to FIADB TREE.CARBON_BG (Phase 1 shortcut; native NSVB root model planned) |
"total" |
AG + BG | NSVB above-ground + FIADB below-ground bridge |
How It Differs from biomass()¶
live_tree() |
biomass() |
|
|---|---|---|
| Biomass source | Recomputed from scratch via NSVB equations | Reads FIADB pre-computed DRYBIO_* columns |
| Carbon fraction | Species-specific S10a (0.40-0.55) | Flat 0.47 multiplier |
| Coefficient lookup | 3-level precedence (DIVISION, species, Jenkins) | N/A (pre-computed) |
| Cull adjustment | NSVB cull formula with DECAYCD=3 density prop | Built into FIADB values |
| Transparency | Full recompute, auditable | Black-box FIADB values |
For NSVB-era inventories (2024+), both should agree closely. live_tree() is the preferred path for carbon accounting work that needs methodological transparency.
Technical Notes¶
The NSVB pipeline predicts five biomass components per tree:
- Stem inside-bark wood volume (S1a) x wood density x 62.4 = gross wood weight
- Stem bark biomass (S6a)
- Branch biomass (S7a)
- Total above-ground biomass (S8a) - directly predicted
The component sum is harmonized proportionally to the directly-predicted total AGB. Cull-reduced wood uses the Harmon et al. (2011) DECAYCD=3 density proportion (0.54 hardwood, 0.92 softwood). Carbon = harmonized AGB x species-specific S10a fraction.
The optional PLOTGEOM.ECOSUBCD join activates Level 2 of the NSVB coefficient precedence (SPCD + Bailey DIVISION), closing a ~3% growing-stock biomass bias present in the species-level-only fallback. When PLOTGEOM is missing from older databases, the estimator falls back gracefully with a one-shot log warning.
Examples¶
Above-Ground Carbon Per Acre¶
Carbon by Species¶
result = pyfia.live_tree(db, pool="ag", by_species=True)
result = pyfia.join_species_names(result, db)
print(result.sort("CARBON_ACRE", descending=True).head(10))
Carbon by Ownership Group¶
result = pyfia.live_tree(
db,
pool="total",
grp_by="OWNGRPCD",
totals=True,
variance=True,
)
# OWNGRPCD: 10=National Forest, 20=Other Federal,
# 30=State/Local, 40=Private
print(result)
Large Tree Carbon by Forest Type¶
result = pyfia.live_tree(
db,
pool="ag",
grp_by="FORTYPCD",
tree_domain="DIA >= 20.0",
)
result = pyfia.join_forest_type_names(result, db)
print(result)