hestia-earth-models 0.70.0__py3-none-any.whl → 0.70.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hestia_earth/models/aware/scarcityWeightedWaterUse.py +8 -16
- hestia_earth/models/cml2001Baseline/resourceUseMineralsAndMetalsDuringCycle.py +2 -1
- hestia_earth/models/config/Cycle.json +98 -50
- hestia_earth/models/config/ImpactAssessment.json +12 -4
- hestia_earth/models/config/Site.json +40 -21
- hestia_earth/models/cycle/transformation.py +1 -1
- hestia_earth/models/cycle/utils.py +0 -6
- hestia_earth/models/data/ecoinventV3/__init__.py +15 -13
- hestia_earth/models/ecoalimV9/__init__.py +13 -0
- hestia_earth/models/ecoalimV9/cycle.py +128 -0
- hestia_earth/models/ecoalimV9/impact_assessment.py +125 -0
- hestia_earth/models/ecoalimV9/utils.py +31 -0
- hestia_earth/models/ecoinventV3/__init__.py +6 -14
- hestia_earth/models/ecoinventV3/utils.py +1 -29
- hestia_earth/models/ecoinventV3AndEmberClimate/__init__.py +8 -2
- hestia_earth/models/emissionNotRelevant/__init__.py +33 -8
- hestia_earth/models/{cycle → hestia}/aboveGroundCropResidue.py +4 -3
- hestia_earth/models/{cycle → hestia}/aboveGroundCropResidueTotal.py +1 -1
- hestia_earth/models/{site → hestia}/brackishWater.py +1 -1
- hestia_earth/models/{site → hestia}/cationExchangeCapacityPerKgSoil.py +1 -1
- hestia_earth/models/{cycle → hestia}/coldCarcassWeightPerHead.py +1 -1
- hestia_earth/models/{cycle → hestia}/coldDressedCarcassWeightPerHead.py +1 -1
- hestia_earth/models/{cycle → hestia}/concentrateFeed.py +1 -1
- hestia_earth/models/{cycle → hestia}/cropResidueManagement.py +1 -1
- hestia_earth/models/{cycle → hestia}/croppingIntensity.py +1 -1
- hestia_earth/models/{cycle → hestia}/energyContentLowerHeatingValue.py +1 -1
- hestia_earth/models/{cycle → hestia}/excretaKgMass.py +8 -3
- hestia_earth/models/{cycle → hestia}/excretaKgN.py +1 -1
- hestia_earth/models/{cycle → hestia}/excretaKgVs.py +1 -1
- hestia_earth/models/{cycle → hestia}/feedConversionRatio/__init__.py +1 -1
- hestia_earth/models/{site → hestia}/flowingWater.py +1 -1
- hestia_earth/models/{site → hestia}/freshWater.py +1 -1
- hestia_earth/models/{cycle → hestia}/inorganicFertiliser.py +1 -1
- hestia_earth/models/{cycle → hestia}/irrigatedTypeUnspecified.py +14 -19
- hestia_earth/models/hestia/landCover.py +30 -22
- hestia_earth/models/{cycle → hestia}/liveAnimal.py +1 -1
- hestia_earth/models/{cycle → hestia}/longFallowRatio.py +1 -1
- hestia_earth/models/{site → hestia}/management.py +4 -6
- hestia_earth/models/{cycle → hestia}/materialAndSubstrate.py +1 -1
- hestia_earth/models/{cycle → hestia}/milkYield.py +1 -1
- hestia_earth/models/{site → hestia}/netPrimaryProduction.py +1 -1
- hestia_earth/models/{site → hestia}/organicCarbonPerHa.py +1 -1
- hestia_earth/models/hestia/pToSurfaceWaterAquacultureSystems.py +148 -0
- hestia_earth/models/{cycle → hestia}/pastureGrass.py +1 -1
- hestia_earth/models/{cycle → hestia}/pastureSystem.py +1 -1
- hestia_earth/models/{site → hestia}/potentialEvapotranspirationAnnual.py +3 -3
- hestia_earth/models/{site → hestia}/potentialEvapotranspirationMonthly.py +3 -3
- hestia_earth/models/{site → hestia}/precipitationAnnual.py +3 -3
- hestia_earth/models/{site → hestia}/precipitationMonthly.py +3 -3
- hestia_earth/models/{site → hestia}/rainfallAnnual.py +3 -3
- hestia_earth/models/{site → hestia}/rainfallMonthly.py +3 -3
- hestia_earth/models/{cycle → hestia}/readyToCookWeightPerHead.py +1 -1
- hestia_earth/models/{cycle → hestia}/residueBurnt.py +1 -1
- hestia_earth/models/{cycle → hestia}/residueIncorporated.py +1 -1
- hestia_earth/models/{cycle → hestia}/residueLeftOnField.py +1 -1
- hestia_earth/models/hestia/residueRemoved.py +65 -13
- hestia_earth/models/{site → hestia}/salineWater.py +1 -1
- hestia_earth/models/{site → hestia}/soilMeasurement.py +1 -1
- hestia_earth/models/{cycle → hestia}/stockingDensityAnimalHousingAverage.py +1 -1
- hestia_earth/models/{site → hestia}/temperatureAnnual.py +3 -3
- hestia_earth/models/{site → hestia}/temperatureMonthly.py +3 -3
- hestia_earth/models/{site → hestia}/totalNitrogenPerKgSoil.py +1 -1
- hestia_earth/models/{cycle → hestia}/unknownPreSeasonWaterRegime.py +1 -1
- hestia_earth/models/hestia/utils.py +93 -0
- hestia_earth/models/{site → hestia}/waterDepth.py +1 -1
- hestia_earth/models/hestia/waterSalinity.py +78 -0
- hestia_earth/models/ipcc2019/aboveGroundBiomass.py +1 -1
- hestia_earth/models/ipcc2019/belowGroundBiomass.py +1 -1
- hestia_earth/models/ipcc2019/biomass_utils.py +2 -4
- hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +166 -79
- hestia_earth/models/ipcc2019/ch4ToAirOrganicSoilCultivation.py +270 -0
- hestia_earth/models/ipcc2019/co2ToAirAboveGroundBiomassStockChange.py +0 -3
- hestia_earth/models/ipcc2019/co2ToAirBelowGroundBiomassStockChange.py +0 -3
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +88 -63
- hestia_earth/models/ipcc2019/co2ToAirLimeHydrolysis.py +7 -5
- hestia_earth/models/ipcc2019/co2ToAirOrganicSoilCultivation.py +215 -0
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChange.py +0 -3
- hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +16 -9
- hestia_earth/models/ipcc2019/n2OToAirOrganicSoilCultivationDirect.py +161 -0
- hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +35 -47
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1.py +86 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2.py +127 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa_utils.py +7 -5
- hestia_earth/models/ipcc2019/organicSoilCultivation_utils.py +159 -0
- hestia_earth/models/mocking/search-results.json +1113 -1113
- hestia_earth/models/pooreNemecek2018/utils.py +8 -2
- hestia_earth/models/schmidt2007/ch4ToAirWasteTreatment.py +1 -4
- hestia_earth/models/schmidt2007/h2SToAirWasteTreatment.py +1 -4
- hestia_earth/models/schmidt2007/n2OToAirWasteTreatmentDirect.py +1 -4
- hestia_earth/models/schmidt2007/nh3ToAirWasteTreatment.py +1 -4
- hestia_earth/models/site/grouped_measurement.py +132 -0
- hestia_earth/models/utils/__init__.py +4 -3
- hestia_earth/models/utils/background_emissions.py +52 -0
- hestia_earth/models/utils/blank_node.py +47 -14
- hestia_earth/models/utils/constant.py +26 -20
- hestia_earth/models/utils/impact_assessment.py +26 -17
- hestia_earth/models/utils/lookup.py +48 -39
- hestia_earth/models/utils/measurement.py +3 -3
- hestia_earth/models/utils/product.py +39 -1
- hestia_earth/models/utils/property.py +14 -6
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.70.0.dist-info → hestia_earth_models-0.70.2.dist-info}/METADATA +2 -2
- {hestia_earth_models-0.70.0.dist-info → hestia_earth_models-0.70.2.dist-info}/RECORD +187 -171
- tests/models/aware/test_scarcityWeightedWaterUse.py +1 -12
- tests/models/ecoalimV9/__init__.py +0 -0
- tests/models/ecoalimV9/test_cycle.py +21 -0
- tests/models/ecoalimV9/test_impact_assessment.py +24 -0
- tests/models/environmentalFootprintV3_1/test_scarcityWeightedWaterUse.py +4 -2
- tests/models/{cycle → hestia}/test_aboveGroundCropResidue.py +1 -1
- tests/models/{cycle → hestia}/test_aboveGroundCropResidueTotal.py +1 -1
- tests/models/{site → hestia}/test_brackishWater.py +1 -1
- tests/models/{site → hestia}/test_cationExchangeCapacityPerKgSoil.py +1 -1
- tests/models/{cycle → hestia}/test_coldCarcassWeightPerHead.py +1 -1
- tests/models/{cycle → hestia}/test_coldDressedCarcassWeightPerHead.py +1 -1
- tests/models/{cycle → hestia}/test_concentrateFeed.py +1 -1
- tests/models/{cycle → hestia}/test_cropResidueManagement.py +1 -1
- tests/models/{cycle → hestia}/test_croppingIntensity.py +1 -1
- tests/models/{cycle → hestia}/test_energyContentLowerHeatingValue.py +5 -3
- tests/models/{cycle → hestia}/test_excretaKgMass.py +1 -1
- tests/models/{cycle → hestia}/test_excretaKgN.py +1 -1
- tests/models/{cycle → hestia}/test_excretaKgVs.py +1 -1
- tests/models/{cycle → hestia}/test_feedConversionRatio.py +3 -4
- tests/models/{site → hestia}/test_flowingWater.py +1 -1
- tests/models/{site → hestia}/test_freshWater.py +1 -1
- tests/models/{cycle → hestia}/test_inorganicFertiliser.py +1 -1
- tests/models/{cycle → hestia}/test_irrigatedTypeUnspecified.py +2 -5
- tests/models/hestia/test_landCover.py +4 -34
- tests/models/{cycle → hestia}/test_liveAnimal.py +1 -1
- tests/models/{cycle → hestia}/test_longFallowRatio.py +1 -1
- tests/models/{site → hestia}/test_management.py +1 -1
- tests/models/{cycle → hestia}/test_materialsAndSubstrate.py +1 -1
- tests/models/{cycle → hestia}/test_milkYield.py +1 -1
- tests/models/{site → hestia}/test_netPrimaryProduction.py +1 -1
- tests/models/{site → hestia}/test_organicCarbonPerHa.py +1 -1
- tests/models/{site → hestia}/test_organicCarbonPerKgSoil.py +1 -1
- tests/models/{site → hestia}/test_organicCarbonPerM3Soil.py +1 -1
- tests/models/{site → hestia}/test_organicMatterPerKgSoil.py +1 -1
- tests/models/{site → hestia}/test_organicMatterPerM3Soil.py +1 -1
- tests/models/hestia/test_pToSurfaceWaterAquacultureSystems.py +56 -0
- tests/models/{cycle → hestia}/test_pastureGrass.py +1 -1
- tests/models/{cycle → hestia}/test_pastureSystem.py +1 -1
- tests/models/{site → hestia}/test_potentialEvapotranspirationAnnual.py +1 -1
- tests/models/{site → hestia}/test_potentialEvapotranspirationMonthly.py +1 -1
- tests/models/{site → hestia}/test_precipitationAnnual.py +1 -1
- tests/models/{site → hestia}/test_precipitationMonthly.py +1 -1
- tests/models/{site → hestia}/test_rainfallAnnual.py +1 -1
- tests/models/{site → hestia}/test_rainfallMonthly.py +1 -1
- tests/models/{cycle → hestia}/test_readyToCookWeightPerHead.py +1 -1
- tests/models/{cycle → hestia}/test_residueBurnt.py +1 -1
- tests/models/{cycle → hestia}/test_residueIncorporated.py +1 -1
- tests/models/{cycle → hestia}/test_residueLeftOnField.py +1 -1
- tests/models/hestia/test_residueRemoved.py +15 -3
- tests/models/{site → hestia}/test_salineWater.py +1 -1
- tests/models/{site → hestia}/test_soilMeasurement.py +13 -21
- tests/models/{cycle → hestia}/test_stockingDensityAnimalHousingAverage.py +1 -1
- tests/models/{site → hestia}/test_temperatureAnnual.py +1 -1
- tests/models/{site → hestia}/test_temperatureMonthly.py +1 -1
- tests/models/{site → hestia}/test_totalNitrogenPerKgSoil.py +1 -1
- tests/models/{cycle → hestia}/test_unknownPreSeasonWaterRegime.py +1 -1
- tests/models/{site → hestia}/test_waterDepth.py +1 -1
- tests/models/hestia/test_waterSalinity.py +26 -0
- tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +2 -5
- tests/models/ipcc2019/test_ch4ToAirFloodedRice.py +10 -42
- tests/models/ipcc2019/test_ch4ToAirOrganicSoilCultivation.py +61 -0
- tests/models/ipcc2019/test_co2ToAirAboveGroundBiomassStockChange.py +11 -9
- tests/models/ipcc2019/test_co2ToAirBelowGroundBiomassStockChange.py +10 -8
- tests/models/ipcc2019/test_co2ToAirLimeHydrolysis.py +1 -1
- tests/models/ipcc2019/test_co2ToAirOrganicSoilCultivation.py +62 -0
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChange.py +11 -8
- tests/models/ipcc2019/test_n2OToAirOrganicSoilCultivationDirect.py +61 -0
- tests/models/ipcc2019/test_nonCo2EmissionsToAirNaturalVegetationBurning.py +3 -2
- tests/models/site/test_grouped_measurement.py +20 -0
- tests/models/test_ecoinventV3AndEmberClimate.py +2 -2
- tests/models/test_emissionNotRelevant.py +0 -8
- tests/models/utils/test_measurement.py +1 -1
- hestia_earth/models/cycle/residueRemoved.py +0 -54
- hestia_earth/models/hestia/nh3ToSurfaceWaterAquacultureSystems.py +0 -64
- hestia_earth/models/site/utils.py +0 -93
- tests/models/cycle/test_residueRemoved.py +0 -37
- tests/models/hestia/test_nh3ToSurfaceWaterAquacultureSystems.py +0 -51
- /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioCarbon.py +0 -0
- /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioDryMatter.py +0 -0
- /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioEnergy.py +0 -0
- /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioFedWeight.py +0 -0
- /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioNitrogen.py +0 -0
- /hestia_earth/models/{site → hestia}/organicCarbonPerKgSoil.py +0 -0
- /hestia_earth/models/{site → hestia}/organicCarbonPerM3Soil.py +0 -0
- /hestia_earth/models/{site → hestia}/organicMatterPerKgSoil.py +0 -0
- /hestia_earth/models/{site → hestia}/organicMatterPerM3Soil.py +0 -0
- {hestia_earth_models-0.70.0.dist-info → hestia_earth_models-0.70.2.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.70.0.dist-info → hestia_earth_models-0.70.2.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.70.0.dist-info → hestia_earth_models-0.70.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition
|
2
|
+
|
3
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
4
|
+
from hestia_earth.models.utils.cycle import land_occupation_per_ha
|
5
|
+
from hestia_earth.models.utils.ecoClimateZone import EcoClimateZone, get_eco_climate_zone_value
|
6
|
+
from hestia_earth.models.utils.emission import _new_emission
|
7
|
+
from hestia_earth.models.utils.measurement import most_relevant_measurement_value
|
8
|
+
from hestia_earth.models.utils.site import valid_site_type
|
9
|
+
|
10
|
+
from .organicSoilCultivation_utils import (
|
11
|
+
assign_organic_soil_category, calc_emission, get_emission_factor, OrganicSoilCategory, remap_categories,
|
12
|
+
valid_eco_climate_zone
|
13
|
+
)
|
14
|
+
from . import MODEL
|
15
|
+
|
16
|
+
|
17
|
+
REQUIREMENTS = {
|
18
|
+
"Cycle": {
|
19
|
+
"or": [
|
20
|
+
{
|
21
|
+
"cycleDuration": "",
|
22
|
+
"practices": [{"@type": "Practice", "value": "", "term.@id": "longFallowRatio"}]
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"@doc": "for plantations, additional properties are required",
|
26
|
+
"practices": [
|
27
|
+
{"@type": "Practice", "value": "", "term.@id": "nurseryDensity"},
|
28
|
+
{"@type": "Practice", "value": "", "term.@id": "nurseryDuration"},
|
29
|
+
{"@type": "Practice", "value": "", "term.@id": "plantationProductiveLifespan"},
|
30
|
+
{"@type": "Practice", "value": "", "term.@id": "plantationDensity"},
|
31
|
+
{"@type": "Practice", "value": "", "term.@id": "plantationLifespan"},
|
32
|
+
{"@type": "Practice", "value": "", "term.@id": "rotationDuration"}
|
33
|
+
]
|
34
|
+
}
|
35
|
+
],
|
36
|
+
"site": {
|
37
|
+
"@type": "Site",
|
38
|
+
"measurements": [
|
39
|
+
{"@type": "Measurement", "value": "", "term.@id": "histosol"},
|
40
|
+
{"@type": "Measurement", "value": "", "term.@id": "ecoClimateZone"}
|
41
|
+
]
|
42
|
+
},
|
43
|
+
"optional": {
|
44
|
+
"cycleDuration": ""
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
LOOKUPS = {
|
49
|
+
"crop": [
|
50
|
+
"isPlantation",
|
51
|
+
"IPCC_2013_ORGANIC_SOIL_CULTIVATION_CATEGORY"
|
52
|
+
],
|
53
|
+
"forage": [
|
54
|
+
"isPlantation",
|
55
|
+
"IPCC_2013_ORGANIC_SOIL_CULTIVATION_CATEGORY"
|
56
|
+
],
|
57
|
+
"ecoClimateZone": [
|
58
|
+
"IPCC_2013_ORGANIC_SOILS_TONNES_N2O-N_HECTARE_ANNUAL_CROPS",
|
59
|
+
"IPCC_2013_ORGANIC_SOILS_TONNES_N2O-N_HECTARE_PERENNIAL_CROPS",
|
60
|
+
"IPCC_2013_ORGANIC_SOILS_TONNES_N2O-N_HECTARE_ACACIA",
|
61
|
+
"IPCC_2013_ORGANIC_SOILS_TONNES_N2O-N_HECTARE_OIL_PALM",
|
62
|
+
"IPCC_2013_ORGANIC_SOILS_TONNES_N2O-N_HECTARE_SAGO_PALM",
|
63
|
+
"IPCC_2013_ORGANIC_SOILS_TONNES_N2O-N_HECTARE_PADDY_RICE_CULTIVATION",
|
64
|
+
"IPCC_2013_ORGANIC_SOILS_TONNES_N2O-N_HECTARE_GRASSLAND",
|
65
|
+
"IPCC_2013_ORGANIC_SOILS_TONNES_N2O-N_HECTARE_OTHER"
|
66
|
+
]
|
67
|
+
}
|
68
|
+
RETURNS = {
|
69
|
+
"Emission": [{
|
70
|
+
"value": "",
|
71
|
+
"sd": "",
|
72
|
+
"statsDefinition": "modelled",
|
73
|
+
"methodTier": "tier 1"
|
74
|
+
}]
|
75
|
+
}
|
76
|
+
TERM_ID = 'n2OToAirOrganicSoilCultivationDirect'
|
77
|
+
TIER = EmissionMethodTier.TIER_1.value
|
78
|
+
|
79
|
+
_STATS_DEFINITION = EmissionStatsDefinition.MODELLED.value
|
80
|
+
|
81
|
+
_CATEGORY_REMAPPER = {
|
82
|
+
OrganicSoilCategory.ACACIA: OrganicSoilCategory.PERENNIAL_CROPS
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
def _emission(value: float, sd: float):
|
87
|
+
emission = _new_emission(TERM_ID, MODEL)
|
88
|
+
emission['value'] = [value]
|
89
|
+
emission['sd'] = [sd]
|
90
|
+
emission['statsDefinition'] = _STATS_DEFINITION
|
91
|
+
emission['methodTier'] = TIER
|
92
|
+
return emission
|
93
|
+
|
94
|
+
|
95
|
+
def sample_emission_factor(
|
96
|
+
eco_climate_zone: EcoClimateZone,
|
97
|
+
organic_soil_category: OrganicSoilCategory,
|
98
|
+
) -> tuple[float, float]:
|
99
|
+
category = remap_categories(organic_soil_category, _CATEGORY_REMAPPER) # fewer categories than CO2 model
|
100
|
+
factor_data = get_emission_factor(TERM_ID, eco_climate_zone, category)
|
101
|
+
mean = factor_data.get("value", 0)
|
102
|
+
sd = factor_data.get("sd", 0)
|
103
|
+
return mean, sd
|
104
|
+
|
105
|
+
|
106
|
+
def _should_run(cycle: dict):
|
107
|
+
end_date = cycle.get('endDate')
|
108
|
+
site = cycle.get('site', {})
|
109
|
+
measurements = site.get('measurements', [])
|
110
|
+
|
111
|
+
def _get_measurement_content(term_id: str):
|
112
|
+
return most_relevant_measurement_value(measurements, term_id, end_date)
|
113
|
+
|
114
|
+
histosol = _get_measurement_content('histosol')
|
115
|
+
eco_climate_zone = get_eco_climate_zone_value(cycle, as_enum=True)
|
116
|
+
organic_soil_category = assign_organic_soil_category(cycle, log_id=TERM_ID)
|
117
|
+
|
118
|
+
emission_factor_mean, emission_factor_sd = (
|
119
|
+
sample_emission_factor(eco_climate_zone, organic_soil_category)
|
120
|
+
if eco_climate_zone
|
121
|
+
else (None, None)
|
122
|
+
)
|
123
|
+
|
124
|
+
land_occupation = land_occupation_per_ha(MODEL, TERM_ID, cycle)
|
125
|
+
|
126
|
+
logRequirements(
|
127
|
+
cycle, model=MODEL, term=TERM_ID,
|
128
|
+
eco_climate_zone=eco_climate_zone,
|
129
|
+
organic_soil_category=organic_soil_category,
|
130
|
+
emission_factor=f"{emission_factor_mean} ± {emission_factor_sd}",
|
131
|
+
land_occupation=land_occupation,
|
132
|
+
histosol=histosol
|
133
|
+
)
|
134
|
+
|
135
|
+
should_run = all([
|
136
|
+
valid_site_type(site),
|
137
|
+
valid_eco_climate_zone(eco_climate_zone),
|
138
|
+
all(
|
139
|
+
var is not None for var in [
|
140
|
+
emission_factor_mean,
|
141
|
+
emission_factor_sd,
|
142
|
+
land_occupation,
|
143
|
+
histosol
|
144
|
+
]
|
145
|
+
)
|
146
|
+
])
|
147
|
+
|
148
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
149
|
+
|
150
|
+
return should_run, emission_factor_mean, emission_factor_sd, histosol, land_occupation
|
151
|
+
|
152
|
+
|
153
|
+
def _run(emission_factor_mean: float, emission_factor_sd: float, histosol: float, land_occupation: float):
|
154
|
+
value = calc_emission(TERM_ID, emission_factor_mean, histosol, land_occupation)
|
155
|
+
sd = calc_emission(TERM_ID, emission_factor_sd, histosol, land_occupation)
|
156
|
+
return [_emission(value, sd)]
|
157
|
+
|
158
|
+
|
159
|
+
def run(cycle: dict):
|
160
|
+
should_run, emission_factor_mean, emission_factor_sd, histosol, land_occupation = _should_run(cycle)
|
161
|
+
return _run(emission_factor_mean, emission_factor_sd, histosol, land_occupation) if should_run else []
|
@@ -156,8 +156,6 @@ _Inventory = dict[int, _InventoryYear]
|
|
156
156
|
{year (int): data (_InventoryYear)}
|
157
157
|
"""
|
158
158
|
|
159
|
-
_EmissionInventory = dict[_EmissionTermId, npt.NDArray]
|
160
|
-
|
161
159
|
|
162
160
|
_BIOMASS_CATEGORY_TO_FUEL_CATEGORY = {
|
163
161
|
BiomassCategory.FOREST: {
|
@@ -518,9 +516,9 @@ def _sum_cycle_emissions(term_id: _EmissionTermId, cycle_id: str, inventory: _In
|
|
518
516
|
return reduce(add_cycle_emissions, inventory.keys(), np.array(0))
|
519
517
|
|
520
518
|
|
521
|
-
def
|
519
|
+
def _compile_inventory(
|
522
520
|
cycle: dict, site: dict, land_cover_nodes: list[dict], eco_climate_zone: EcoClimateZone
|
523
|
-
)
|
521
|
+
):
|
524
522
|
"""
|
525
523
|
Compile the run data for the model, collating data from `site.management` and related cycles. An annualised
|
526
524
|
inventory of land cover change and natural vegetation burning events is constructed. Emissions from burning events
|
@@ -539,18 +537,12 @@ def _compile_run_data(
|
|
539
537
|
|
540
538
|
Returns
|
541
539
|
-------
|
542
|
-
|
543
|
-
|
544
|
-
```
|
545
|
-
{
|
546
|
-
emission_term_id (str): value (NDArray),
|
547
|
-
...
|
548
|
-
}
|
549
|
-
```
|
540
|
+
should_run : bool
|
541
|
+
Whether the model should be run.
|
550
542
|
inventory : _Inventory
|
551
|
-
An inventory of model data
|
543
|
+
An inventory of model data.
|
552
544
|
logs : dict
|
553
|
-
Data
|
545
|
+
Data about the inventory compilation to be logged.
|
554
546
|
"""
|
555
547
|
cycle_id = cycle.get("@id")
|
556
548
|
related_cycles_ = related_cycles(site, cycles_mapping={cycle_id: cycle})
|
@@ -586,9 +578,15 @@ def _compile_run_data(
|
|
586
578
|
Returns
|
587
579
|
-------
|
588
580
|
inventory : dict
|
589
|
-
An inventory of model data, updated to include the
|
581
|
+
An inventory of model data, updated to include the input year.
|
590
582
|
"""
|
591
|
-
land_cover_nodes =
|
583
|
+
land_cover_nodes = land_cover_grouped.get(
|
584
|
+
next(
|
585
|
+
(k for k in sorted(land_cover_grouped) if k >= year), # backfill if possible
|
586
|
+
min(land_cover_grouped, key=lambda k: abs(k - year)) # else forward-fill
|
587
|
+
),
|
588
|
+
[]
|
589
|
+
)
|
592
590
|
|
593
591
|
biomass_category_summary = summarise_land_cover_nodes(land_cover_nodes)
|
594
592
|
prev_biomass_category_summary = inventory.get(year-1, {}).get("biomass_category_summary", {})
|
@@ -656,17 +654,17 @@ def _compile_run_data(
|
|
656
654
|
|
657
655
|
inventory = reduce(build_inventory_year, range(min_year, max_year+1), dict())
|
658
656
|
|
659
|
-
|
660
|
-
term_id: value for term_id in EMISSION_TERM_IDS
|
661
|
-
if np.all((value := _sum_cycle_emissions(term_id, cycle_id, inventory)) > 0)
|
662
|
-
}
|
657
|
+
n_land_cover_years = len(land_cover_grouped)
|
663
658
|
|
664
659
|
logs = {
|
660
|
+
"n_land_cover_years": n_land_cover_years,
|
665
661
|
"percent_burned": percent_burned,
|
666
662
|
"seed": seed,
|
667
663
|
}
|
668
664
|
|
669
|
-
|
665
|
+
should_run = bool(inventory and n_land_cover_years > 1)
|
666
|
+
|
667
|
+
return should_run, inventory, logs
|
670
668
|
|
671
669
|
|
672
670
|
def _format_bool(value: Optional[bool]) -> str:
|
@@ -831,23 +829,16 @@ def _format_inventory(term_id: _EmissionTermId, cycle_id: str, inventory: dict)
|
|
831
829
|
) if inventory else "None"
|
832
830
|
|
833
831
|
|
834
|
-
def
|
835
|
-
term_id: _EmissionTermId, cycle: dict, emission_inventory: _EmissionInventory, inventory: dict, logs: dict
|
836
|
-
):
|
832
|
+
def _log_emission_data(should_run: bool, term_id: _EmissionTermId, cycle: dict, inventory: dict, logs: dict):
|
837
833
|
"""
|
838
|
-
|
839
|
-
the model logs and inventory.
|
834
|
+
Format and log the model logs and inventory.
|
840
835
|
"""
|
841
|
-
should_run = term_id in emission_inventory
|
842
|
-
|
843
836
|
formatted_logs = _format_logs(logs)
|
844
837
|
formatted_inventory = _format_inventory(term_id, cycle.get("@id"), inventory)
|
845
838
|
|
846
839
|
logRequirements(cycle, model=MODEL, term=term_id, **formatted_logs, inventory=formatted_inventory)
|
847
840
|
logShouldRun(cycle, MODEL, term_id, should_run)
|
848
841
|
|
849
|
-
return should_run
|
850
|
-
|
851
842
|
|
852
843
|
def _should_run(cycle: dict):
|
853
844
|
"""
|
@@ -861,8 +852,8 @@ def _should_run(cycle: dict):
|
|
861
852
|
|
862
853
|
Returns
|
863
854
|
-------
|
864
|
-
tuple[bool,
|
865
|
-
should_run,
|
855
|
+
tuple[bool, _Inventory]
|
856
|
+
should_run, inventory
|
866
857
|
"""
|
867
858
|
site = _get_site(cycle)
|
868
859
|
|
@@ -873,7 +864,7 @@ def _should_run(cycle: dict):
|
|
873
864
|
|
874
865
|
has_valid_site_type = all([site_type, site_type not in _EXCLUDED_SITE_TYPES])
|
875
866
|
has_valid_eco_climate_zone = all([eco_climate_zone, eco_climate_zone not in _EXCLUDED_ECO_CLIMATE_ZONES])
|
876
|
-
has_land_cover_nodes = len(land_cover_nodes) >
|
867
|
+
has_land_cover_nodes = len(land_cover_nodes) > 1
|
877
868
|
|
878
869
|
should_compile_inventory = all([
|
879
870
|
has_valid_site_type,
|
@@ -881,9 +872,9 @@ def _should_run(cycle: dict):
|
|
881
872
|
has_land_cover_nodes
|
882
873
|
])
|
883
874
|
|
884
|
-
|
885
|
-
|
886
|
-
if should_compile_inventory else (
|
875
|
+
should_run, inventory, compilation_logs = (
|
876
|
+
_compile_inventory(cycle, site, land_cover_nodes, eco_climate_zone)
|
877
|
+
if should_compile_inventory else (False, {}, {})
|
887
878
|
)
|
888
879
|
|
889
880
|
logs = {
|
@@ -897,21 +888,18 @@ def _should_run(cycle: dict):
|
|
897
888
|
**compilation_logs
|
898
889
|
}
|
899
890
|
|
900
|
-
|
901
|
-
|
902
|
-
_should_run_emission(term_id, cycle, emission_inventory, inventory, logs) for term_id in EMISSION_TERM_IDS
|
903
|
-
])
|
904
|
-
])
|
891
|
+
for term_id in EMISSION_TERM_IDS:
|
892
|
+
_log_emission_data(should_run, term_id, cycle, inventory, logs)
|
905
893
|
|
906
|
-
return should_run,
|
894
|
+
return should_run, inventory
|
907
895
|
|
908
896
|
|
909
|
-
def _run_emission(term_id: _EmissionTermId,
|
897
|
+
def _run_emission(term_id: _EmissionTermId, cycle_id: str, inventory: _Inventory) -> list[dict]:
|
910
898
|
"""
|
911
|
-
Retrieve the
|
899
|
+
Retrieve the sum relevant emissions and format them as a HESTIA
|
912
900
|
[Emission node](https://www.hestia.earth/schema/Emission).
|
913
901
|
"""
|
914
|
-
emission =
|
902
|
+
emission = _sum_cycle_emissions(term_id, cycle_id, inventory)
|
915
903
|
descriptive_stats = calc_descriptive_stats(emission, STATS_DEFINITION, decimals=3)
|
916
904
|
return _emission(term_id, **descriptive_stats)
|
917
905
|
|
@@ -932,5 +920,5 @@ def run(cycle: dict):
|
|
932
920
|
`ch4ToAirNaturalVegetationBurning` **OR** `coToAirNaturalVegetationBurning` **OR**
|
933
921
|
`n2OToAirNaturalVegetationBurningDirect` **OR** `noxToAirNaturalVegetationBurning`.
|
934
922
|
"""
|
935
|
-
should_run,
|
936
|
-
return [_run_emission(term_id,
|
923
|
+
should_run, inventory = _should_run(cycle)
|
924
|
+
return [_run_emission(term_id, cycle.get("@id"), inventory) for term_id in EMISSION_TERM_IDS] if should_run else []
|
@@ -31,6 +31,77 @@ from .organicCarbonPerHa_utils import (
|
|
31
31
|
)
|
32
32
|
from . import MODEL
|
33
33
|
|
34
|
+
REQUIREMENTS = {
|
35
|
+
"Site": {
|
36
|
+
"management": [
|
37
|
+
{"@type": "Management", "value": "", "term.termType": "landCover"}
|
38
|
+
],
|
39
|
+
"measurements": [
|
40
|
+
{
|
41
|
+
"@type": "Measurement",
|
42
|
+
"value": ["1", "2", "3", "4", "7", "8", "9", "10", "11", "12"],
|
43
|
+
"term.@id": "ecoClimateZone"
|
44
|
+
}
|
45
|
+
],
|
46
|
+
"optional": {
|
47
|
+
"measurements": [
|
48
|
+
{"@type": "Measurement", "value": "", "term.termType": ["soilType", "usdaSoilType"]}
|
49
|
+
],
|
50
|
+
"management": [
|
51
|
+
{
|
52
|
+
"@type": "Management",
|
53
|
+
"value": "",
|
54
|
+
"startDate": "",
|
55
|
+
"endDate": "",
|
56
|
+
"term.termType": "cropResidueManagement",
|
57
|
+
"name": ["burnt", "removed"]
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"@type": "Management",
|
61
|
+
"value": "",
|
62
|
+
"startDate": "",
|
63
|
+
"endDate": "",
|
64
|
+
"term.termType": "landUseManagement"
|
65
|
+
},
|
66
|
+
{"@type": "Management", "value": "", "startDate": "", "endDate": "", "term.termType": "tillage"},
|
67
|
+
{
|
68
|
+
"@type": "Management",
|
69
|
+
"value": "",
|
70
|
+
"startDate": "",
|
71
|
+
"endDate": "",
|
72
|
+
"term.termType": "waterRegime",
|
73
|
+
"name": ["deep water", "irrigated"]
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"@type": "Management",
|
77
|
+
"value": "",
|
78
|
+
"startDate": "",
|
79
|
+
"endDate": "",
|
80
|
+
"term.@id": "amendmentIncreasingSoilCarbonUsed"
|
81
|
+
},
|
82
|
+
{"@type": "Management", "value": "", "startDate": "", "endDate": "", "term.@id": "animalManureUsed"},
|
83
|
+
{
|
84
|
+
"@type": "Management",
|
85
|
+
"value": "",
|
86
|
+
"startDate": "",
|
87
|
+
"endDate": "",
|
88
|
+
"term.@id": "inorganicNitrogenFertiliserUsed"
|
89
|
+
},
|
90
|
+
{
|
91
|
+
"@type": "Management",
|
92
|
+
"value": "",
|
93
|
+
"startDate": "",
|
94
|
+
"endDate": "",
|
95
|
+
"term.@id": "organicFertiliserUsed"
|
96
|
+
},
|
97
|
+
{"@type": "Management", "value": "", "startDate": "", "endDate": "", "term.@id": "shortBareFallow"}
|
98
|
+
]
|
99
|
+
},
|
100
|
+
"none": {
|
101
|
+
"siteType": ["glass or high accessible cover"]
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
34
105
|
LOOKUPS = {
|
35
106
|
"crop": "IPCC_LAND_USE_CATEGORY",
|
36
107
|
"landCover": [
|
@@ -43,6 +114,20 @@ LOOKUPS = {
|
|
43
114
|
"tillage": "IPCC_TILLAGE_MANAGEMENT_CATEGORY",
|
44
115
|
"usdaSoilType": "IPCC_SOIL_CATEGORY"
|
45
116
|
}
|
117
|
+
RETURNS = {
|
118
|
+
"Measurement": [{
|
119
|
+
"value": "",
|
120
|
+
"sd": "",
|
121
|
+
"min": "",
|
122
|
+
"max": "",
|
123
|
+
"statsDefinition": "simulated",
|
124
|
+
"observations": "",
|
125
|
+
"dates": "",
|
126
|
+
"depthUpper": "0",
|
127
|
+
"depthLower": "30",
|
128
|
+
"methodClassification": "tier 1 model"
|
129
|
+
}]
|
130
|
+
}
|
46
131
|
|
47
132
|
TERM_ID = 'organicCarbonPerHa'
|
48
133
|
_METHOD_CLASSIFICATION = MeasurementMethodClassification.TIER_1_MODEL.value
|
@@ -108,7 +193,7 @@ def _measurement(
|
|
108
193
|
dict
|
109
194
|
A valid HESTIA `Measurement` node, see: https://www.hestia.earth/schema/Measurement.
|
110
195
|
"""
|
111
|
-
measurement = _new_measurement(TERM_ID) | descriptive_stats_dict
|
196
|
+
measurement = _new_measurement(TERM_ID, MODEL) | descriptive_stats_dict
|
112
197
|
measurement["dates"] = [f"{year}-12-31" for year in timestamps]
|
113
198
|
measurement["depthUpper"] = DEPTH_UPPER
|
114
199
|
measurement["depthLower"] = DEPTH_LOWER
|
@@ -33,11 +33,137 @@ from .organicCarbonPerHa_utils import (
|
|
33
33
|
)
|
34
34
|
from . import MODEL
|
35
35
|
|
36
|
+
REQUIREMENTS = {
|
37
|
+
"Site": {
|
38
|
+
"siteType": "cropland",
|
39
|
+
"measurements": [
|
40
|
+
{
|
41
|
+
"@type": "Measurement",
|
42
|
+
"term.@id": "sandContent",
|
43
|
+
"value": "",
|
44
|
+
"depthUpper": "0",
|
45
|
+
"depthLower": "30",
|
46
|
+
"optional": {
|
47
|
+
"dates": ""
|
48
|
+
}
|
49
|
+
},
|
50
|
+
{
|
51
|
+
"@type": "Measurement",
|
52
|
+
"term.@id": "temperatureMonthly",
|
53
|
+
"value": "",
|
54
|
+
"dates": ""
|
55
|
+
},
|
56
|
+
{
|
57
|
+
"@type": "Measurement",
|
58
|
+
"term.@id": "precipitationMonthly",
|
59
|
+
"value": "",
|
60
|
+
"dates": ""
|
61
|
+
},
|
62
|
+
{
|
63
|
+
"@type": "Measurement",
|
64
|
+
"term.@id": "potentialEvapotranspirationMonthly",
|
65
|
+
"value": "",
|
66
|
+
"dates": ""
|
67
|
+
}
|
68
|
+
],
|
69
|
+
"related": {
|
70
|
+
"Cycle": [{
|
71
|
+
"endDate": "",
|
72
|
+
"products": [
|
73
|
+
{
|
74
|
+
"@type": "Product",
|
75
|
+
"term.@id": [
|
76
|
+
"aboveGroundCropResidueLeftOnField",
|
77
|
+
"aboveGroundCropResidueIncorporated",
|
78
|
+
"belowGroundCropResidue",
|
79
|
+
"discardedCropLeftOnField",
|
80
|
+
"discardedCropIncorporated"
|
81
|
+
],
|
82
|
+
"value": "",
|
83
|
+
"properties": [
|
84
|
+
{
|
85
|
+
"@type": "Property",
|
86
|
+
"term.@id": "carbonContent",
|
87
|
+
"value": ""
|
88
|
+
},
|
89
|
+
{
|
90
|
+
"@type": "Property",
|
91
|
+
"term.@id": "nitrogenContent",
|
92
|
+
"value": ""
|
93
|
+
},
|
94
|
+
{
|
95
|
+
"@type": "Property",
|
96
|
+
"term.@id": "ligninContent",
|
97
|
+
"value": ""
|
98
|
+
}
|
99
|
+
]
|
100
|
+
}
|
101
|
+
],
|
102
|
+
"inputs": [
|
103
|
+
{
|
104
|
+
"@type": "Input",
|
105
|
+
"term.termType": ["organicFertiliser", "soilAmendment"],
|
106
|
+
"value": "",
|
107
|
+
"properties": [
|
108
|
+
{
|
109
|
+
"@type": "Property",
|
110
|
+
"term.@id": "carbonContent",
|
111
|
+
"value": ""
|
112
|
+
},
|
113
|
+
{
|
114
|
+
"@type": "Property",
|
115
|
+
"term.@id": "nitrogenContent",
|
116
|
+
"value": ""
|
117
|
+
},
|
118
|
+
{
|
119
|
+
"@type": "Property",
|
120
|
+
"term.@id": "ligninContent",
|
121
|
+
"value": ""
|
122
|
+
}
|
123
|
+
]
|
124
|
+
}
|
125
|
+
],
|
126
|
+
"practices": [
|
127
|
+
{
|
128
|
+
"@type": "Practice",
|
129
|
+
"term.termType": "tillage",
|
130
|
+
"value": ""
|
131
|
+
},
|
132
|
+
{
|
133
|
+
"@type": "Practice",
|
134
|
+
"term.termType": "waterRegime",
|
135
|
+
"name": "irrigated",
|
136
|
+
"value": "",
|
137
|
+
"startDate": "",
|
138
|
+
"endDate": ""
|
139
|
+
}
|
140
|
+
],
|
141
|
+
"optional": {
|
142
|
+
"startDate": ""
|
143
|
+
}
|
144
|
+
}]
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
36
148
|
LOOKUPS = {
|
37
149
|
"crop": "IPCC_LAND_USE_CATEGORY",
|
38
150
|
"landCover": "IPCC_LAND_USE_CATEGORY",
|
39
151
|
"tillage": "IPCC_TILLAGE_MANAGEMENT_CATEGORY"
|
40
152
|
}
|
153
|
+
RETURNS = {
|
154
|
+
"Measurement": [{
|
155
|
+
"value": "",
|
156
|
+
"sd": "",
|
157
|
+
"min": "",
|
158
|
+
"max": "",
|
159
|
+
"statsDefinition": "simulated",
|
160
|
+
"observations": "",
|
161
|
+
"dates": "",
|
162
|
+
"depthUpper": "0",
|
163
|
+
"depthLower": "30",
|
164
|
+
"methodClassification": "tier 2 model"
|
165
|
+
}]
|
166
|
+
}
|
41
167
|
|
42
168
|
TERM_ID = 'organicCarbonPerHa'
|
43
169
|
_METHOD_CLASSIFICATION = MeasurementMethodClassification.TIER_2_MODEL.value
|
@@ -124,7 +250,7 @@ def _measurement(
|
|
124
250
|
dict
|
125
251
|
A valid HESTIA `Measurement` node, see: https://www.hestia.earth/schema/Measurement.
|
126
252
|
"""
|
127
|
-
measurement = _new_measurement(TERM_ID) | descriptive_stats_dict
|
253
|
+
measurement = _new_measurement(TERM_ID, MODEL) | descriptive_stats_dict
|
128
254
|
measurement["dates"] = [f"{year}-12-31" for year in timestamps]
|
129
255
|
measurement["depthUpper"] = DEPTH_UPPER
|
130
256
|
measurement["depthLower"] = DEPTH_LOWER
|
@@ -1,13 +1,15 @@
|
|
1
1
|
from enum import Enum
|
2
|
+
from numpy import inf
|
2
3
|
from numpy.typing import NDArray
|
3
4
|
from typing import NamedTuple, Optional
|
4
5
|
|
5
6
|
from hestia_earth.schema import MeasurementStatsDefinition, SiteSiteType
|
6
7
|
|
7
8
|
from hestia_earth.models.utils.array_builders import (
|
8
|
-
repeat_single,
|
9
|
+
repeat_single, truncated_normal_1d
|
9
10
|
)
|
10
11
|
from hestia_earth.models.utils.blank_node import cumulative_nodes_term_match, node_term_match
|
12
|
+
from hestia_earth.models.utils.stats import calc_z_critical
|
11
13
|
from hestia_earth.models.utils.term import get_cover_crop_property_terms, get_irrigated_terms
|
12
14
|
|
13
15
|
STATS_DEFINITION = MeasurementStatsDefinition.SIMULATED.value
|
@@ -238,7 +240,9 @@ def sample_plus_minus_uncertainty(
|
|
238
240
|
*, iterations: int, value: float, uncertainty: float, seed: Optional[int] = None, **_
|
239
241
|
) -> NDArray:
|
240
242
|
"""Randomly sample a model parameter with a plus/minus uncertainty distribution."""
|
241
|
-
|
243
|
+
n_sds = calc_z_critical(95)
|
244
|
+
sigma = (value * (uncertainty / 100)) / n_sds
|
245
|
+
return truncated_normal_1d(shape=(1, iterations), mu=value, sigma=sigma, low=0, high=inf, seed=seed)
|
242
246
|
|
243
247
|
|
244
248
|
def sample_plus_minus_error(
|
@@ -246,9 +250,7 @@ def sample_plus_minus_error(
|
|
246
250
|
) -> NDArray:
|
247
251
|
"""Randomly sample a model parameter with a truncated normal distribution described using plus/minus error."""
|
248
252
|
sd = value * (error / 200)
|
249
|
-
|
250
|
-
high = value + (value * (error / 100))
|
251
|
-
return truncated_normal_1d(shape=(1, iterations), mu=value, sigma=sd, low=low, high=high, seed=seed)
|
253
|
+
return truncated_normal_1d(shape=(1, iterations), mu=value, sigma=sd, low=0, high=inf, seed=seed)
|
252
254
|
|
253
255
|
|
254
256
|
def sample_constant(*, iterations: int, value: float, **_) -> NDArray:
|