pyforestry.sweden.systems package#

Subpackages#

Submodules#

pyforestry.sweden.systems.elfving_hagglund_1975 module#

Elfving & Hägglund (1975): stems and basal area in young Swedish stands.

Elfving, B. & Hägglund, B. (1975). Utgångslägen för produktionsprognoser: tall och gran i Sverige. /Initial stands for yield forecasts: Scots pine and Norway spruce in Sweden./ Rapporter och Uppsatser 38, Institutionen för skogsproduktion, Skogshögskolan, Stockholm.

Eight functions, four per response, grouped by species and part of the country:

  • f5.1-f5.4, ln(stamantal/ha) – stems per hectare, table p. 42.

  • f6.1-f6.4, ln(grundyta/ha) in dm² – basal area per hectare, table p. 53. Hence the / 100 each basal-area function ends with.

Every coefficient in all eight was read off those two tables and matches this implementation exactly, including the pine-southern basal-area intercept 1.280 that previously carried a TODO for want of a primary-source check.

Units are the tables’ own “Sort” column, and two are folded into the coefficient rather than the variable, so the printed number does not always appear here literally:

  • Latitude is tabulated per 0.1°, so the printed -0.0033 is written -0.033 with latitude in whole degrees.

  • Density (slutenhet) is tabulated in tenths, so a factor of 0.1-1.0 is scaled to 1-10 before use.

One reading is not settled by the tables; see ElfvingHagglundInitialStand.estimate_basal_area_young_pine_north() for the altitude transform, which is written there rather than here because that is where it is computed.

class pyforestry.sweden.systems.elfving_hagglund_1975.ElfvingHagglundInitialStand[source]#

Bases: object

Provides methods to estimate initial stand density (stems/ha) and basal area (m²/ha) for young Spruce and Pine stands in Sweden, based on the models published by Elfving & Hägglund (1975).

Estimates are generally for stems thicker than 2.5 cm at breast height.

References

Elfving, B., Hägglund, B. (1975). Utgångslägen för produktionsprognoser: Tall och gran i Sverige. Skogshögskolan, Inst. f. skogsproduktion. Rapp. o. Upps. Nr 38. Stockholm. 75 pp.

static estimate_basal_area_young_pine_north(latitude: float, altitude: float, site_index: SiteIndexValue, dominant_height: float, stems: Stems | None = None, stand_density_factor: float = 0.65, broadleaves_percent_ba: float = 0.0, pct: bool = False, even_or_somewhat_uneven_aged: bool = True) → StandBasalArea[source]#

Estimates initial basal area (m²/ha) for young Pine in Northern Sweden. Based on Function 6.1, Elfving & Hägglund (1975), p. 53.

Parameters:
  • latitude – Latitude, degrees N.

  • altitude – Altitude, meters above sea level.

  • site_index – Site index H100 (m).

  • dominant_height – Dominant height (m).

  • stems – Stems per hectare. If None, estimated internally.

  • stand_density_factor – Stand density factor (0.1-1.0).

  • broadleaves_percent_ba – Percentage of broadleaves in BA (0-100).

  • pct – True if pre-commercial thinning has occurred.

  • even_or_somewhat_uneven_aged – True if stand is even or somewhat uneven-aged.

Returns:

Estimated basal area (m²/ha).

static estimate_basal_area_young_pine_south(latitude: float, altitude: float, site_index: SiteIndexValue, dominant_height: float, stems: Stems | None = None, age_at_breast_height: AgeMeasurement | None = None, stand_density_factor: float = 0.65, uneven_aged: bool = False, pct: bool = False, regeneration: str = 'culture') → StandBasalArea[source]#

Estimates initial basal area (m²/ha) for young Pine in Southern Sweden. Based on Function 6.2, Elfving & Hägglund (1975), p. 53.

Parameters:
  • latitude – Latitude, degrees N.

  • altitude – Altitude, meters above sea level.

  • site_index – Site index H100 (m).

  • dominant_height – Dominant height (m).

  • stems – Stems per hectare. If None, estimated internally.

  • age_at_breast_height – Age at breast height. Required if stems is None.

  • stand_density_factor – Stand density factor (0.1-1.0).

  • uneven_aged – True if the stand is uneven-aged.

  • pct – True if pre-commercial thinning has occurred.

  • regeneration – Method of establishment (“culture”, “natural regeneration”, “unknown”).

Returns:

Estimated basal area (m²/ha).

static estimate_basal_area_young_spruce_north(altitude: float, site_index: SiteIndexValue, dominant_height: float, stems: Stems | None = None, stand_density_factor: float = 0.65, broadleaves_percent_ba: float = 0.0, spatial_distribution: int = 1, pct: bool = False, even_or_somewhat_uneven_aged: bool = True) → StandBasalArea[source]#

Estimates initial basal area (m²/ha) for young Spruce in Northern Sweden. Based on Function 6.3, Elfving & Hägglund (1975), p. 53.

Parameters:
  • altitude – Altitude, meters above sea level.

  • site_index – Site index H100 (m).

  • dominant_height – Dominant height (m).

  • stems – Stems per hectare. If None, estimated internally.

  • stand_density_factor – Stand density factor (0.1-1.0).

  • broadleaves_percent_ba – Percentage of broadleaves in BA (0-100).

  • spatial_distribution – Code for spatial distribution (1, 2, or 3).

  • pct – True if pre-commercial thinning has occurred.

  • even_or_somewhat_uneven_aged – True if stand is even or somewhat uneven-aged.

Returns:

Estimated basal area (m²/ha).

static estimate_basal_area_young_spruce_south(altitude: float, site_index: SiteIndexValue, dominant_height: float, age_at_breast_height: AgeMeasurement, stems: Stems | None = None, stand_density_factor: float = 0.65, broadleaves_percent_ba: float = 0.0, spatial_distribution: int = 1, even_or_somewhat_uneven_aged: bool = True, pct: bool = False) → StandBasalArea[source]#

Estimates initial basal area (m²/ha) for young Spruce in Southern Sweden. Based on Function 6.4, Elfving & Hägglund (1975), p. 53.

Parameters:
  • altitude – Altitude, meters above sea level.

  • site_index – Site index H100 (m).

  • dominant_height – Dominant height (m).

  • age_at_breast_height – Age at breast height (years). Required if stems is None.

  • stems – Stems per hectare. If None, estimated internally.

  • stand_density_factor – Stand density factor (0.1-1.0).

  • broadleaves_percent_ba – Percentage of broadleaves in BA (0-100).

  • spatial_distribution – Code for spatial distribution (1, 2, or 3).

  • even_or_somewhat_uneven_aged – True if stand is even or somewhat uneven-aged.

  • pct – Pre-commercial thinning flag (used only if stems need estimation).

Returns:

Estimated basal area (m²/ha).

static estimate_initial_spruce_stand(dominant_height: float, age_bh: AgeMeasurement, site_index: SiteIndexValue, altitude: float, northern_sweden: bool = True, broadleaves_percent_ba: float = 0, even_aged: bool = True, stand_density_factor: float = 0.65, pct: bool = False, spatial_distribution: int = 1) → Tuple[Stems, StandBasalArea][source]#

Estimates initial stems/ha and basal area/ha for Spruce stands. (Combined function calling specific estimators based on region).

Parameters:
  • dominant_height – Dominant height of the stand (m).

  • age_bh – Age at breast height (years).

  • site_index – Site index object (e.g., H100). The numeric value is used.

  • altitude – Altitude (meters above sea level).

  • northern_sweden – True if the site is in Northern Sweden, False otherwise.

  • broadleaves_percent_ba – Percentage of broadleaves in the basal area (0-100).

  • even_aged – True if the stand is considered even-aged or somewhat uneven-aged.

  • stand_density_factor – A factor related to target density (0.1 to 1.0).

  • pct – True if pre-commercial thinning has occurred.

  • spatial_distribution – Code indicating spatial distribution (1=even, 2=somewhat uneven, 3=grouped).

Returns:

  • Stems: Estimated number of stems per hectare.

  • StandBasalArea: Estimated basal area (m²/ha).

Return type:

A tuple containing

static estimate_stems_young_pine_north(latitude: float, altitude: float, dominant_height: float, stand_density_factor: float = 0.65, pct: bool = False, even_or_somewhat_uneven_aged: bool = True) → Stems[source]#

Estimates initial stems/ha (>2.5cm DBH) for young Pine in Northern Sweden. Based on Function 5.1, Elfving & Hägglund (1975), p. 42.

Parameters:
  • latitude – Latitude, degrees N.

  • altitude – Altitude, meters above sea level.

  • dominant_height – Dominant height, meters.

  • stand_density_factor – Stand density factor (0.1-1.0).

  • pct – True if pre-commercial thinning has occurred.

  • even_or_somewhat_uneven_aged – True if stand is even or somewhat uneven-aged.

Returns:

Estimated number of stems per hectare (>2.5cm DBH).

static estimate_stems_young_pine_south(latitude: float, site_index: SiteIndexValue, dominant_height: float, age_at_breast_height: AgeMeasurement | None = None, stand_density_factor: float = 0.65, pct: bool = False, regeneration: str = 'culture') → Stems[source]#

Estimates initial stems/ha (>2.5cm DBH) for young Pine in Southern Sweden. Based on Function 5.2, Elfving & Hägglund (1975), p. 42.

Parameters:
  • latitude – Latitude (used if age needs calculation).

  • site_index – Site index H100 (m).

  • dominant_height – Dominant height (m).

  • age_at_breast_height – Age at breast height. If None, it attempts calculation (Not Implemented Yet).

  • stand_density_factor – Stand density factor (0.1-1.0).

  • pct – True if pre-commercial thinning has occurred.

  • regeneration – Method of establishment (“culture”, “natural regeneration”, “unknown”). Used if age needs calculation.

Returns:

Estimated number of stems per hectare (>2.5cm DBH).

static estimate_stems_young_spruce_north(altitude: float, site_index: SiteIndexValue, stand_density_factor: float = 0.65, broadleaves_percent_ba: float = 0.0, pct: bool = False, even_or_somewhat_uneven_aged: bool = True) → Stems[source]#

Estimates initial stems/ha (>2.5cm DBH) for young Spruce in Northern Sweden. Based on Function 5.3, Elfving & Hägglund (1975), p. 42.

Parameters:
  • altitude – Altitude, meters above sea level.

  • site_index – Site index H100 (m).

  • stand_density_factor – Stand density factor (0.1-1.0).

  • broadleaves_percent_ba – Percentage of broadleaves in BA (0-100).

  • pct – True if pre-commercial thinning has occurred.

  • even_or_somewhat_uneven_aged – True if stand is even or somewhat uneven-aged.

Returns:

Estimated number of stems per hectare (>2.5cm DBH).

static estimate_stems_young_spruce_south(altitude: float, site_index: SiteIndexValue, age_at_breast_height: AgeMeasurement, stand_density_factor: float = 0.65, broadleaves_percent_ba: float = 0.0, even_or_somewhat_uneven_aged: bool = True) → Stems[source]#

Estimates initial stems/ha (>2.5cm DBH) for young Spruce in Southern Sweden. Based on Function 5.4, Elfving & Hägglund (1975), p. 42.

Parameters:
  • altitude – Altitude, meters above sea level.

  • site_index – Site index H100 (m).

  • age_at_breast_height – Age at breast height (years).

  • stand_density_factor – Stand density factor (0.1-1.0).

  • broadleaves_percent_ba – Percentage of broadleaves in BA (0-100).

  • even_or_somewhat_uneven_aged – True if stand is even or somewhat uneven-aged.

Returns:

Estimated number of stems per hectare (>2.5cm DBH).

pyforestry.sweden.systems.eriksson_1976 module#

Eriksson (1976) spruce production model (FORTRAN77 port).

This port keeps the original growth, thinning, and mortality logic while integrating with pyforestry primitives:

  • Site index and height trajectories use Hagglund (1970). The southern trajectory delegates to the shared module (it matches the FORTRAN GRANS exactly). The northern trajectory uses an Eriksson-local Hagglund function 8.4 (_solve_northern_spruce_8_4()) to match the FORTRAN GRANN (latitude-independent) rather than the shared module’s latitude-refined function 8.7. StandInit.reproduce_fortran_errors flips the two known transcription errors in the canonical listing’s GRANN (RK exponent, RM2 intercept).

  • Initial stems/basal area use Elfving & Hagglund (1975) when not supplied. This is the same model as the FORTRAN’s built-in generator (labels 600-616, comment “HAGGLUND, ELFVING”): the FORTRAN Q/R regressions are Functions 5.3/5.4 (stems) and 6.3 (basal area), and its X(1) > 3.5 branch is the north/south split (see estimate_initial_stand()).

  • Thinning schedules support age, basal-area, and dominant-height intervals; the last mirrors FORTRAN IV=2 by converting height targets to ages (_height_program_to_age()).

class pyforestry.sweden.systems.eriksson_1976.Eriksson1976ManagementSchedule(program: ThinningProgram, state_prefix: str = 'eriksson_1976_schedule', action_name: str = 'schedule_thinning')[source]#

Bases: object

Bridge ThinningProgram schedules into simulation triggers.

action_name: str = 'schedule_thinning'#
initialize(ctx: SimulationContext) → None[source]#

Seed schedule state keys in the simulation context.

policy() → Callable[[SimulationContext], Sequence[Action]][source]#

Return this schedule as a management policy for a simulation pipeline.

The schedule used to be handed out as a list of TriggerSpec objects for SimulationSetup to evaluate. A policy is the same decision – look at the stand, decide whether to thin – expressed as the one type the pipeline understands, and its exceptions are no longer swallowed into a history row.

state_prefix: str = 'eriksson_1976_schedule'#
class pyforestry.sweden.systems.eriksson_1976.Eriksson1976Model(init: StandInit | None = None, program: ThinningProgram | None = None, *, track_history: bool = False)[source]#

Bases: GrowthModel

Simulation adapter for the Eriksson (1976) stand model.

available_actions() → Dict[str, ActionSpec][source]#

Expose simulation actions supported by the model.

build_context(stand: Stand, *, init: StandInit | None = None, program: ThinningProgram | None = None, track_history: bool | None = None, **kwargs: Any) → SimulationContext[source]#

Build a simulation context with an attached Eriksson 1976 stand.

property component_id: str#

Stable identifier for the Eriksson 1976 stand model.

requirements() → Requirements[source]#

Declare aggregate inventory requirements.

property source: SourceReference#

Bibliographic provenance for the Eriksson 1976 stand model.

update_step(ctx: SimulationContext, dt: float) → None[source]#

Advance the stand model and sync aggregate metrics.

class pyforestry.sweden.systems.eriksson_1976.Eriksson1976Stand(init: StandInit, program: ThinningProgram | None = None, *, track_history: bool = False)[source]#

Bases: object

Stateful stand simulator for the Eriksson (1976) model.

property basal_area_m2_per_ha: float#

Current basal area (m²/ha) over bark.

property bh_age: float#

Current breast-height age.

property dominant_height_m: float#

Current dominant height (m).

property done: bool#

Whether the simulator has reached a stopping condition.

grow(years: float, *, thinning: ThinningRequest | Mapping[str, Any] | None = None) → Dict[str, Any] | None[source]#

Advance the stand by years with an optional thinning.

property last_row: Dict[str, Any] | None#

Last output row produced by the simulator.

property qmd_cm: float#

Current quadratic mean diameter (cm).

run() → Eriksson1976Stand[source]#

Run scheduled simulation until completion.

property self_thinning_summary: Dict[str, float]#

Summary of self-thinning removals accumulated to date.

property stems_per_ha: float#

Current stem density per hectare.

step() → Dict[str, Any] | None[source]#

Advance the stand using scheduled thinning and step length.

property total_age: float#

Current total age including time to breast height.

property track_history: bool#

Whether the stand records all output rows.

property volume_m3sk: float#

Current stand compute_stand_volume_m3sk (m³sk/ha).

class pyforestry.sweden.systems.eriksson_1976.SimulationResult(rows: List[Dict[str, Any]], self_thinning_summary: Dict[str, float])[source]#

Bases: object

Simulation outputs for Eriksson (1976).

class pyforestry.sweden.systems.eriksson_1976.StandInit(region: Literal['north', 'south', 1, 2], h100_m: float, start_bh_age: float, final_bh_age: float | None = None, final_total_age: float | None = None, stems: float | None = None, basal_area: float | None = None, latitude: float | None = None, altitude_m: float = 0.0, stand_density_factor: float = 0.65, broadleaves_percent_ba: float = 0.0, even_aged: bool = True, spatial_distribution: int = 1, pct: bool = False, growth_scaling: int = 1, culture_class: int = 1, vg: float = 100.0, use_culture_height: bool = False, reproduce_fortran_errors: bool = False)[source]#

Bases: object

Initial stand and site specification for the Eriksson (1976) model.

altitude_m: float = 0.0#
basal_area: float | None = None#
broadleaves_percent_ba: float = 0.0#
culture_class: int = 1#
even_aged: bool = True#
final_bh_age: float | None = None#
final_total_age: float | None = None#
growth_scaling: int = 1#
pct: bool = False#
reproduce_fortran_errors: bool = False#
spatial_distribution: int = 1#
stand_density_factor: float = 0.65#
stems: float | None = None#
use_culture_height: bool = False#
vg: float = 100.0#
class pyforestry.sweden.systems.eriksson_1976.ThinningProgram(interval_type: ~typing.Literal['age', 'basal_area', 'dominant_height'], first_trigger: float, intervals: ~typing.Sequence[float] = <factory>, outtake_type: ~typing.Literal['percent', 'residual', 'absolute'] = 'percent', outtakes: ~typing.Sequence[float] = <factory>, diameter_factors: ~typing.Sequence[float] = <factory>, use_diameter_factors: bool = False)[source]#

Bases: object

Thinning program for Eriksson (1976).

Units of first_trigger and intervals depend on interval_type:

  • "age": first_trigger is the first thinning breast-height age (years) and intervals are the year gaps between successive thinnings.

  • "basal_area": first_trigger is the standing basal area (m2/ha) that triggers the first thinning and intervals are basal-area increments (m2/ha).

  • "dominant_height": first_trigger is the first target dominant height (m) and intervals are successive dominant-height increments (m). Mirrors FORTRAN IV=2: the targets are converted to breast-height ages via the site’s height trajectory and the simulation then runs on the age scheduler.

outtake_type: Literal['percent', 'residual', 'absolute'] = 'percent'#
use_diameter_factors: bool = False#
class pyforestry.sweden.systems.eriksson_1976.ThinningRequest(outtake: float, outtake_type: Literal['percent', 'residual', 'absolute'] = 'percent', diameter_factor: float | None = None)[source]#

Bases: object

Explicit thinning request for a single growth step.

diameter_factor: float | None = None#
outtake_type: Literal['percent', 'residual', 'absolute'] = 'percent'#
pyforestry.sweden.systems.eriksson_1976.estimate_initial_stand(init: StandInit) → Tuple[float, float, float, SiteIndexValue, float][source]#

Compute dominant height, stems, and basal area for the initial stand.

When stems/basal_area are not supplied, they are generated with Elfving & Hagglund (1975) via ElfvingHagglundInitialStand. This is the same model as the FORTRAN’s built-in generator (labels 600-616): its stem regression Q is Function 5.3 (north) / 5.4 (south) and its basal-area regression R is Function 6.3 – the slope coefficients match to the digit (altitude, density, SI > 22 i.e. H100 > 220 dm, broadleaves, stems, spatial distribution). The FORTRAN X inputs map to StandInit fields: altitude -> altitude_m, stand-density factor -> stand_density_factor, broadleaves -> broadleaves_percent_ba, spatial/age structure -> spatial_distribution / even_aged, pre-commercial thinning -> pct.

pyforestry.sweden.systems.eriksson_1976.simulate(init: StandInit, program: ThinningProgram) → SimulationResult[source]#

Run the Eriksson (1976) simulation.

pyforestry.sweden.systems.nystrom_soderberg_1987 module#

Nyström & Söderberg (1987) young-stand functions for age and diameter.

class pyforestry.sweden.systems.nystrom_soderberg_1987.NystromSoderberg1987[source]#

Bases: object

Age at breast height and dbh-from-height functions.

static age_at_breast_height(*, height_dm: float, mean_height_dm: float, site_index_dm: float, species: TreeName, stub_indicator: float = 0.0, european_birch_indicator: float | None = None) → float[source]#

Compute sapling age at breast height (years).

Parameters:
  • height_dm (float) – Tree height in decimetres.

  • mean_height_dm (float) – Mean height (dm) for saplings on the plot.

  • site_index_dm (float) – Site index in decimetres.

  • species (TreeName) – Tree species.

  • stub_indicator (float) – Indicator for vegetatively propagated birch (0/1).

  • european_birch_indicator (float | None) – Indicator for Betula pendula (0/1).

Returns:

Age at breast height (years). For height < 12 dm, returns -1.

Return type:

float

static dbh_from_height(*, height_dm: float, species: TreeName, total_height_sqr_m2_per_100m2: float, broadleaf_height_sqr_share: float, natural_regeneration: int, cleaning_indicator: int, years_since_cleaning: int, altitude_m: float, latitude_deg: float, shrubs: int, herb_grass: int, near_coast: int, site_index_pine_m: float, h_max_m: float, veg: int = 0) → float[source]#

Estimate dbh (cm) from height and stand context.

Parameters:
  • height_dm (float) – Tree height in decimetres.

  • species (TreeName) – Tree species.

  • total_height_sqr_m2_per_100m2 (float) – Sum of height^2 (m2/100m2).

  • broadleaf_height_sqr_share (float) – Broadleaf share of height^2 (0..1).

  • natural_regeneration (int) – Indicator for natural regeneration.

  • cleaning_indicator (int) – Indicator for cleaning in last 10 years.

  • years_since_cleaning (int) – Years since cleaning (0/5/10).

  • altitude_m (float) – Altitude (m).

  • latitude_deg (float) – Latitude (degrees).

  • shrubs (int) – Shrub indicator.

  • herb_grass (int) – Herb/grass indicator.

  • near_coast (int) – Indicator for distance-to-coast < 5 km.

  • site_index_pine_m (float) – Pine site index (m).

  • h_max_m (float) – Mean height of three tallest trees (m).

  • veg (int) – Indicator for vegetatively propagated birch (0/1).

Returns:

Diameter at breast height (cm).

Return type:

float

pyforestry.sweden.systems.persson_1992 module#

Persson (1992) Scots Pine production model.

This port implements a stand-level growth simulator for Scots Pine (Pinus sylvestris L.) in Sweden, based on:

Persson, O. A. (1992). En produktionsmodell för tallskog i Sverige (A growth simulator for Scots Pine in Sweden). Report No. 31, Dept. of Forest Yield Research, Swedish University of Agricultural Sciences, Garpenberg. ISSN 0348-7636.

The primary driving function is a basal-area increment function (Function 2, p. 56). Supporting regressions cover standing volume, bark area, annual natural mortality in basal area, and the diameter ratio of self-thinned stems. Height growth is estimated with Hägglund (1974) site-index curves via pyforestry.sweden.siteindex.hagglund_1970. Initial stem count and basal area, when not supplied, are estimated with Elfving & Hägglund (1975).

class pyforestry.sweden.systems.persson_1992.Persson1992Model(init: PerssonStandInit | None = None, program: PerssonThinningProgram | None = None, *, track_history: bool = False)[source]#

Bases: GrowthModel

Simulation adapter for the Persson (1992) Scots Pine model.

available_actions() → Dict[str, ActionSpec][source]#

The one thing a management policy can ask this model to do.

build_context(stand: Stand, *, init: PerssonStandInit | None = None, program: PerssonThinningProgram | None = None, track_history: bool | None = None, **kwargs: Any) → SimulationContext[source]#

Build a context around a live stand simulator.

Unlike a yield-table model, this one is stepped rather than tabulated: the context carries the Persson1992Stand itself, because a thinning scheduled mid-run changes everything after it.

Parameters:
  • stand – The stand. Read for its persson_1992_init and persson_1992_program attributes, and for the stems, basal area, latitude and altitude the starting state leaves out.

  • init – The starting state, taking precedence over both.

  • program – The thinning schedule, likewise.

  • track_history – Overrides the model’s own setting for this run.

  • **kwargs – Passed to GrowthModel.build_context().

Raises:

ValueError – If no starting state can be resolved.

property component_id: str#

The catalog key for this model.

requirements() → Requirements[source]#

Aggregate: the model steps a whole-stand basal area and stem number.

Persson’s functions are stand-level throughout, so a tree list would be reduced to those two numbers and its detail discarded.

property source: SourceReference#

The report this growth and yield system is taken from.

update_step(ctx: SimulationContext, dt: float) → None[source]#

Grow the stand by dt years, applying any queued thinning first.

The thinning is popped from the context state, so one scheduled through available_actions() fires once and not every step after. years_since_thin restarts at nought when one fires, which is what the thinning-response term in the growth functions reads.

class pyforestry.sweden.systems.persson_1992.Persson1992Stand(init: PerssonStandInit, program: PerssonThinningProgram | None = None, *, track_history: bool = False)[source]#

Bases: object

Stateful stand simulator for Persson (1992) Scots Pine.

property basal_area_m2_per_ha: float#

Basal area over bark (m2/ha). The under-bark twin drives the growth.

property bh_age: float#

Breast-height age (years). The clock every function here is fitted on.

property dominant_height_m: float#

Dominant height (m) at the present breast-height age.

property done: bool#

Whether the run has reached its final age. run() is idempotent.

grow(years: float, *, thinning: PerssonThinningRequest | Mapping[str, Any] | None = None) → Dict[str, Any] | None[source]#

Advance the stand by years with an optional thinning.

property last_row: Dict[str, Any] | None#

The most recent step’s figures, or None before the first step.

property qmd_cm: float#

Quadratic mean diameter (cm) over bark, from basal area and stems.

run() → Persson1992Stand[source]#

Run scheduled simulation until completion.

property self_thinning_summary: Dict[str, float]#

What self-thinning has taken since the run started, cumulatively.

Mortality is a separate account from the thinnings a programme prescribes: this is the wood the stand lost on its own, and it is never harvested.

property stems_per_ha: float#

Living stems per hectare, after any thinning and self-thinning.

step() → Dict[str, Any] | None[source]#

Advance the stand using the scheduled thinning program.

property total_age: float#

breast-height age plus the years to reach 1.3 m.

Type:

Total age (years)

property track_history: bool#

Whether every step is kept in rows, not just the last.

property volume_m3sk: float#

Standing volume (m3sk/ha) of the living stand as it now stands.

class pyforestry.sweden.systems.persson_1992.PerssonSimulationResult(rows: List[Dict[str, Any]], self_thinning_summary: Dict[str, float])[source]#

Bases: object

Simulation outputs for Persson (1992).

class pyforestry.sweden.systems.persson_1992.PerssonStandInit(h100_m: float, start_bh_age: float, latitude: float = 64.0, altitude_m: float = 0.0, final_bh_age: float | None = None, final_total_age: float | None = None, stems: float | None = None, basal_area: float | None = None, stand_density_factor: float = 0.65, broadleaves_percent_ba: float = 0.0, even_aged: bool = True, pct: bool = False, regeneration: Literal['culture', 'natural', 'unknown'] = 'culture')[source]#

Bases: object

Initial stand and site specification for the Persson (1992) model.

altitude_m: float = 0.0#
basal_area: float | None = None#
broadleaves_percent_ba: float = 0.0#
even_aged: bool = True#
final_bh_age: float | None = None#
final_total_age: float | None = None#
pct: bool = False#
regeneration: Literal['culture', 'natural', 'unknown'] = 'culture'#
stand_density_factor: float = 0.65#
stems: float | None = None#
class pyforestry.sweden.systems.persson_1992.PerssonThinningProgram(interval_type: ~typing.Literal['age', 'basal_area'], first_trigger: float, intervals: ~typing.Sequence[float] = <factory>, outtake_type: ~typing.Literal['percent', 'residual', 'absolute'] = 'percent', outtakes: ~typing.Sequence[float] = <factory>, diameter_factors: ~typing.Sequence[float] = <factory>, use_diameter_factors: bool = False)[source]#

Bases: object

Thinning program for Persson (1992).

outtake_type: Literal['percent', 'residual', 'absolute'] = 'percent'#
use_diameter_factors: bool = False#
class pyforestry.sweden.systems.persson_1992.PerssonThinningRequest(outtake: float, outtake_type: Literal['percent', 'residual', 'absolute'] = 'percent', diameter_factor: float | None = None)[source]#

Bases: object

Explicit thinning request for a single growth step.

diameter_factor: float | None = None#
outtake_type: Literal['percent', 'residual', 'absolute'] = 'percent'#
pyforestry.sweden.systems.persson_1992.persson_estimate_initial_stand(init: PerssonStandInit) → Tuple[float, float, float, SiteIndexValue, float][source]#

Compute dominant height, stems, basal area, site index, and T13.

Returns:

(hdom_m, stems, basal_area_ob, site_index, t13)

pyforestry.sweden.systems.persson_1992.persson_simulate(init: PerssonStandInit, program: PerssonThinningProgram) → PerssonSimulationResult[source]#

Run the Persson (1992) simulation and return the result.

pyforestry.sweden.systems.petterson_1955 module#

Petterson (1955) coniferous-forest yield-table model.

This port reconstructs the stand-development / yield-table engine of

Petterson, H. (1955). Barrskogens volymproduktion (The yield of coniferous forests). Meddelanden från Statens skogsforskningsinstitut, Band 45:1. Stockholm.

The model represents a stand by a left-truncated normal diameter distribution discretised into 12 relative diameter (”phi”) classes. It advances the stand in five-year steps interleaved with low-/through-thinning “moments”, and produces the classic yield table (age, dominant height, mean diameter, stems, basal area and volume before/after thinning, increments and thinning percentages).

Structure of the method (chapter references are to Petterson 1955):

  • Truncated-normal geometry and structure factors M', sigma' and the retained-stem fraction F(phi) — Kap 9.3 and appendix M7. The underlying normal N(Mn, sigma_n) is cut at +3 sigma (upper limit L) and truncated from the left at alpha; phi = (L - alpha) / sigma_n.

  • Diameter development D = A + B * d0 — Kap 21. Over one five-year period the mean-diameter growth ratio R comes from the growth-percent function F_.3 (R' = 1.01 R, b = 0.96 R'); the lower limit alpha follows alpha = R' (0.04 [Ms2] + 0.96 [alpha]) and B = prod(b), A = alpha - B alpha0. Gran, Norra Sverige uses the special radius regressions of appendix M31 instead (see _m31_ab()).

  • Height — the dominant-height trajectory over age (Kap 7.5, exponent n=3) and the Näslund within-stand height/diameter curve (Kap 22, K from F_.4).

  • Volume — per-class Näslund (1947) “minor” volume functions under bark (delegated to pyforestry.sweden.volume.naslund_1947.NaslundVolume), fed with under-bark diameters from the double-bark functions F_.5.

  • Thinning — low thinning (L) develops phi (Kap 12/16, strength u' = phi_before / phi_after); through thinning (G) removes a uniform fraction (psi' = (1 - G/100) ** (interval / 5)); high thinning (H) holds phi and draws sigma_n in from the coarse end (Kap 16.7, simplified per M26). Stem numbers follow Kap 17-18.

Validation. Reproducing the published production tables (Del XIV):

Variant / regime

Agreement with the published P-tables

Pine, North (F1)

< 0.5 % (validated against P.4/5/9/13)

Pine, South (F3)

< 0.5 % (validated against P.58)

Spruce, South (F8)

< 0.5 % (validated against P.83)

Spruce, North (M31)

~ 2-3 % (P.70/71/72; a provisional reconstruction — Petterson’s own Gran-N tables are a rough estimate built from increment cores, M31)

High thinning (H)

~ 1 % (P.21/22/23; provisional M26 “överslag”)

The starting-state, diameter, height and structure-factor engines are verified independently against the book’s worked examples (M27/M28 diameter table; the 7.6 height example; the M7 structure factors).

class pyforestry.sweden.systems.petterson_1955.Petterson1955Model(init: PettersonStandInit | None = None, program: PettersonThinningProgram | None = None)[source]#

Bases: GrowthModel

Simulation adapter for the Petterson (1955) yield-table model.

build_context(stand: Stand, *, init: PettersonStandInit | None = None, program: PettersonThinningProgram | None = None, **kwargs: Any) → SimulationContext[source]#

Build a context whose whole yield table is already computed.

The table is a closed-form product of the starting state and the thinning programme, so it is built once here and stepped through afterwards; update_step() only advances which row the context stands on.

Parameters:
  • stand – The stand. Read for its petterson_1955_init and petterson_1955_program attributes when the arguments and the model’s own defaults leave them unresolved.

  • init – The starting state, taking precedence over both.

  • program – The thinning regime, likewise.

  • **kwargs – Passed to GrowthModel.build_context().

Raises:

ValueError – If no starting state can be resolved from any of the three places it may come from.

property component_id: str#

The catalog key for this model.

requirements() → Requirements[source]#

Aggregate: the model carries its own diameter distribution.

A stand is described here by a truncated normal in twelve relative classes, derived from the starting state rather than read off a tree list, so a caller’s tree list would be discarded.

property source: SourceReference#

The monograph these yield tables are reconstructed from.

update_step(ctx: SimulationContext, dt: float) → None[source]#

Step to the next thinning occasion in the pre-computed table.

dt is not read: the occasions are the table’s own, spaced by the programme’s interval, and a caller asking for some other period would get a row that does not correspond to it. A run that reaches the end of the table holds on its last row rather than raising.

class pyforestry.sweden.systems.petterson_1955.Petterson1955Stand(init: PettersonStandInit, program: PettersonThinningProgram | None = None)[source]#

Bases: object

Stateful yield-table simulator for the Petterson (1955) model.

property done: bool#

Whether the table has been built. run() is idempotent.

property rows: List[PettersonYieldRow]#

The yield table built so far – empty until run().

run() → Petterson1955Stand[source]#

Build the whole yield table.

class pyforestry.sweden.systems.petterson_1955.PettersonSimulationResult(variant: str, h100: float, program: PettersonThinningProgram, rows: List[PettersonYieldRow])[source]#

Bases: object

Output of a Petterson (1955) yield-table simulation.

class pyforestry.sweden.systems.petterson_1955.PettersonStandInit(species: Literal['pine', 'spruce'], region: Literal['north', 'south'], h100: float, planted: bool = False, start_total_age: float | None = None, ms1: float | None = None, phi1: float | None = None, stems: float | None = None, max_total_age: float | None = None)[source]#

Bases: object

Initial stand / site specification for the Petterson (1955) model.

species is "pine" or "spruce"; region is "north" or "south". Starting-state fields left as None fall back to the register conventions of the chosen variant. start_total_age defaults to the age at which the top-height trajectory reaches 8 m (the utgångsläge).

max_total_age: float | None = None#
ms1: float | None = None#
phi1: float | None = None#
planted: bool = False#
start_total_age: float | None = None#
stems: float | None = None#
class pyforestry.sweden.systems.petterson_1955.PettersonThinningProgram(low: float = 5.0, high: float = 0.0, through: float = 10.0, interval: float = 10.0)[source]#

Bases: object

Thinning program: five-year basal-area outtake percentages + interval.

low develops the truncated distribution (låggallringsmoment L), through removes a uniform fraction (genomgallringsmoment G), and high develops the distribution from the coarse end (höggallringsmoment H). low and high are mutually exclusive within a program (as in the register). All three are five-year basal-area outtake percentages. interval is in years and must be a multiple of five.

High thinning follows the simplified “överslag” method of appendix M26 (used for the book’s own high-thin tables P.21-24): phi is held constant while sigma_n is drawn in from the right, and the top height is referred to LL (the position the upper limit would have held had the coarsest trees not been removed). It is therefore a provisional reconstruction.

high: float = 0.0#
interval: float = 10.0#
low: float = 5.0#
through: float = 10.0#
class pyforestry.sweden.systems.petterson_1955.PettersonVariant(key: str, species: str, region: str, f1_a: float, f1_b: float, f2_a: float, f2_b: float, f3_a: float, f3_b2: float, f3_b3: float, f3_seb_off: float, f3_bS: float, f3_bM: float, f3_e_mode: str, f3_bE1: float, f3_bE2: float, f4_a: float, f4_b: float, height_n: int, f5_a: float, f5_b: float, t_a: float, t_b: float, default_ms1: float, default_phi1: float, default_stems: float, default_through: float, default_interval: float, special_m31: bool = False)[source]#

Bases: object

Coefficient set for one species / region group (functions F1/F3/F5/F8).

special_m31: bool = False#
class pyforestry.sweden.systems.petterson_1955.PettersonYieldRow(total_age: int, dominant_height_m: float, qmd_after_cm: float, mean_height_after_m: float, stems_before: float, stems_after: float, ba_before_m2: float, ba_after_m2: float, volume_before_m3sk: float, volume_removed_m3sk: float, volume_after_m3sk: float, cai_m3sk: float | None, mai_m3sk: float, thin_pct_stems: float, thin_pct_ba: float, thin_pct_volume: float)[source]#

Bases: object

One age row of a Petterson yield table (values after thinning where noted).

pyforestry.sweden.systems.petterson_1955.petterson_simulate(init: PettersonStandInit, program: PettersonThinningProgram | None = None) → PettersonSimulationResult[source]#

Run the Petterson (1955) simulation and return the yield table.

pyforestry.sweden.systems.petterson_1955.petterson_structure_factors(phi: float) → Tuple[float, float, float][source]#

Return (M', sigma', F) of the left-truncated normal (Kap 9.3, M7).

M' is the mean measured from the lower cut alpha in sigma_n units, sigma' = sigma_s / sigma_n the relative standard deviation and F the retained-stem fraction F(phi). For phi >= 6 the distribution has become a full normal whose lower bound has relocated to the right (Kap 12.4-12.5): the shape saturates while M' = phi - 3.

pyforestry.sweden.systems.petterson_1955.petterson_top_height(v: PettersonVariant, total_age: float, h100: float, t_over: float = 1.0) → float[source]#

Dominant (top) height h_3sigma at a total age (Kap 7.5, n=3).

t_over is t'/t (1.0 natural, 0.7 planted).

Module contents#

Whole published growth-and-yield systems for Sweden.

Each module here is one publication reproduced end to end: its own coefficients, its own state, its own stepping rules. Eriksson (1976), Persson (1992), Petterson (1955), Ekö (1985) and Elfving & Hägglund (1975) are not assemblies of interchangeable equations — the parts were fitted together and only agree with the printed yield tables when used together. Keeping each one whole is what makes it checkable against its source.

That is the difference from pyforestry.sweden.adapters, and it runs in one direction only: a system may carry coefficients and ship the GrowthModel that drives it, because a self-contained system owns its own interface. An adapter may not carry coefficients at all.

Individual published equations that stand on their own — a volume function, a site-index curve, a bark thickness model — belong in the domain packages (sweden/volume, sweden/siteindex, sweden/bark, …) instead.

pyforestry.sweden.systems.available_systems() → dict[str, type][source]#

Return each published system’s own runner, by name.

These project a stand end to end, exactly as get_pipeline()’s composites do – which available_pipelines() alone does not say, since it lists only the two compositions pyforestry assembled itself. Asking what this package can run means asking both.

The classes are returned rather than built, because there is no shared constructor to build them with and inventing one would misrepresent them: each takes the starting state and thinning programme its own publication defines. Read the class to see what it wants.

Returns:

Name to runner class. The same names their GrowthModel adapters use in available_models(), so one system is one name whichever way it is reached – the adapter steps a stand you supply, the runner builds and projects its own.