pyforestry package#
Subpackages#
- pyforestry.base package
- Subpackages
- pyforestry.base.competition package
- pyforestry.base.helpers package
- Subpackages
- Submodules
- pyforestry.base.helpers.bitterlich_angle_count module
- pyforestry.base.helpers.bucking module
- pyforestry.base.helpers.height_models module
- pyforestry.base.helpers.plot module
- pyforestry.base.helpers.stand module
- pyforestry.base.helpers.top_height module
- pyforestry.base.helpers.tree module
- pyforestry.base.helpers.tree_metrics module
- pyforestry.base.helpers.tree_species module
- pyforestry.base.helpers.utils module
- Module contents
- pyforestry.base.imputation package
- pyforestry.base.pricelist package
- pyforestry.base.simulation package
- pyforestry.base.taper package
- pyforestry.base.timber package
- pyforestry.base.timber_bucking package
- Submodules
- pyforestry.base.aggregation module
- pyforestry.base.contracts module
- Module contents
- Subpackages
- pyforestry.norway package
- pyforestry.simulation package
- Subpackages
- Submodules
- pyforestry.simulation.artifacts module
- pyforestry.simulation.contracts module
- pyforestry.simulation.forcing module
- pyforestry.simulation.policy module
- pyforestry.simulation.presets module
- pyforestry.simulation.provenance module
- pyforestry.simulation.scenario module
- pyforestry.simulation.stages module
- Module contents
- pyforestry.sweden package
- Subpackages
- pyforestry.sweden.adapters package
- pyforestry.sweden.bark package
- pyforestry.sweden.biomass package
- pyforestry.sweden.geo package
- pyforestry.sweden.growth package
- pyforestry.sweden.height package
- pyforestry.sweden.helpers package
- pyforestry.sweden.ingrowth package
- pyforestry.sweden.misc package
- pyforestry.sweden.mortality package
- Submodules
- pyforestry.sweden.mortality.bengtsson module
- pyforestry.sweden.mortality.elfving_2013 module
- pyforestry.sweden.mortality.fridman_stahl_2001 module
- pyforestry.sweden.mortality.naslund_1986 module
- pyforestry.sweden.mortality.retained_trees module
- pyforestry.sweden.mortality.root_rot_thor_stahl_stenlid_2005 module
- pyforestry.sweden.mortality.siipilehto_2020 module
- pyforestry.sweden.mortality.soderberg_1986 module
- pyforestry.sweden.mortality.types module
- Module contents
- pyforestry.sweden.pricelist package
- pyforestry.sweden.regeneration package
- pyforestry.sweden.simulation package
- pyforestry.sweden.site package
- pyforestry.sweden.siteindex package
- Subpackages
- Submodules
- pyforestry.sweden.siteindex.carbonnier_1971 module
- pyforestry.sweden.siteindex.elfving_kiviste_1997 module
- pyforestry.sweden.siteindex.eriksson_1997 module
- pyforestry.sweden.siteindex.hagglund_1970 module
- pyforestry.sweden.siteindex.hagglund_remrod_1977 module
- pyforestry.sweden.siteindex.johansson_1996 module
- pyforestry.sweden.siteindex.johansson_1999 module
- pyforestry.sweden.siteindex.johansson_2011 module
- pyforestry.sweden.siteindex.johansson_2013 module
- pyforestry.sweden.siteindex.validation module
- Module contents
- pyforestry.sweden.systems package
- pyforestry.sweden.taper package
- pyforestry.sweden.timber package
- pyforestry.sweden.volume package
- Submodules
- pyforestry.sweden.volume.andersson_1954 module
- pyforestry.sweden.volume.brandel_1990 module
- pyforestry.sweden.volume.carbonnier_1954 module
- pyforestry.sweden.volume.eriksson_1973 module
- pyforestry.sweden.volume.johnsson_1953 module
- pyforestry.sweden.volume.matern_1975 module
- pyforestry.sweden.volume.naslund_1947 module
- pyforestry.sweden.volume.soderberg_1986_form_height module
- Module contents
- Module contents
- Subpackages
Submodules#
pyforestry.catalog module#
Discover and search pyforestry’s scientific formula models.
Most formula modules publish a module-level DESCRIPTOR (see
pyforestry.base.contracts.FormulaModuleDescriptor) describing the
model’s identity, citation, species applicability, and units. This module
aggregates those descriptors so a model can be found without already knowing its
import path:
>>> from pyforestry import catalog
>>> catalog.find(domain="volume") # all volume models
>>> catalog.find(domain="growth", species="pinus") # best-effort species filter
>>> catalog.search("bark") # by id / module / citation
>>> entry = catalog.describe("soderberg_1992_bark")
>>> entry.source.title
Discovery covers pyforestry.base as well as the regions, so region-independent
models are findable too:
>>> catalog.find(region="base") # Näslund, García, Bitterlich, Näsberg
Discovery currently covers modules that expose a DESCRIPTOR; the set grows as
more modules adopt the convention.
- class pyforestry.catalog.ModelEntry(component_id: str, module: str, region: str, domain: str, source: SourceReference, species_groups: Mapping[str, frozenset[str]], units: Mapping[str, str], kernel_names: tuple[str, ...], kind: str = 'formula', composes: tuple[str, ...] = ())[source]#
Bases:
objectA discoverable formula model and its introspection metadata.
- composes: tuple[str, ...] = ()#
- kind: str = 'formula'#
- pyforestry.catalog.describe(identifier: str) ModelEntry[source]#
Return the model matching
identifier(component id or module path).Falls back to a unique case-insensitive substring match on the component id.
- Raises:
KeyError – if no model, or more than one, matches
identifier.
- pyforestry.catalog.discovery_errors() dict[str, BaseException][source]#
Return the modules the last discovery pass could not import.
Empty when everything imported. A non-empty result means the catalog is incomplete and says exactly which modules are missing and why – which is what “this model does not exist” used to look like.
- pyforestry.catalog.domains() list[str][source]#
Return the sorted set of model domains (e.g.
volume,mortality).
- pyforestry.catalog.find(*, region: str | None = None, domain: str | None = None, species: str | None = None, units: str | None = None, kind: str | None = None) list[ModelEntry][source]#
Return models matching every supplied filter (case-insensitive).
- Parameters:
region – Region name, e.g.
"sweden".domain – Domain name, e.g.
"volume". Returns both formula kernels and composed models for that domain unlesskindis also given.species – Substring matched against each model’s species identifiers. Best-effort, since identifiers are stored as
TreeNamestrings.units – Substring matched against the model’s unit names or values.
kind –
"formula"(equation kernels) or"model"(composed, runnable model adapters).
- Returns:
Matching
ModelEntryobjects, ordered by region/domain/id.
- pyforestry.catalog.list_models() list[ModelEntry][source]#
Return every discoverable model entry.
- pyforestry.catalog.refresh() None[source]#
Clear the discovery cache (e.g. after importing new model modules).
- pyforestry.catalog.regions() list[str][source]#
Return the sorted set of regions that publish discoverable models.
- pyforestry.catalog.search(query: str) list[ModelEntry][source]#
Return models whose id, module, domain, or citation contains
query.
pyforestry.projection module#
One projection, in one call.
Running a projection used to mean knowing Eriksson1976Model, StandInit,
ThinningProgram, build_context, mode_hint, SimulationSetup and
Eriksson1976ManagementSchedule – seven concepts, one of which raised
TypeError when used the way the repository’s own worked example used it.
import pyforestry as pf
result = pf.project(stand, model="elfving_2010", years=100, step=5, seed=42)
result.table # a DataFrame, one row per step
result.stand # the final state
result.provenance # what was cited, and by what
The typed constructors are all still there; this is the ninety-per-cent path, not
a replacement for them. model= resolves through
pyforestry.catalog, which is the payoff for having built a discovery layer:
the string a user finds with catalog.search("elfving") is the string they can
run.
- class pyforestry.projection.ProjectionResult(table: pd.DataFrame, stand: Stand, context: SimulationContext, provenance: Mapping[str, Any]=<factory>)[source]#
Bases:
objectWhat a projection produced, and where it came from.
- property model: GrowthModel#
The model that was stepped.
- pyforestry.projection.available_models() list[str][source]#
Return every name
project()accepts formodel=, sorted.These are single-tree/stand growth models: give one a
Standand it advances it. The composite pipelines – which build their own stand from a site and run nine models around a growth model – are a different shape and are not listed here; seeavailable_pipelines().
- pyforestry.projection.available_pipelines() list[str][source]#
Return every composite pipeline name, sorted, across all regions.
A pipeline is not something
project()can run: it reconstructs its own stand from a site rather than advancing one you supply. Build it with theget_pipelineof the region that publishes it – Sweden’s ispyforestry.sweden.simulation.presets.get_pipeline()– and drive it withinitialize(site=...)/run_projection(...).
- pyforestry.projection.project(stand: Stand, *, model: str | 'GrowthModel', years: float, step: float | None = None, seed: int | None = None, policy: 'Policy' | None = None, attrs: Mapping[str, Any] | None = None, inputs: Any | None = None, pipeline: Sequence['Step'] | None = None) ProjectionResult[source]#
Project
standforward and return the result.- Parameters:
stand – The inventory to project. Deep-copied first, so the caller’s stand is untouched and the same stand can be projected under several models or several seeds and compared. (
GrowthModel.build_contextcopies only the plot containers and shares theTreeobjects, because a model grows diameters in place. That is right for a model and wrong for a front door: it would makeproject(stand, ...)return something different the second time you called it.)model – A name from
available_models(), or aGrowthModelyou built yourself.years – Total length of the projection.
step – Length of one period. Defaults to the model’s declared
native_step_years, and to 5 years for a model that declares none, so the common case needs no argument and no guessing.seed – Root seed for every random stream the run uses. Required only if something in the run draws; without it, drawing raises rather than silently using an unseeded generator.
policy – A management policy –
Callable[[ctx], Sequence[Action]]– run before growth in each period. Triggers, schedules and rulesets are all policies; seepyforestry.base.simulation.pipeline.attrs – Site and history values the stand does not carry typed. Resolved into the model’s
Inputsduring the build, so a missing one is a named error before any time is simulated.inputs – An already-built
Inputsinstance, which skips resolution.pipeline – The ordered steps to run each period, overriding the default (management if a policy was given, then growth). Supply this to add a valuation step or reorder the phases.
- Returns:
- Raises:
ValueError – If
modelnames nothing, if the stand cannot supply what the model needs, or if the clock arguments are not positive.
Module contents#
Top-level package for pyforestry.
The compact path to a projection – you have a stand, you want it advanced:
import pyforestry as pf
result = pf.project(stand, model="elfving_2010", years=100, step=5, seed=42)
pf.available_models() lists what model= accepts.
The other shape is a composite pipeline: you have a site rather than a
stand, and want one reconstructed and grown through a whole published workflow
(NYSKOG regeneration, young-stand growth, mortality, ingrowth, valuation).
project cannot drive one, because a pipeline builds its own stand:
from pyforestry.sweden.simulation.presets import get_pipeline
pipeline = get_pipeline("elfving_2010_composite")
table = pipeline.run_projection(site=site, n_steps=20)
pf.available_pipelines() lists those. The two are named apart on purpose:
"elfving_2010" is the growth model, "elfving_2010_composite" the whole
workflow around it, and the same string used to mean both.
Everything else is lazily loaded on first access, so importing the package costs almost nothing until you reach for a region.