hestia-earth-models 0.64.11__py3-none-any.whl → 0.64.13__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.
Potentially problematic release.
This version of hestia-earth-models might be problematic. Click here for more details.
- hestia_earth/models/aware/scarcityWeightedWaterUse.py +1 -1
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandOccupation.py +1 -1
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandTransformation.py +1 -1
- hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsTotalLandUseEffects.py +3 -2
- hestia_earth/models/cml2001Baseline/eutrophicationPotentialExcludingFate.py +2 -2
- hestia_earth/models/cml2001Baseline/terrestrialAcidificationPotentialIncludingFateAverageEurope.py +2 -2
- hestia_earth/models/cml2001NonBaseline/eutrophicationPotentialIncludingFateAverageEurope.py +2 -2
- hestia_earth/models/cml2001NonBaseline/terrestrialAcidificationPotentialExcludingFate.py +2 -2
- hestia_earth/models/cycle/completeness/seed.py +6 -4
- hestia_earth/models/cycle/concentrateFeed.py +36 -19
- hestia_earth/models/cycle/endDate.py +10 -1
- hestia_earth/models/cycle/milkYield.py +6 -5
- hestia_earth/models/cycle/startDate.py +6 -4
- hestia_earth/models/edip2003/ozoneDepletionPotential.py +2 -2
- hestia_earth/models/emissionNotRelevant/__init__.py +3 -2
- hestia_earth/models/environmentalFootprintV3/freshwaterEcotoxicityPotentialCtue.py +2 -3
- hestia_earth/models/faostat2018/utils.py +72 -12
- hestia_earth/models/hestia/__init__.py +13 -0
- hestia_earth/models/hestia/landCover.py +727 -0
- hestia_earth/models/ipcc2013ExcludingFeedbacks/gwp100.py +2 -2
- hestia_earth/models/ipcc2013IncludingFeedbacks/gwp100.py +2 -2
- hestia_earth/models/ipcc2019/aboveGroundBiomass.py +4 -8
- hestia_earth/models/ipcc2019/animal/fatContent.py +1 -1
- hestia_earth/models/ipcc2019/animal/milkYieldPerAnimal.py +91 -0
- hestia_earth/models/ipcc2019/animal/trueProteinContent.py +1 -1
- hestia_earth/models/ipcc2019/animal/utils.py +17 -12
- hestia_earth/models/ipcc2019/belowGroundBiomass.py +4 -8
- hestia_earth/models/ipcc2019/biomass_utils.py +11 -0
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +1 -1
- hestia_earth/models/ipcc2019/co2ToAirAboveGroundBiomassStockChange.py +8 -4
- hestia_earth/models/ipcc2019/co2ToAirBelowGroundBiomassStockChange.py +7 -3
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +52 -6
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChange.py +7 -3
- hestia_earth/models/ipcc2019/n2OToAirExcretaDirect.py +14 -9
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +9 -3
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +1 -2
- hestia_earth/models/koble2014/aboveGroundCropResidue.py +5 -1
- hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsClimateChange.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsFreshwaterEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealth.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthClimateChange.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthHumanToxicityCancerogenic.py +2 -3
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthHumanToxicityNonCancerogenic.py +2 -3
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthStratosphericOzoneDepletion.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToMarineEcosystemsMarineEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactAllEffects100Years/damageToMarineEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsClimateChange.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsTerrestrialEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsClimateChange.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealth.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthClimateChange.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthHumanToxicityCancerogenic.py +2 -3
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthHumanToxicityNonCancerogenic.py +2 -3
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthStratosphericOzoneDepletion.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToMarineEcosystemsMarineEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToMarineEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsClimateChange.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsFreshwaterEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealth.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthClimateChange.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthHumanToxicityCancerogenic.py +2 -3
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthHumanToxicityNonCancerogenic.py +2 -3
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthStratosphericOzoneDepletion.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToMarineEcosystemsMarineEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactCertainEffects100Years/damageToMarineEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsClimateChange.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsTerrestrialEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealth.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthClimateChange.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthHumanToxicityCancerogenic.py +2 -3
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthHumanToxicityNonCancerogenic.py +2 -3
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthStratosphericOzoneDepletion.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToMarineEcosystemsMarineEcotoxicity.py +2 -3
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToMarineEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsClimateChange.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsPdfYear.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialEcotoxicity.py +2 -3
- hestia_earth/models/linkedImpactAssessment/emissions.py +3 -0
- hestia_earth/models/log.py +4 -3
- hestia_earth/models/mocking/search-results.json +575 -575
- hestia_earth/models/pooreNemecek2018/excretaKgN.py +4 -4
- hestia_earth/models/pooreNemecek2018/excretaKgVs.py +4 -4
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterCropResidueDecomposition.py +1 -1
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterExcreta.py +1 -1
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterInorganicFertiliser.py +1 -1
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterOrganicFertiliser.py +1 -1
- hestia_earth/models/pooreNemecek2018/{saplings.py → saplingsDepreciatedAmountPerCycle.py} +1 -1
- hestia_earth/models/pooreNemecek2018/utils.py +7 -1
- hestia_earth/models/recipe2016Egalitarian/damageToFreshwaterEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Egalitarian/damageToHumanHealth.py +2 -2
- hestia_earth/models/recipe2016Egalitarian/damageToMarineEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Egalitarian/damageToTerrestrialEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Egalitarian/freshwaterAquaticEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/recipe2016Egalitarian/freshwaterEutrophicationPotential.py +2 -2
- hestia_earth/models/recipe2016Egalitarian/humanCarcinogenicToxicity.py +2 -3
- hestia_earth/models/recipe2016Egalitarian/humanNonCarcinogenicToxicity.py +2 -3
- hestia_earth/models/recipe2016Egalitarian/marineAquaticEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/recipe2016Egalitarian/marineEutrophicationPotential.py +2 -2
- hestia_earth/models/recipe2016Egalitarian/ozoneDepletionPotential.py +2 -2
- hestia_earth/models/recipe2016Egalitarian/terrestrialAcidificationPotential.py +2 -2
- hestia_earth/models/recipe2016Egalitarian/terrestrialEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/recipe2016Hierarchist/damageToFreshwaterEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Hierarchist/damageToHumanHealth.py +2 -2
- hestia_earth/models/recipe2016Hierarchist/damageToMarineEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Hierarchist/damageToTerrestrialEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Hierarchist/freshwaterAquaticEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/recipe2016Hierarchist/freshwaterEutrophicationPotential.py +2 -2
- hestia_earth/models/recipe2016Hierarchist/humanCarcinogenicToxicity.py +2 -3
- hestia_earth/models/recipe2016Hierarchist/humanNonCarcinogenicToxicity.py +2 -3
- hestia_earth/models/recipe2016Hierarchist/marineAquaticEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/recipe2016Hierarchist/marineEutrophicationPotential.py +2 -2
- hestia_earth/models/recipe2016Hierarchist/ozoneDepletionPotential.py +2 -2
- hestia_earth/models/recipe2016Hierarchist/terrestrialAcidificationPotential.py +2 -2
- hestia_earth/models/recipe2016Hierarchist/terrestrialEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/recipe2016Individualist/damageToFreshwaterEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Individualist/damageToHumanHealth.py +2 -2
- hestia_earth/models/recipe2016Individualist/damageToMarineEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Individualist/damageToTerrestrialEcosystemsSpeciesYear.py +2 -2
- hestia_earth/models/recipe2016Individualist/freshwaterAquaticEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/recipe2016Individualist/freshwaterEutrophicationPotential.py +2 -2
- hestia_earth/models/recipe2016Individualist/humanCarcinogenicToxicity.py +2 -3
- hestia_earth/models/recipe2016Individualist/humanNonCarcinogenicToxicity.py +2 -3
- hestia_earth/models/recipe2016Individualist/marineAquaticEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/recipe2016Individualist/marineEutrophicationPotential.py +2 -2
- hestia_earth/models/recipe2016Individualist/ozoneDepletionPotential.py +2 -2
- hestia_earth/models/recipe2016Individualist/terrestrialAcidificationPotential.py +2 -2
- hestia_earth/models/recipe2016Individualist/terrestrialEcotoxicityPotential14Dcbeq.py +2 -3
- hestia_earth/models/site/management.py +142 -144
- hestia_earth/models/stehfestBouwman2006/n2OToAirCropResidueDecompositionDirect.py +1 -1
- hestia_earth/models/stehfestBouwman2006/n2OToAirExcretaDirect.py +1 -1
- hestia_earth/models/stehfestBouwman2006/n2OToAirInorganicFertiliserDirect.py +1 -1
- hestia_earth/models/stehfestBouwman2006/n2OToAirOrganicFertiliserDirect.py +1 -1
- hestia_earth/models/stehfestBouwman2006/noxToAirCropResidueDecomposition.py +1 -1
- hestia_earth/models/stehfestBouwman2006/noxToAirExcreta.py +1 -1
- hestia_earth/models/stehfestBouwman2006/noxToAirInorganicFertiliser.py +1 -1
- hestia_earth/models/stehfestBouwman2006/noxToAirOrganicFertiliser.py +1 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirCropResidueDecomposition.py +1 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirExcreta.py +1 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirInorganicFertiliser.py +1 -1
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirOrganicFertiliser.py +1 -1
- hestia_earth/models/usetoxV2/freshwaterEcotoxicityPotentialCtue.py +2 -3
- hestia_earth/models/utils/__init__.py +4 -1
- hestia_earth/models/utils/blank_node.py +34 -14
- hestia_earth/models/utils/emission.py +1 -8
- hestia_earth/models/utils/lookup.py +2 -1
- hestia_earth/models/utils/management.py +11 -0
- hestia_earth/models/utils/pesticideAI.py +11 -17
- hestia_earth/models/utils/term.py +2 -1
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.64.11.dist-info → hestia_earth_models-0.64.13.dist-info}/METADATA +4 -4
- {hestia_earth_models-0.64.11.dist-info → hestia_earth_models-0.64.13.dist-info}/RECORD +192 -188
- {hestia_earth_models-0.64.11.dist-info → hestia_earth_models-0.64.13.dist-info}/WHEEL +1 -1
- tests/models/cycle/completeness/test_seed.py +1 -1
- tests/models/cycle/test_endDate.py +18 -2
- tests/models/cycle/test_startDate.py +21 -3
- tests/models/faostat2018/test_faostat_utils.py +84 -0
- tests/models/hestia/__init__.py +0 -0
- tests/models/hestia/test_landCover.py +210 -0
- tests/models/ipcc2019/animal/test_milkYieldPerAnimal.py +21 -0
- tests/models/ipcc2019/test_aboveGroundBiomass.py +2 -1
- tests/models/ipcc2019/test_belowGroundBiomass.py +2 -1
- tests/models/ipcc2019/test_co2ToAirAboveGroundBiomassStockChange.py +4 -3
- tests/models/ipcc2019/test_co2ToAirBelowGroundBiomassStockChange.py +3 -3
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChange.py +49 -2
- tests/models/ipcc2019/test_n2OToAirExcretaDirect.py +12 -0
- tests/models/ipcc2019/test_organicCarbonPerHa.py +1 -0
- tests/models/koble2014/test_aboveGroundCropResidue.py +13 -0
- tests/models/pooreNemecek2018/test_no3ToGroundwaterCropResidueDecomposition.py +3 -2
- tests/models/pooreNemecek2018/test_no3ToGroundwaterExcreta.py +3 -2
- tests/models/pooreNemecek2018/test_no3ToGroundwaterInorganicFertiliser.py +3 -2
- tests/models/pooreNemecek2018/test_no3ToGroundwaterOrganicFertiliser.py +3 -2
- tests/models/pooreNemecek2018/{test_saplings.py → test_saplingsDepreciatedAmountPerCycle.py} +1 -1
- tests/models/site/test_management.py +18 -151
- tests/models/utils/test_blank_node.py +57 -1
- tests/models/utils/test_emission.py +1 -6
- tests/models/utils/test_site.py +33 -2
- tests/models/pooreNemecek2018/test_no3ToGroundwaterSoilFlux.py +0 -90
- tests/models/stehfestBouwman2006/test_n2OToAirSoilFlux.py +0 -41
- tests/models/stehfestBouwman2006/test_noxToAirSoilFlux.py +0 -40
- tests/models/stehfestBouwman2006GisImplementation/test_noxToAirSoilFlux.py +0 -33
- /hestia_earth/models/pooreNemecek2018/{no3ToGroundwaterSoilFlux.py → no3ToGroundwaterSoilFlux_utils.py} +0 -0
- /hestia_earth/models/stehfestBouwman2006/{n2OToAirSoilFlux.py → n2OToAirSoilFlux_utils.py} +0 -0
- /hestia_earth/models/stehfestBouwman2006/{noxToAirSoilFlux.py → noxToAirSoilFlux_utils.py} +0 -0
- /hestia_earth/models/stehfestBouwman2006GisImplementation/{noxToAirSoilFlux.py → noxToAirSoilFlux_utils.py} +0 -0
- {hestia_earth_models-0.64.11.dist-info → hestia_earth_models-0.64.13.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.64.11.dist-info → hestia_earth_models-0.64.13.dist-info}/top_level.txt +0 -0
|
@@ -29,5 +29,5 @@ def run(impact_assessment: dict):
|
|
|
29
29
|
value = impact_emission_lookup_value(MODEL, TERM_ID, impact_assessment, LOOKUPS['emission'])
|
|
30
30
|
logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
|
|
31
31
|
value=value)
|
|
32
|
-
logShouldRun(impact_assessment, MODEL, TERM_ID,
|
|
33
|
-
return _indicator(value)
|
|
32
|
+
logShouldRun(impact_assessment, MODEL, TERM_ID, value is not None)
|
|
33
|
+
return _indicator(value) if value is not None else None
|
|
@@ -29,5 +29,5 @@ def run(impact_assessment: dict):
|
|
|
29
29
|
value = impact_emission_lookup_value(MODEL, TERM_ID, impact_assessment, LOOKUPS['emission'])
|
|
30
30
|
logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
|
|
31
31
|
value=value)
|
|
32
|
-
logShouldRun(impact_assessment, MODEL, TERM_ID,
|
|
33
|
-
return _indicator(value)
|
|
32
|
+
logShouldRun(impact_assessment, MODEL, TERM_ID, value is not None)
|
|
33
|
+
return _indicator(value) if value is not None else None
|
|
@@ -7,11 +7,9 @@ from typing import Optional, Union
|
|
|
7
7
|
from hestia_earth.schema import (
|
|
8
8
|
MeasurementMethodClassification,
|
|
9
9
|
MeasurementStatsDefinition,
|
|
10
|
-
SiteSiteType
|
|
11
|
-
TermTermType
|
|
10
|
+
SiteSiteType
|
|
12
11
|
)
|
|
13
12
|
|
|
14
|
-
from hestia_earth.utils.model import filter_list_term_type
|
|
15
13
|
from hestia_earth.utils.tools import non_empty_list
|
|
16
14
|
|
|
17
15
|
from hestia_earth.models.log import log_as_table, logRequirements, logShouldRun
|
|
@@ -24,8 +22,8 @@ from hestia_earth.models.utils.measurement import _new_measurement
|
|
|
24
22
|
|
|
25
23
|
from . import MODEL
|
|
26
24
|
from .biomass_utils import (
|
|
27
|
-
BiomassCategory, detect_land_cover_change, group_by_biomass_category, group_by_term_id,
|
|
28
|
-
summarise_land_cover_nodes
|
|
25
|
+
BiomassCategory, get_valid_land_cover_terms, detect_land_cover_change, group_by_biomass_category, group_by_term_id,
|
|
26
|
+
sample_biomass_equilibrium, summarise_land_cover_nodes
|
|
29
27
|
)
|
|
30
28
|
|
|
31
29
|
|
|
@@ -94,8 +92,6 @@ _ITERATIONS = 10000
|
|
|
94
92
|
_METHOD_CLASSIFICATION = MeasurementMethodClassification.TIER_1_MODEL.value
|
|
95
93
|
_STATS_DEFINITION = MeasurementStatsDefinition.SIMULATED.value
|
|
96
94
|
|
|
97
|
-
_LAND_COVER_TERM_TYPE = TermTermType.LANDCOVER
|
|
98
|
-
|
|
99
95
|
_EQUILIBRIUM_TRANSITION_PERIOD = 20
|
|
100
96
|
_EXCLUDED_ECO_CLIMATE_ZONES = {EcoClimateZone.POLAR_MOIST, EcoClimateZone.POLAR_DRY}
|
|
101
97
|
_EXCLUDED_SITE_TYPES = {
|
|
@@ -156,7 +152,7 @@ def _should_run(site: dict) -> tuple[bool, dict, dict]:
|
|
|
156
152
|
site_type = site.get("siteType")
|
|
157
153
|
eco_climate_zone = get_eco_climate_zone_value(site, as_enum=True)
|
|
158
154
|
|
|
159
|
-
land_cover =
|
|
155
|
+
land_cover = get_valid_land_cover_terms(site)
|
|
160
156
|
|
|
161
157
|
has_valid_site_type = site_type not in _EXCLUDED_SITE_TYPES
|
|
162
158
|
has_valid_eco_climate_zone = all([
|
|
@@ -33,6 +33,6 @@ TERM_ID = 'fatContent'
|
|
|
33
33
|
|
|
34
34
|
def run(cycle: dict):
|
|
35
35
|
animals = should_run_by_productivity_lookup(
|
|
36
|
-
TERM_ID, cycle, list(LOOKUPS.keys())[0],
|
|
36
|
+
TERM_ID, cycle, list(LOOKUPS.keys())[0], practice_column=LOOKUPS['liveAnimal']
|
|
37
37
|
)
|
|
38
38
|
return list(map(run_animal_by_productivity(TERM_ID, include_practice=True), animals))
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Milk Yield Per Animal
|
|
3
|
+
|
|
4
|
+
This model gap-fills the practice "Milk yield per X, raw" for live animals added to the animal node,
|
|
5
|
+
taking values from a lookup file.
|
|
6
|
+
"""
|
|
7
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
8
|
+
from hestia_earth.models.utils.blank_node import merge_blank_nodes, get_lookup_value
|
|
9
|
+
from hestia_earth.models.utils.practice import _new_practice
|
|
10
|
+
from .utils import map_live_animals_by_productivity_lookup
|
|
11
|
+
from .. import MODEL
|
|
12
|
+
|
|
13
|
+
REQUIREMENTS = {
|
|
14
|
+
"Cycle": {
|
|
15
|
+
"site": {
|
|
16
|
+
"@type": "Site",
|
|
17
|
+
"country": {"@type": "Term", "termType": "region"}
|
|
18
|
+
},
|
|
19
|
+
"animals": [{
|
|
20
|
+
"@type": "Animal",
|
|
21
|
+
"term.termType": "liveAnimal",
|
|
22
|
+
"practices": {
|
|
23
|
+
"@type": "Practice",
|
|
24
|
+
"term.termType": "animalManagement"
|
|
25
|
+
}
|
|
26
|
+
}]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
LOOKUPS = {
|
|
30
|
+
"region-liveAnimal-milkYieldPerAnimal": "yield value",
|
|
31
|
+
"liveAnimal": ["milkYieldPracticeTermIds", "ipcc2019MilkYieldPerAnimalTermId"]
|
|
32
|
+
}
|
|
33
|
+
RETURNS = {
|
|
34
|
+
"Animal": [{
|
|
35
|
+
"practices": [{
|
|
36
|
+
"@type": "Practice",
|
|
37
|
+
"value": ""
|
|
38
|
+
}]
|
|
39
|
+
}]
|
|
40
|
+
}
|
|
41
|
+
MODEL_KEY = 'milkYieldPerAnimal'
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _practice(term_id: str, value: float):
|
|
45
|
+
node = _new_practice(term_id, MODEL)
|
|
46
|
+
node['value'] = [value]
|
|
47
|
+
return node
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _run_animal(data: dict):
|
|
51
|
+
animal = data.get('animal')
|
|
52
|
+
value = data.get('value')
|
|
53
|
+
practice_id = get_lookup_value(animal.get('term'), LOOKUPS['liveAnimal'][1])
|
|
54
|
+
return animal | ({
|
|
55
|
+
'practices': merge_blank_nodes(animal.get('practices', []), [_practice(practice_id, value)])
|
|
56
|
+
} if practice_id else {})
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _should_run(cycle: dict):
|
|
60
|
+
country = cycle.get('site', {}).get('country', {})
|
|
61
|
+
country_id = country.get('@id')
|
|
62
|
+
live_animals_with_value = map_live_animals_by_productivity_lookup(
|
|
63
|
+
None, cycle, list(LOOKUPS.keys())[0], practice_column=LOOKUPS['liveAnimal'][0]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def _should_run_animal(value: dict):
|
|
67
|
+
animal = value.get('animal')
|
|
68
|
+
lookup_value = value.get('value')
|
|
69
|
+
term_id = animal.get('term').get('@id')
|
|
70
|
+
practice = value.get('practice')
|
|
71
|
+
|
|
72
|
+
logRequirements(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
73
|
+
country_id=country_id,
|
|
74
|
+
practice=practice.get('term', {}).get('@id'))
|
|
75
|
+
|
|
76
|
+
should_run = all([
|
|
77
|
+
country_id,
|
|
78
|
+
lookup_value is not None,
|
|
79
|
+
# must not have the practice already
|
|
80
|
+
not practice
|
|
81
|
+
])
|
|
82
|
+
logShouldRun(cycle, MODEL, term_id, should_run, model_key=MODEL_KEY)
|
|
83
|
+
|
|
84
|
+
return should_run
|
|
85
|
+
|
|
86
|
+
return list(filter(_should_run_animal, live_animals_with_value))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def run(cycle: dict):
|
|
90
|
+
animals = _should_run(cycle)
|
|
91
|
+
return list(map(_run_animal, animals))
|
|
@@ -33,6 +33,6 @@ TERM_ID = 'trueProteinContent'
|
|
|
33
33
|
|
|
34
34
|
def run(cycle: dict):
|
|
35
35
|
animals = should_run_by_productivity_lookup(
|
|
36
|
-
TERM_ID, cycle, list(LOOKUPS.keys())[0],
|
|
36
|
+
TERM_ID, cycle, list(LOOKUPS.keys())[0], practice_column=LOOKUPS['liveAnimal']
|
|
37
37
|
)
|
|
38
38
|
return list(map(run_animal_by_productivity(TERM_ID, include_practice=True), animals))
|
|
@@ -11,9 +11,9 @@ from hestia_earth.models.utils.term import get_lookup_value
|
|
|
11
11
|
from .. import MODEL
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def _get_practice(term_id: str, animal: dict,
|
|
14
|
+
def _get_practice(term_id: str, animal: dict, practice_column: str):
|
|
15
15
|
term = animal.get('term', {})
|
|
16
|
-
value = get_lookup_value(term,
|
|
16
|
+
value = get_lookup_value(term, practice_column, model=MODEL, term=term_id)
|
|
17
17
|
practice_ids = non_empty_list((value or '').split(';'))
|
|
18
18
|
return next(
|
|
19
19
|
(p for p in animal.get('practices', []) if p.get('term', {}).get('@id') in practice_ids),
|
|
@@ -36,7 +36,7 @@ def productivity_lookup_value(term_id: str, lookup: str, country: dict, animal:
|
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
def map_live_animals_by_productivity_lookup(term_id: str, cycle: dict, lookup_col: str,
|
|
39
|
+
def map_live_animals_by_productivity_lookup(term_id: str, cycle: dict, lookup_col: str, practice_column: str = None):
|
|
40
40
|
country = cycle.get('site', {}).get('country', {})
|
|
41
41
|
live_animals = filter_list_term_type(cycle.get('animals', []), TermTermType.LIVEANIMAL)
|
|
42
42
|
live_animals = list(filter(node_has_no_property(term_id), live_animals))
|
|
@@ -44,35 +44,40 @@ def map_live_animals_by_productivity_lookup(term_id: str, cycle: dict, lookup_co
|
|
|
44
44
|
'animal': animal,
|
|
45
45
|
'value': productivity_lookup_value(term_id, lookup_col, country, animal)
|
|
46
46
|
} | ({
|
|
47
|
-
'practice': _get_practice(term_id, animal,
|
|
48
|
-
} if
|
|
47
|
+
'practice': _get_practice(term_id, animal, practice_column)
|
|
48
|
+
} if practice_column else {}) for animal in live_animals]
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
def should_run_by_productivity_lookup(
|
|
51
|
+
def should_run_by_productivity_lookup(
|
|
52
|
+
term_id: str,
|
|
53
|
+
cycle: dict,
|
|
54
|
+
lookup_col: str,
|
|
55
|
+
practice_column: str = None
|
|
56
|
+
):
|
|
52
57
|
country = cycle.get('site', {}).get('country', {})
|
|
53
58
|
country_id = country.get('@id')
|
|
54
|
-
live_animals_with_value = map_live_animals_by_productivity_lookup(term_id, cycle, lookup_col,
|
|
59
|
+
live_animals_with_value = map_live_animals_by_productivity_lookup(term_id, cycle, lookup_col, practice_column)
|
|
55
60
|
|
|
56
61
|
def _should_run_animal(value: dict):
|
|
57
62
|
animal = value.get('animal')
|
|
58
63
|
lookup_value = value.get('value')
|
|
59
64
|
practice = value.get('practice')
|
|
60
|
-
|
|
65
|
+
animal_term_id = animal.get('term').get('@id')
|
|
61
66
|
|
|
62
|
-
logRequirements(cycle, model=MODEL, term=
|
|
67
|
+
logRequirements(cycle, model=MODEL, term=animal_term_id, property=term_id,
|
|
63
68
|
country_id=country_id,
|
|
64
69
|
**({
|
|
65
70
|
lookup_col.replace('-', '_'): lookup_value
|
|
66
71
|
} | ({
|
|
67
72
|
'practice': practice.get('term', {}).get('@id')
|
|
68
|
-
} if
|
|
73
|
+
} if practice_column else {})))
|
|
69
74
|
|
|
70
75
|
should_run = all([
|
|
71
76
|
country_id,
|
|
72
|
-
not
|
|
77
|
+
not practice_column or bool(practice),
|
|
73
78
|
lookup_value is not None
|
|
74
79
|
])
|
|
75
|
-
logShouldRun(cycle, MODEL,
|
|
80
|
+
logShouldRun(cycle, MODEL, animal_term_id, should_run, property=term_id)
|
|
76
81
|
|
|
77
82
|
return should_run
|
|
78
83
|
|
|
@@ -7,11 +7,9 @@ from typing import Optional, Union
|
|
|
7
7
|
from hestia_earth.schema import (
|
|
8
8
|
MeasurementMethodClassification,
|
|
9
9
|
MeasurementStatsDefinition,
|
|
10
|
-
SiteSiteType
|
|
11
|
-
TermTermType
|
|
10
|
+
SiteSiteType
|
|
12
11
|
)
|
|
13
12
|
|
|
14
|
-
from hestia_earth.utils.model import filter_list_term_type
|
|
15
13
|
from hestia_earth.utils.tools import non_empty_list
|
|
16
14
|
|
|
17
15
|
from hestia_earth.models.log import log_as_table, logRequirements, logShouldRun
|
|
@@ -24,8 +22,8 @@ from hestia_earth.models.utils.measurement import _new_measurement
|
|
|
24
22
|
|
|
25
23
|
from . import MODEL
|
|
26
24
|
from .biomass_utils import (
|
|
27
|
-
BiomassCategory, detect_land_cover_change, group_by_biomass_category,
|
|
28
|
-
summarise_land_cover_nodes
|
|
25
|
+
BiomassCategory, get_valid_land_cover_terms, detect_land_cover_change, group_by_biomass_category,
|
|
26
|
+
sample_biomass_equilibrium, summarise_land_cover_nodes
|
|
29
27
|
)
|
|
30
28
|
|
|
31
29
|
|
|
@@ -81,8 +79,6 @@ _ITERATIONS = 10000
|
|
|
81
79
|
_METHOD_CLASSIFICATION = MeasurementMethodClassification.TIER_1_MODEL.value
|
|
82
80
|
_STATS_DEFINITION = MeasurementStatsDefinition.SIMULATED.value
|
|
83
81
|
|
|
84
|
-
_LAND_COVER_TERM_TYPE = TermTermType.LANDCOVER
|
|
85
|
-
|
|
86
82
|
_EQUILIBRIUM_TRANSITION_PERIOD = 20
|
|
87
83
|
_EXCLUDED_ECO_CLIMATE_ZONES = {EcoClimateZone.POLAR_MOIST, EcoClimateZone.POLAR_DRY}
|
|
88
84
|
_EXCLUDED_SITE_TYPES = {
|
|
@@ -149,7 +145,7 @@ def _should_run(site: dict) -> tuple[bool, dict, dict]:
|
|
|
149
145
|
site_type = site.get("siteType")
|
|
150
146
|
eco_climate_zone = get_eco_climate_zone_value(site, as_enum=True)
|
|
151
147
|
|
|
152
|
-
land_cover =
|
|
148
|
+
land_cover = get_valid_land_cover_terms(site)
|
|
153
149
|
|
|
154
150
|
has_valid_site_type = site_type not in _EXCLUDED_SITE_TYPES
|
|
155
151
|
has_valid_eco_climate_zone = all([
|
|
@@ -5,9 +5,12 @@ from numpy import random
|
|
|
5
5
|
from numpy.typing import NDArray
|
|
6
6
|
from typing import Callable, Optional, Union
|
|
7
7
|
|
|
8
|
+
from hestia_earth.schema import TermTermType
|
|
8
9
|
from hestia_earth.utils.blank_node import get_node_value
|
|
10
|
+
from hestia_earth.utils.model import filter_list_term_type
|
|
9
11
|
|
|
10
12
|
from hestia_earth.models.utils.array_builders import repeat_single, truncated_normal_1d
|
|
13
|
+
from hestia_earth.models.utils.blank_node import validate_start_date_end_date
|
|
11
14
|
from hestia_earth.models.utils.ecoClimateZone import EcoClimateZone, get_ecoClimateZone_lookup_grouped_value
|
|
12
15
|
from hestia_earth.models.utils.term import get_lookup_value
|
|
13
16
|
|
|
@@ -404,3 +407,11 @@ _KWARGS_TO_SAMPLE_FUNC = {
|
|
|
404
407
|
("value", "error"): sample_plus_minus_error,
|
|
405
408
|
("value",): sample_constant
|
|
406
409
|
}
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def get_valid_land_cover_terms(site: dict) -> list[dict]:
|
|
413
|
+
"""Retrieve valid `landCover` nodes from a site's management."""
|
|
414
|
+
return [
|
|
415
|
+
node for node in filter_list_term_type(site.get("management", []), TermTermType.LANDCOVER)
|
|
416
|
+
if validate_start_date_end_date(node)
|
|
417
|
+
]
|
|
@@ -250,7 +250,7 @@ def _should_run(cycle: dict):
|
|
|
250
250
|
milk_yield=milk_yield,
|
|
251
251
|
enteric_factor=enteric_factor,
|
|
252
252
|
enteric_sd=enteric_sd,
|
|
253
|
-
default_values=default_values)
|
|
253
|
+
default_values=';'.join(map(str, default_values)))
|
|
254
254
|
|
|
255
255
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
256
256
|
term_type_animalFeed_complete=is_animalFeed_complete,
|
|
@@ -77,7 +77,9 @@ def _emission(
|
|
|
77
77
|
min: list[float] = None,
|
|
78
78
|
max: list[float] = None,
|
|
79
79
|
statsDefinition: str = None,
|
|
80
|
-
observations: list[int] = None
|
|
80
|
+
observations: list[int] = None,
|
|
81
|
+
start_date: str,
|
|
82
|
+
end_date: str
|
|
81
83
|
) -> dict:
|
|
82
84
|
"""
|
|
83
85
|
Create an emission node based on the provided value and method tier.
|
|
@@ -105,7 +107,9 @@ def _emission(
|
|
|
105
107
|
"max": max,
|
|
106
108
|
"statsDefinition": statsDefinition,
|
|
107
109
|
"observations": observations,
|
|
108
|
-
"
|
|
110
|
+
"startDate": start_date,
|
|
111
|
+
"endDate": end_date,
|
|
112
|
+
"methodTier": method_tier.value,
|
|
109
113
|
}
|
|
110
114
|
emission = _new_emission(term_id, MODEL) | {
|
|
111
115
|
key: value for key, value in update_dict.items() if value
|
|
@@ -141,13 +145,13 @@ def run(cycle: dict) -> list[dict]:
|
|
|
141
145
|
management_change_emission_term_id=_MG_EMISSION_TERM_ID
|
|
142
146
|
)
|
|
143
147
|
|
|
144
|
-
should_run,
|
|
148
|
+
should_run, kwargs, logs = should_run_exec(cycle)
|
|
145
149
|
|
|
146
150
|
for term_id in [_LU_EMISSION_TERM_ID, _MG_EMISSION_TERM_ID]:
|
|
147
151
|
logRequirements(cycle, model=MODEL, term=term_id, **logs)
|
|
148
152
|
logShouldRun(cycle, MODEL, term_id, should_run)
|
|
149
153
|
|
|
150
|
-
return run_exec(
|
|
154
|
+
return run_exec(**kwargs) if should_run else []
|
|
151
155
|
|
|
152
156
|
|
|
153
157
|
def _should_compile_inventory_func(
|
|
@@ -68,7 +68,9 @@ def _emission(
|
|
|
68
68
|
min: list[float] = None,
|
|
69
69
|
max: list[float] = None,
|
|
70
70
|
statsDefinition: str = None,
|
|
71
|
-
observations: list[int] = None
|
|
71
|
+
observations: list[int] = None,
|
|
72
|
+
start_date: str,
|
|
73
|
+
end_date: str
|
|
72
74
|
) -> dict:
|
|
73
75
|
"""
|
|
74
76
|
Create an emission node based on the provided value and method tier.
|
|
@@ -96,6 +98,8 @@ def _emission(
|
|
|
96
98
|
"max": max,
|
|
97
99
|
"statsDefinition": statsDefinition,
|
|
98
100
|
"observations": observations,
|
|
101
|
+
"startDate": start_date,
|
|
102
|
+
"endDate": end_date,
|
|
99
103
|
"methodTier": method_tier.value,
|
|
100
104
|
"depth": _DEPTH_LOWER
|
|
101
105
|
}
|
|
@@ -133,13 +137,13 @@ def run(cycle: dict) -> list[dict]:
|
|
|
133
137
|
management_change_emission_term_id=_MG_EMISSION_TERM_ID
|
|
134
138
|
)
|
|
135
139
|
|
|
136
|
-
should_run,
|
|
140
|
+
should_run, kwargs, logs = should_run_exec(cycle)
|
|
137
141
|
|
|
138
142
|
for term_id in [_LU_EMISSION_TERM_ID, _MG_EMISSION_TERM_ID]:
|
|
139
143
|
logRequirements(cycle, model=MODEL, term=term_id, **logs)
|
|
140
144
|
logShouldRun(cycle, MODEL, term_id, should_run)
|
|
141
145
|
|
|
142
|
-
return run_exec(
|
|
146
|
+
return run_exec(**kwargs) if should_run else []
|
|
143
147
|
|
|
144
148
|
|
|
145
149
|
def _should_run_measurement_func(node: dict) -> bool:
|
|
@@ -3,7 +3,7 @@ Utilities for calculating CO2 emissions based on changes in carbon stocks (e.g.,
|
|
|
3
3
|
`aboveGroundBiomass` and `belowGroundBiomass`).
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from datetime import datetime
|
|
6
|
+
from datetime import datetime, timedelta
|
|
7
7
|
from enum import Enum
|
|
8
8
|
from functools import reduce
|
|
9
9
|
from itertools import product
|
|
@@ -24,7 +24,7 @@ from hestia_earth.models.utils import pairwise
|
|
|
24
24
|
from hestia_earth.models.utils.array_builders import correlated_normal_2d, gen_seed
|
|
25
25
|
from hestia_earth.models.utils.blank_node import (
|
|
26
26
|
_gapfill_datestr, _get_datestr_format, DatestrGapfillMode, DatestrFormat, group_nodes_by_year, node_term_match,
|
|
27
|
-
split_node_by_dates
|
|
27
|
+
split_node_by_dates, validate_start_date_end_date
|
|
28
28
|
)
|
|
29
29
|
from hestia_earth.models.utils.constant import Units, get_atomic_conversion
|
|
30
30
|
from hestia_earth.models.utils.descriptive_stats import calc_descriptive_stats
|
|
@@ -401,11 +401,15 @@ def create_should_run_function(
|
|
|
401
401
|
`(should_run, cycle_id, inventory, logs)`
|
|
402
402
|
"""
|
|
403
403
|
cycle_id = cycle.get("@id")
|
|
404
|
+
cycle_start_date = cycle.get("startDate")
|
|
405
|
+
cycle_end_date = cycle.get("endDate")
|
|
406
|
+
|
|
404
407
|
site = _get_site(cycle)
|
|
405
408
|
cycles = related_cycles(site)
|
|
406
409
|
|
|
407
410
|
carbon_stock_measurements = [
|
|
408
|
-
node for node in site.get("measurements", [])
|
|
411
|
+
node for node in site.get("measurements", [])
|
|
412
|
+
if all([
|
|
409
413
|
node_term_match(node, carbon_stock_term_id),
|
|
410
414
|
_has_valid_array_fields(node),
|
|
411
415
|
_has_valid_dates(node),
|
|
@@ -414,7 +418,10 @@ def create_should_run_function(
|
|
|
414
418
|
])
|
|
415
419
|
]
|
|
416
420
|
|
|
417
|
-
land_cover_nodes =
|
|
421
|
+
land_cover_nodes = [
|
|
422
|
+
node for node in filter_list_term_type(site.get("management", []), TermTermType.LANDCOVER)
|
|
423
|
+
if validate_start_date_end_date(node)
|
|
424
|
+
]
|
|
418
425
|
|
|
419
426
|
seed = gen_seed(site) # All cycles linked to the same site should be consistent
|
|
420
427
|
rng = random.default_rng(seed)
|
|
@@ -445,13 +452,20 @@ def create_should_run_function(
|
|
|
445
452
|
|
|
446
453
|
should_run_ = all([has_valid_inventory, has_consecutive_years])
|
|
447
454
|
|
|
455
|
+
kwargs = {
|
|
456
|
+
"cycle_id": cycle_id,
|
|
457
|
+
"cycle_start_date": cycle_start_date,
|
|
458
|
+
"cycle_end_date": cycle_end_date,
|
|
459
|
+
"inventory": inventory
|
|
460
|
+
}
|
|
461
|
+
|
|
448
462
|
logs = should_compile_logs | inventory_logs | {
|
|
449
463
|
"seed": seed,
|
|
450
464
|
"has_valid_inventory": has_valid_inventory,
|
|
451
465
|
"has_consecutive_years": has_consecutive_years
|
|
452
466
|
}
|
|
453
467
|
|
|
454
|
-
return should_run_,
|
|
468
|
+
return should_run_, kwargs, logs
|
|
455
469
|
|
|
456
470
|
return should_run
|
|
457
471
|
|
|
@@ -1413,7 +1427,7 @@ def create_run_function(
|
|
|
1413
1427
|
|
|
1414
1428
|
return result | update_dict
|
|
1415
1429
|
|
|
1416
|
-
def run(cycle_id: str, inventory: dict) -> list[dict]:
|
|
1430
|
+
def run(cycle_id: str, cycle_start_date: str, cycle_end_date: str, inventory: dict) -> list[dict]:
|
|
1417
1431
|
"""
|
|
1418
1432
|
Calculate emissions for a specific cycle using from a carbon stock change using pre-compiled inventory data.
|
|
1419
1433
|
|
|
@@ -1442,6 +1456,8 @@ def create_run_function(
|
|
|
1442
1456
|
new_emission_func(
|
|
1443
1457
|
term_id=emission_term_id,
|
|
1444
1458
|
method_tier=total_emission.method,
|
|
1459
|
+
start_date=_get_emission_start_date(total_emission, cycle_start_date),
|
|
1460
|
+
end_date=_get_emission_end_date(total_emission, cycle_end_date),
|
|
1445
1461
|
**calc_descriptive_stats(
|
|
1446
1462
|
total_emission.value,
|
|
1447
1463
|
EmissionStatsDefinition.SIMULATED,
|
|
@@ -1451,3 +1467,33 @@ def create_run_function(
|
|
|
1451
1467
|
]
|
|
1452
1468
|
|
|
1453
1469
|
return run
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
def _get_emission_start_date(emission: CarbonStockChangeEmission, cycle_start_date: str) -> str:
|
|
1473
|
+
cycle_datetime = safe_parse_date(_gapfill_datestr(cycle_start_date))
|
|
1474
|
+
emission_datetime = safe_parse_date(emission.start_date)
|
|
1475
|
+
|
|
1476
|
+
should_run = (
|
|
1477
|
+
cycle_datetime and emission_datetime
|
|
1478
|
+
and cycle_datetime <= emission_datetime # If the cycle starts before the emission, add a `startDate`
|
|
1479
|
+
)
|
|
1480
|
+
|
|
1481
|
+
return (
|
|
1482
|
+
(emission_datetime + timedelta(seconds=1)).strftime(DatestrFormat.YEAR_MONTH_DAY.value) if should_run
|
|
1483
|
+
else None
|
|
1484
|
+
)
|
|
1485
|
+
|
|
1486
|
+
|
|
1487
|
+
def _get_emission_end_date(emission: CarbonStockChangeEmission, cycle_end_date: str) -> str:
|
|
1488
|
+
cycle_datetime = safe_parse_date(_gapfill_datestr(cycle_end_date))
|
|
1489
|
+
emission_datetime = safe_parse_date(emission.end_date)
|
|
1490
|
+
|
|
1491
|
+
should_run = (
|
|
1492
|
+
cycle_datetime and emission_datetime
|
|
1493
|
+
and cycle_datetime >= emission_datetime # If the cycle ends after the emission, add an `endDate`
|
|
1494
|
+
)
|
|
1495
|
+
|
|
1496
|
+
return (
|
|
1497
|
+
emission_datetime.strftime(DatestrFormat.YEAR_MONTH_DAY.value) if should_run
|
|
1498
|
+
else None
|
|
1499
|
+
)
|
|
@@ -68,7 +68,9 @@ def _emission(
|
|
|
68
68
|
min: list[float] = None,
|
|
69
69
|
max: list[float] = None,
|
|
70
70
|
statsDefinition: str = None,
|
|
71
|
-
observations: list[int] = None
|
|
71
|
+
observations: list[int] = None,
|
|
72
|
+
start_date: str,
|
|
73
|
+
end_date: str
|
|
72
74
|
) -> dict:
|
|
73
75
|
"""
|
|
74
76
|
Create an emission node based on the provided value and method tier.
|
|
@@ -96,6 +98,8 @@ def _emission(
|
|
|
96
98
|
"max": max,
|
|
97
99
|
"statsDefinition": statsDefinition,
|
|
98
100
|
"observations": observations,
|
|
101
|
+
"startDate": start_date,
|
|
102
|
+
"endDate": end_date,
|
|
99
103
|
"methodTier": method_tier.value,
|
|
100
104
|
"depth": _DEPTH_LOWER
|
|
101
105
|
}
|
|
@@ -133,13 +137,13 @@ def run(cycle: dict) -> list[dict]:
|
|
|
133
137
|
management_change_emission_term_id=_MG_EMISSION_TERM_ID
|
|
134
138
|
)
|
|
135
139
|
|
|
136
|
-
should_run,
|
|
140
|
+
should_run, kwargs, logs = should_run_exec(cycle)
|
|
137
141
|
|
|
138
142
|
for term_id in [_LU_EMISSION_TERM_ID, _MG_EMISSION_TERM_ID]:
|
|
139
143
|
logRequirements(cycle, model=MODEL, term=term_id, **logs)
|
|
140
144
|
logShouldRun(cycle, MODEL, term_id, should_run)
|
|
141
145
|
|
|
142
|
-
return run_exec(
|
|
146
|
+
return run_exec(**kwargs) if should_run else []
|
|
143
147
|
|
|
144
148
|
|
|
145
149
|
def _should_run_measurement_func(node: dict) -> bool:
|
|
@@ -10,7 +10,12 @@ from . import MODEL
|
|
|
10
10
|
|
|
11
11
|
REQUIREMENTS = {
|
|
12
12
|
"Cycle": {
|
|
13
|
-
"
|
|
13
|
+
"or": {
|
|
14
|
+
"completeness.excreta": "True",
|
|
15
|
+
"inputs": [
|
|
16
|
+
{"@type": "Input", "term.termType": "excreta", "units": "kg N"}
|
|
17
|
+
]
|
|
18
|
+
},
|
|
14
19
|
"practices": [
|
|
15
20
|
{"@type": "Practice", "value": "", "term.termType": "excretaManagement"}
|
|
16
21
|
]
|
|
@@ -36,26 +41,26 @@ def _emission(value: float):
|
|
|
36
41
|
return emission
|
|
37
42
|
|
|
38
43
|
|
|
39
|
-
def _run(
|
|
40
|
-
value = N2O_N_EF *
|
|
44
|
+
def _run(N_total: float, N2O_N_EF: float):
|
|
45
|
+
value = (N2O_N_EF or 0) * (N_total or 0) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
|
|
41
46
|
return [_emission(value)]
|
|
42
47
|
|
|
43
48
|
|
|
44
49
|
def _should_run(cycle: dict):
|
|
45
|
-
|
|
50
|
+
N_total = total_excreta(cycle.get('inputs', []))
|
|
46
51
|
N2O_N_EF = get_lookup_factor(cycle.get('practices', []), LOOKUPS['excretaManagement'])
|
|
47
52
|
term_type_complete = _is_term_type_complete(cycle, TermTermType.EXCRETA)
|
|
48
53
|
|
|
49
54
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
50
|
-
|
|
55
|
+
N_total=N_total,
|
|
51
56
|
N2O_N_EF=N2O_N_EF,
|
|
52
57
|
term_type_excreta_complete=term_type_complete)
|
|
53
58
|
|
|
54
|
-
should_run = all([
|
|
59
|
+
should_run = all([N_total, N2O_N_EF]) or all([not N_total, term_type_complete])
|
|
55
60
|
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
|
56
|
-
return should_run,
|
|
61
|
+
return should_run, N_total, N2O_N_EF
|
|
57
62
|
|
|
58
63
|
|
|
59
64
|
def run(cycle: dict):
|
|
60
|
-
should_run,
|
|
61
|
-
return _run(
|
|
65
|
+
should_run, N_total, N2O_N_EF = _should_run(cycle)
|
|
66
|
+
return _run(N_total, N2O_N_EF) if should_run else []
|
|
@@ -24,7 +24,7 @@ from hestia_earth.utils.blank_node import get_node_value
|
|
|
24
24
|
from hestia_earth.models.utils.array_builders import gen_seed
|
|
25
25
|
from hestia_earth.models.utils.blank_node import (
|
|
26
26
|
cumulative_nodes_match, cumulative_nodes_lookup_match, cumulative_nodes_term_match,
|
|
27
|
-
node_lookup_match, node_term_match, group_nodes_by_year
|
|
27
|
+
node_lookup_match, node_term_match, group_nodes_by_year, validate_start_date_end_date
|
|
28
28
|
)
|
|
29
29
|
from hestia_earth.models.utils.ecoClimateZone import EcoClimateZone, get_eco_climate_zone_value
|
|
30
30
|
from hestia_earth.models.utils.descriptive_stats import calc_descriptive_stats
|
|
@@ -1209,8 +1209,14 @@ def _assign_ipcc_land_use_category(
|
|
|
1209
1209
|
DECISION_TREE = _LAND_USE_CATEGORY_DECISION_TREE
|
|
1210
1210
|
DEFAULT = IpccLandUseCategory.OTHER
|
|
1211
1211
|
|
|
1212
|
-
land_cover_nodes =
|
|
1213
|
-
|
|
1212
|
+
land_cover_nodes = [
|
|
1213
|
+
node for node in filter_list_term_type(management_nodes, [TermTermType.LANDCOVER])
|
|
1214
|
+
if validate_start_date_end_date(node)
|
|
1215
|
+
]
|
|
1216
|
+
water_regime_nodes = [
|
|
1217
|
+
node for node in filter_list_term_type(management_nodes, [TermTermType.WATERREGIME])
|
|
1218
|
+
if validate_start_date_end_date(node)
|
|
1219
|
+
]
|
|
1214
1220
|
|
|
1215
1221
|
has_irrigation = check_irrigation(water_regime_nodes)
|
|
1216
1222
|
has_upland_rice = _has_upland_rice(land_cover_nodes)
|
|
@@ -1271,8 +1271,7 @@ def _get_irrigated_monthly(year: int, cycles: list[dict]) -> list[bool]:
|
|
|
1271
1271
|
irrigation_nodes = non_empty_list(flatten([
|
|
1272
1272
|
[
|
|
1273
1273
|
{
|
|
1274
|
-
|
|
1275
|
-
"endDate": cycle.get("endDate"),
|
|
1274
|
+
**{key: cycle.get(key) for key in ["startDate", "endDate"] if cycle.get(key)},
|
|
1276
1275
|
**node
|
|
1277
1276
|
} for node in cycle.get("practices", [])
|
|
1278
1277
|
] for cycle in cycles
|
|
@@ -94,6 +94,10 @@ def _model_value(term_id: str, products: list):
|
|
|
94
94
|
return list_average(values) if len(values) > 0 else 0
|
|
95
95
|
|
|
96
96
|
|
|
97
|
+
def _remaining_model_value(products: list):
|
|
98
|
+
return list_sum(find_term_match(products, REMAINING_MODEL).get('value', []), 0)
|
|
99
|
+
|
|
100
|
+
|
|
97
101
|
def _run(cycle: dict, total_values: list):
|
|
98
102
|
products = cycle.get('products', [])
|
|
99
103
|
total_value = list_average(total_values)
|
|
@@ -126,7 +130,7 @@ def _run(cycle: dict, total_values: list):
|
|
|
126
130
|
|
|
127
131
|
return values + [
|
|
128
132
|
# whatever remains is "left on field"
|
|
129
|
-
_product(REMAINING_MODEL, remaining_value)
|
|
133
|
+
_product(REMAINING_MODEL, remaining_value + _remaining_model_value(products))
|
|
130
134
|
] if remaining_value > 0 else values
|
|
131
135
|
|
|
132
136
|
|
|
@@ -29,5 +29,5 @@ def run(impact_assessment: dict):
|
|
|
29
29
|
value = impact_emission_lookup_value(MODEL, TERM_ID, impact_assessment, LOOKUPS['emission'])
|
|
30
30
|
logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
|
|
31
31
|
value=value)
|
|
32
|
-
logShouldRun(impact_assessment, MODEL, TERM_ID,
|
|
33
|
-
return _indicator(value)
|
|
32
|
+
logShouldRun(impact_assessment, MODEL, TERM_ID, value is not None)
|
|
33
|
+
return _indicator(value) if value is not None else None
|