Stand metrics and site enums#
Notebook Objectives#
Walk through stand/site enum usage and how they feed site-index-ready stand setup.
Provide runnable, copy-safe snippets that work in the docs build environment.
Prerequisites#
Python environment with
pyforestryinstalled from this repository.Execute cells in order; random components should use fixed seeds where shown.
Sources#
Swedish site primitives and enums in
pyforestry.sweden.site.
This notebook shows how to work with circular plots, site enums, and site index models.
[1]:
from pyforestry.base.helpers import CircularPlot, Stand, Tree, parse_tree_species
plot1 = CircularPlot(
id=1,
radius_m=5.0,
trees=[
Tree(species=parse_tree_species("picea abies"), diameter_cm=20),
Tree(species=parse_tree_species("pinus sylvestris"), diameter_cm=25),
],
)
plot2 = CircularPlot(
id=2,
radius_m=5.0,
trees=[
Tree(species=parse_tree_species("picea abies"), diameter_cm=30),
],
)
stand = Stand(plots=[plot1, plot2])
stand.BasalArea.TOTAL.value, stand.Stems.TOTAL.value
[1]:
(9.625, 190.9859317102744)
Site enums help provide structured parameters.
[2]:
from pyforestry.base.helpers import enum_code
from pyforestry.sweden.site.enums import Sweden
enum_code(Sweden.SoilMoistureEnum.DRY), enum_code(Sweden.County.UPPSALA)
[2]:
(1, 16)
[3]:
from pyforestry.sweden.siteindex.sis.hagglund_lundmark_1977 import Hagglund_Lundmark_1977_SIS
sis = Hagglund_Lundmark_1977_SIS(
species="Picea abies",
latitude=60,
altitude=100,
soil_moisture=Sweden.SoilMoistureEnum.MESIC,
ground_layer=Sweden.BottomLayer.FRESH_MOSS,
vegetation=Sweden.FieldLayer.BILBERRY,
soil_texture=Sweden.SoilTextureTill.SANDY,
climate_code=Sweden.ClimateZone.K1,
lateral_water=Sweden.SoilWater.SELDOM_NEVER,
soil_depth=Sweden.SoilDepth.DEEP,
incline_percent=5,
aspect=0,
nfi_adjustments=True,
dlan=Sweden.County.UPPSALA,
peat=False,
gotland=False,
coast=False,
limes_norrlandicus=False,
)
float(sis)
[3]:
26.672815668837686
Generate Site Categories From Requested SIS#
Use predict_site_categories_county_tree to get all categorical site inputs from species, requested sis_hagglund_1979, and county, then compare requested vs achieved SIS.
[4]:
import pandas as pd
from pyforestry.sweden.siteindex.sis.generated_site_category_trees import (
predict_site_categories_county_tree,
)
requested_sis = 24.0
species = "Picea abies"
county = Sweden.County.UPPSALA
predicted_categories = predict_site_categories_county_tree(
sis_hagglund_1979=requested_sis,
species=species,
Direktlan=county,
)
achieved_sis = Hagglund_Lundmark_1977_SIS(
species=species,
latitude=60,
altitude=100,
soil_moisture=predicted_categories["soil_moisture"],
ground_layer=predicted_categories["bottom_layer"],
vegetation=predicted_categories["field_layer"],
soil_texture=predicted_categories["soil_texture"],
climate_code=Sweden.ClimateZone.K1,
lateral_water=predicted_categories["soil_water"],
soil_depth=predicted_categories["soil_depth"],
incline_percent=5,
aspect=0,
nfi_adjustments=True,
dlan=county,
ditched=bool(predicted_categories["ditched"]),
peat=False,
gotland=False,
coast=False,
limes_norrlandicus=False,
)
summary = pd.DataFrame(
[
{
"requested_sis": requested_sis,
"achieved_sis": float(achieved_sis),
"sis_abs_error": abs(float(achieved_sis) - requested_sis),
"sis_rel_error_pct": 100.0 * abs(float(achieved_sis) - requested_sis) / requested_sis,
}
]
)
display(summary)
predicted_categories
| requested_sis | achieved_sis | sis_abs_error | sis_rel_error_pct | |
|---|---|---|---|---|
| 0 | 24.0 | 27.239957 | 3.239957 | 13.499821 |
[4]:
{'field_layer': <SwedenFieldLayer.BROADLEAVED_GRASS: Vegetation(code=8, swedish_name='Bredbl. gräs', english_name='Broadleaved grass', index=2.5)>,
'bottom_layer': <SwedenBottomLayer.FRESH_MOSS: BottomLayerType(code=6, english_name='Fresh moss type', swedish_name='Friskmosstyp')>,
'soil_texture': <SwedenSoilTextureTill.CLAY: SoilTextureCategory(code=8, swedish_name='Lerig morän', english_name='Clayey till', short_name='Clay')>,
'soil_moisture': <SwedenSoilMoisture.MESIC: SoilMoistureData(code=2, swedish_description='frisk', english_description='Mesic (subsoil water depth = 1-2 m)')>,
'soil_depth': <SwedenSoilDepth.DEEP: SoilDepthCat(code=1, swedish_description='Mäktigt >70 cm. Inga synliga hällar', english_description='Deep >70cm. No visible stone outcrops.')>,
'soil_water': <SwedenSoilWater.SELDOM_NEVER: SoilWaterCat(code=1, swedish_description='saknas', english_description='Seldom/never')>,
'ditched': False}
Geographic utilities and climate calculations.
[5]:
from pyforestry.sweden.geo import Moren_Perttu_radiation_1994, RetrieveGeoCode
RetrieveGeoCode.getDistanceToCoast(14.784528, 56.892405)
RetrieveGeoCode.getClimateCode(14.784528, 56.892405)
[6]:
calc = Moren_Perttu_radiation_1994(latitude=60, altitude=100, july_avg_temp=17, jan_avg_temp=-8)
(
calc.calculate_temperature_sum_1000m(threshold_temperature=5),
calc.get_corrected_temperature_sum(threshold_temperature=5),
)
[6]:
(1216.3800000000003, 1266.3800000000003)