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
|
@@ -14,18 +14,19 @@ When nodes are chronologically consecutive with "% area" or "boolean" units and
|
|
|
14
14
|
condensed into a single node to aid readability.
|
|
15
15
|
"""
|
|
16
16
|
from functools import reduce
|
|
17
|
-
|
|
18
|
-
from hestia_earth.
|
|
19
|
-
from hestia_earth.utils.
|
|
20
|
-
from hestia_earth.utils.model import filter_list_term_type, linked_node
|
|
21
|
-
from hestia_earth.utils.tools import safe_parse_float, flatten, non_empty_list
|
|
17
|
+
from hestia_earth.schema import TermTermType, SiteSiteType
|
|
18
|
+
from hestia_earth.utils.model import filter_list_term_type
|
|
19
|
+
from hestia_earth.utils.tools import safe_parse_float, flatten
|
|
22
20
|
from hestia_earth.utils.blank_node import get_node_value
|
|
23
21
|
|
|
24
|
-
from hestia_earth.models.log import logRequirements, logShouldRun,
|
|
22
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
23
|
+
from hestia_earth.models.utils import _include
|
|
24
|
+
from hestia_earth.models.utils.management import _new_management
|
|
25
25
|
from hestia_earth.models.utils.term import get_lookup_value
|
|
26
26
|
from hestia_earth.models.utils.blank_node import condense_nodes
|
|
27
|
-
from hestia_earth.models.utils.site import
|
|
28
|
-
|
|
27
|
+
from hestia_earth.models.utils.site import (
|
|
28
|
+
related_cycles, get_land_cover_term_id as get_landCover_term_id_from_site_type
|
|
29
|
+
)
|
|
29
30
|
from . import MODEL
|
|
30
31
|
|
|
31
32
|
REQUIREMENTS = {
|
|
@@ -89,36 +90,37 @@ LOOKUPS = {
|
|
|
89
90
|
"landUseManagement": "GAP_FILL_TO_MANAGEMENT"
|
|
90
91
|
}
|
|
91
92
|
MODEL_KEY = 'management'
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
|
|
94
|
+
_LAND_COVER_KEY = LOOKUPS['crop'][0]
|
|
95
|
+
_ANIMAL_MANURE_USED_TERM_ID = "animalManureUsed"
|
|
96
|
+
_INORGANIC_NITROGEN_FERTILISER_USED_TERM_ID = "inorganicNitrogenFertiliserUsed"
|
|
97
|
+
_ORGANIC_FERTILISER_USED_TERM_ID = "organicFertiliserUsed"
|
|
98
|
+
_AMENDMENT_INCREASING_C_USED_TERM_ID = "amendmentIncreasingSoilCarbonUsed"
|
|
99
|
+
_INPUT_RULES = {
|
|
98
100
|
TermTermType.INORGANICFERTILISER.value: (
|
|
99
101
|
(
|
|
100
102
|
TermTermType.INORGANICFERTILISER.value, # Lookup column
|
|
101
103
|
lambda x: safe_parse_float(x) > 0, # Condition
|
|
102
|
-
|
|
104
|
+
_INORGANIC_NITROGEN_FERTILISER_USED_TERM_ID # New term.
|
|
103
105
|
),
|
|
104
106
|
),
|
|
105
107
|
TermTermType.SOILAMENDMENT.value: (
|
|
106
108
|
(
|
|
107
109
|
TermTermType.SOILAMENDMENT.value,
|
|
108
|
-
lambda x: x is True,
|
|
109
|
-
|
|
110
|
+
lambda x: bool(x) is True,
|
|
111
|
+
_AMENDMENT_INCREASING_C_USED_TERM_ID
|
|
110
112
|
),
|
|
111
113
|
),
|
|
112
114
|
TermTermType.ORGANICFERTILISER.value: (
|
|
113
115
|
(
|
|
114
116
|
TermTermType.SOILAMENDMENT.value,
|
|
115
|
-
lambda x: x is True,
|
|
116
|
-
|
|
117
|
+
lambda x: bool(x) is True,
|
|
118
|
+
_ORGANIC_FERTILISER_USED_TERM_ID
|
|
117
119
|
),
|
|
118
120
|
(
|
|
119
121
|
TermTermType.ORGANICFERTILISER.value,
|
|
120
|
-
lambda x: x is True,
|
|
121
|
-
|
|
122
|
+
lambda x: bool(x) is True,
|
|
123
|
+
_ANIMAL_MANURE_USED_TERM_ID
|
|
122
124
|
)
|
|
123
125
|
)
|
|
124
126
|
}
|
|
@@ -128,15 +130,28 @@ _SKIP_LAND_COVER_SITE_TYPES = [
|
|
|
128
130
|
|
|
129
131
|
|
|
130
132
|
def management(data: dict):
|
|
131
|
-
node =
|
|
132
|
-
|
|
133
|
+
node = _new_management(data.get('id'))
|
|
134
|
+
node['value'] = data['value']
|
|
135
|
+
node['endDate'] = data['endDate']
|
|
136
|
+
if data.get('startDate'):
|
|
137
|
+
node['startDate'] = data['startDate']
|
|
138
|
+
if data.get('properties'):
|
|
139
|
+
node['properties'] = data['properties']
|
|
140
|
+
return node
|
|
133
141
|
|
|
134
142
|
|
|
135
|
-
def
|
|
136
|
-
return
|
|
143
|
+
def _map_to_value(value: dict):
|
|
144
|
+
return {
|
|
145
|
+
'id': value.get('term', {}).get('@id'),
|
|
146
|
+
'value': value.get('value'),
|
|
147
|
+
'startDate': value.get('startDate'),
|
|
148
|
+
'endDate': value.get('endDate'),
|
|
149
|
+
'properties': value.get('properties')
|
|
150
|
+
}
|
|
137
151
|
|
|
138
152
|
|
|
139
|
-
def
|
|
153
|
+
def _extract_node_value(node: dict) -> dict:
|
|
154
|
+
return node | {'value': get_node_value(node)}
|
|
140
155
|
|
|
141
156
|
|
|
142
157
|
def _default_dates(cycle: dict, values: list):
|
|
@@ -155,148 +170,121 @@ def _copy_item_if_exists(source: dict, keys: list[str] = None, dest: dict = None
|
|
|
155
170
|
|
|
156
171
|
|
|
157
172
|
def _get_landCover_term_id(product: dict) -> str:
|
|
158
|
-
|
|
173
|
+
term = product.get('term', {})
|
|
174
|
+
value = get_lookup_value(term, _LAND_COVER_KEY, model=MODEL, term=term.get('@id'), model_key=MODEL_KEY)
|
|
159
175
|
return value.split(';')[0] if value else None
|
|
160
176
|
|
|
161
177
|
|
|
162
178
|
def _get_relevant_items(
|
|
163
|
-
|
|
179
|
+
cycle: dict, item_name: str, relevant_terms: list, date_fill: callable = _default_dates
|
|
164
180
|
):
|
|
165
181
|
"""
|
|
166
182
|
Get items from the list of cycles with any of the relevant terms.
|
|
167
183
|
Also adds dates if missing.
|
|
168
184
|
"""
|
|
169
185
|
return [
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
for item in date_fill(cycle=cycle, values=filter_list_term_type(cycle.get(item_name, []), relevant_terms))
|
|
173
|
-
]
|
|
174
|
-
for cycle in cycles
|
|
186
|
+
item
|
|
187
|
+
for item in date_fill(cycle=cycle, values=filter_list_term_type(cycle.get(item_name, []), relevant_terms))
|
|
175
188
|
]
|
|
176
189
|
|
|
177
190
|
|
|
178
|
-
def
|
|
179
|
-
get_lookup_value(term, column, model_key=MODEL_KEY, land_cover_key=LAND_COVER_KEY)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
def _data_from_input(cycle: dict, term_id: str) -> dict:
|
|
183
|
-
return {
|
|
184
|
-
"term": {
|
|
185
|
-
"@type": "Term",
|
|
186
|
-
"@id": term_id,
|
|
187
|
-
"termType": "landUseManagement"
|
|
188
|
-
},
|
|
189
|
-
"value": True,
|
|
190
|
-
"startDate": cycle["startDate"],
|
|
191
|
-
"endDate": cycle["endDate"]
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def _process_rule(cycle, term, term_type) -> list:
|
|
191
|
+
def _process_rule(node: dict, term: dict) -> list:
|
|
196
192
|
relevant_terms = []
|
|
197
|
-
for column, condition, new_term in
|
|
198
|
-
lookup_result =
|
|
193
|
+
for column, condition, new_term in _INPUT_RULES[term.get('termType')]:
|
|
194
|
+
lookup_result = get_lookup_value(term, LOOKUPS[column], model=MODEL, term=term.get('@id'), model_key=MODEL_KEY)
|
|
199
195
|
|
|
200
196
|
if condition(lookup_result):
|
|
201
|
-
relevant_terms.append(
|
|
197
|
+
relevant_terms.append(node | {'id': new_term})
|
|
202
198
|
|
|
203
199
|
return relevant_terms
|
|
204
200
|
|
|
205
201
|
|
|
206
|
-
def
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
]
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
cycles=cycles,
|
|
202
|
+
def _run_from_inputs(site: dict, cycle: dict) -> list:
|
|
203
|
+
inputs = flatten([
|
|
204
|
+
_process_rule(node={
|
|
205
|
+
'value': True,
|
|
206
|
+
'startDate': cycle.get('startDate'),
|
|
207
|
+
'endDate': cycle.get('endDate')
|
|
208
|
+
}, term=input.get('term'))
|
|
209
|
+
for input in cycle.get('inputs', [])
|
|
210
|
+
if input.get('term', {}).get('termType') in _INPUT_RULES
|
|
211
|
+
])
|
|
212
|
+
return inputs
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _run_from_siteType(site: dict, cycle: dict):
|
|
216
|
+
site_type = site.get('siteType')
|
|
217
|
+
site_type_id = get_landCover_term_id_from_site_type(site_type) if site_type not in _SKIP_LAND_COVER_SITE_TYPES \
|
|
218
|
+
else None
|
|
219
|
+
|
|
220
|
+
should_run = all([site_type_id])
|
|
221
|
+
return [{
|
|
222
|
+
'id': site_type_id,
|
|
223
|
+
'value': 100,
|
|
224
|
+
'startDate': cycle.get('startDate'),
|
|
225
|
+
'endDate': cycle.get('endDate')
|
|
226
|
+
}] if should_run else []
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _run_from_landCover(cycle: dict):
|
|
230
|
+
products = _get_relevant_items(
|
|
231
|
+
cycle=cycle,
|
|
237
232
|
item_name="products",
|
|
238
233
|
relevant_terms=[TermTermType.LANDCOVER]
|
|
239
|
-
)
|
|
240
|
-
|
|
241
|
-
_extract_node_value(
|
|
234
|
+
)
|
|
235
|
+
products = [
|
|
236
|
+
_map_to_value(_extract_node_value(
|
|
242
237
|
_include(
|
|
243
238
|
value=product,
|
|
244
239
|
keys=["term", "value", "startDate", "endDate", "properties"]
|
|
245
240
|
)
|
|
246
|
-
) for product in
|
|
241
|
+
)) for product in products
|
|
247
242
|
]
|
|
243
|
+
return products
|
|
244
|
+
|
|
248
245
|
|
|
249
|
-
|
|
250
|
-
|
|
246
|
+
def _run_from_crop_forage(cycle: dict):
|
|
247
|
+
products = _get_relevant_items(
|
|
248
|
+
cycle=cycle,
|
|
251
249
|
item_name="products",
|
|
252
250
|
relevant_terms=[TermTermType.CROP, TermTermType.FORAGE],
|
|
253
251
|
date_fill=_dates_from_current_cycle
|
|
254
252
|
)
|
|
255
|
-
|
|
256
|
-
|
|
253
|
+
products = list(filter(_get_landCover_term_id, products))
|
|
254
|
+
products = [
|
|
255
|
+
_map_to_value(_copy_item_if_exists(
|
|
257
256
|
source=product,
|
|
258
257
|
keys=["startDate", "endDate", "properties"],
|
|
259
258
|
dest={
|
|
260
|
-
"term":
|
|
261
|
-
"value": round(100 / len(
|
|
259
|
+
"term": {'@id': _get_landCover_term_id(product)},
|
|
260
|
+
"value": round(100 / len(products), 2)
|
|
262
261
|
}
|
|
263
|
-
)
|
|
264
|
-
for
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
non_empty_list(flatten([[cycle.get('startDate'), cycle.get('endDate')] for cycle in cycles]))
|
|
269
|
-
))) if site_type not in _SKIP_LAND_COVER_SITE_TYPES else []
|
|
270
|
-
site_type_id = get_landCover_term_id_from_site_type(site_type) if site_type else None
|
|
271
|
-
site_type_term = download_hestia(site_type_id) if all([len(dates) >= 2, site_type_id]) else None
|
|
272
|
-
products_site_type = [{
|
|
273
|
-
"term": linked_node(site_type_term),
|
|
274
|
-
"value": 100,
|
|
275
|
-
"startDate": dates[0],
|
|
276
|
-
"endDate": dates[-1]
|
|
277
|
-
}] if site_type_term else []
|
|
278
|
-
|
|
279
|
-
return products_site_type, products_crop_forage, products_land_cover
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
def _should_run(site: dict):
|
|
283
|
-
cycles = related_cycles(site)
|
|
262
|
+
))
|
|
263
|
+
for product in products
|
|
264
|
+
]
|
|
265
|
+
return products
|
|
266
|
+
|
|
284
267
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
268
|
+
def _has_gap_fill_to_management_set(practice: dict):
|
|
269
|
+
"""
|
|
270
|
+
Include only landUseManagement practices where GAP_FILL_TO_MANAGEMENT = True
|
|
271
|
+
"""
|
|
272
|
+
term = practice.get('term', {})
|
|
273
|
+
return (
|
|
274
|
+
term.get('termType') != TermTermType.LANDUSEMANAGEMENT.value or
|
|
275
|
+
get_lookup_value(lookup_term=term, column=LOOKUPS["landUseManagement"])
|
|
288
276
|
)
|
|
289
|
-
all_products = products_land_cover + products_crop_forage + products_animal
|
|
290
|
-
all_products = condense_nodes(all_products)
|
|
291
277
|
|
|
278
|
+
|
|
279
|
+
def _run_from_practices(cycle: dict):
|
|
292
280
|
practices = [
|
|
293
281
|
_extract_node_value(
|
|
294
282
|
_include(
|
|
295
283
|
value=practice,
|
|
296
284
|
keys=["term", "value", "startDate", "endDate"]
|
|
297
285
|
)
|
|
298
|
-
) for practice in
|
|
299
|
-
|
|
286
|
+
) for practice in _get_relevant_items(
|
|
287
|
+
cycle=cycle,
|
|
300
288
|
item_name="practices",
|
|
301
289
|
relevant_terms=[
|
|
302
290
|
TermTermType.WATERREGIME,
|
|
@@ -305,28 +293,38 @@ def _should_run(site: dict):
|
|
|
305
293
|
TermTermType.LANDUSEMANAGEMENT,
|
|
306
294
|
TermTermType.SYSTEM
|
|
307
295
|
]
|
|
308
|
-
)
|
|
296
|
+
)
|
|
297
|
+
]
|
|
298
|
+
practices = list(map(_map_to_value, filter(_has_gap_fill_to_management_set, practices)))
|
|
299
|
+
return practices
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def _run_cycle(site: dict, cycle: dict):
|
|
303
|
+
inputs = _run_from_inputs(site, cycle)
|
|
304
|
+
products = _run_from_landCover(cycle) + _run_from_crop_forage(cycle)
|
|
305
|
+
site_types = _run_from_siteType(site, cycle)
|
|
306
|
+
practices = _run_from_practices(cycle)
|
|
307
|
+
return [
|
|
308
|
+
node | {'cycle-id': cycle.get('@id')}
|
|
309
|
+
for node in inputs + products + site_types + practices
|
|
309
310
|
]
|
|
310
|
-
practices = _has_gap_fill_to_management_set(practices)
|
|
311
|
-
practices = condense_nodes(practices)
|
|
312
|
-
|
|
313
|
-
relevant_inputs = _get_relevant_inputs(cycles)
|
|
314
|
-
logRequirements(
|
|
315
|
-
site,
|
|
316
|
-
model=MODEL,
|
|
317
|
-
term=None,
|
|
318
|
-
model_key=MODEL_KEY,
|
|
319
|
-
products_crop_forage_ids=log_blank_nodes_id(products_crop_forage),
|
|
320
|
-
products_land_cover_ids=log_blank_nodes_id(products_land_cover),
|
|
321
|
-
products_animal=log_blank_nodes_id(products_animal),
|
|
322
|
-
practice_ids=log_blank_nodes_id(practices),
|
|
323
|
-
inputs=log_blank_nodes_id(relevant_inputs)
|
|
324
|
-
)
|
|
325
|
-
should_run = any(all_products + practices + relevant_inputs)
|
|
326
|
-
logShouldRun(site, MODEL, None, should_run=should_run, model_key=MODEL_KEY)
|
|
327
|
-
return should_run, all_products, practices, relevant_inputs
|
|
328
311
|
|
|
329
312
|
|
|
330
313
|
def run(site: dict):
|
|
331
|
-
|
|
332
|
-
|
|
314
|
+
cycles = related_cycles(site)
|
|
315
|
+
nodes = flatten([_run_cycle(site, cycle) for cycle in cycles])
|
|
316
|
+
|
|
317
|
+
# group nodes with same `id` to display as a single log per node
|
|
318
|
+
grouped_nodes = reduce(lambda p, c: p | {c['id']: p.get(c['id'], []) + [c]}, nodes, {})
|
|
319
|
+
for id, values in grouped_nodes.items():
|
|
320
|
+
logRequirements(
|
|
321
|
+
site,
|
|
322
|
+
model=MODEL,
|
|
323
|
+
term=id,
|
|
324
|
+
model_key=MODEL_KEY,
|
|
325
|
+
details=log_as_table(values, ignore_keys=['id', 'properties']),
|
|
326
|
+
)
|
|
327
|
+
logShouldRun(site, MODEL, id, True, model_key=MODEL_KEY)
|
|
328
|
+
|
|
329
|
+
management_nodes = condense_nodes(list(map(management, nodes)))
|
|
330
|
+
return management_nodes
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_crop_residue_decomposition_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .n2OToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_excreta_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .n2OToAirSoilFlux_utils import _get_value, _should_run
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total
|
|
7
|
-
from .
|
|
7
|
+
from .n2OToAirSoilFlux_utils import _get_value, _should_run
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.cycle import get_organic_fertiliser_N_total
|
|
7
|
-
from .
|
|
7
|
+
from .n2OToAirSoilFlux_utils import _get_value, _should_run
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_crop_residue_decomposition_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .noxToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_excreta_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .noxToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .noxToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_organic_fertiliser_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .noxToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirCropResidueDecomposition.py
CHANGED
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_crop_residue_decomposition_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .noxToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_excreta_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .noxToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .noxToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -4,7 +4,7 @@ from hestia_earth.models.log import logRequirements, logShouldRun
|
|
|
4
4
|
from hestia_earth.models.utils.cycle import get_organic_fertiliser_N_total
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
6
|
from hestia_earth.models.utils.emission import _new_emission
|
|
7
|
-
from .
|
|
7
|
+
from .noxToAirSoilFlux_utils import _should_run, _get_value
|
|
8
8
|
from . import MODEL
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from hestia_earth.models.utils.indicator import _new_indicator
|
|
2
|
-
from hestia_earth.models.utils.pesticideAI import impact_lookup_value
|
|
2
|
+
from hestia_earth.models.utils.pesticideAI import impact_lookup_value
|
|
3
3
|
from . import MODEL
|
|
4
4
|
|
|
5
5
|
REQUIREMENTS = {
|
|
@@ -30,5 +30,4 @@ def _indicator(value: float):
|
|
|
30
30
|
|
|
31
31
|
def run(impact_assessment: dict):
|
|
32
32
|
value = impact_lookup_value(MODEL, TERM_ID, impact_assessment, LOOKUPS['pesticideAI'])
|
|
33
|
-
|
|
34
|
-
return _indicator(value) if should_run else None
|
|
33
|
+
return _indicator(value) if value is not None else None
|
|
@@ -29,7 +29,10 @@ def cached_value(node: dict, key: str = None, default=None):
|
|
|
29
29
|
def _term_id(term): return term.get('@id') if isinstance(term, dict) else term
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def _omit(values: dict, keys: list): return {k: v for k, v in values.items() if k not in keys}
|
|
32
|
+
def _omit(values: dict, keys: list) -> dict: return {k: v for k, v in values.items() if k not in keys}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _include(value: dict, keys: list) -> dict: return {k: v for k, v in value.items() if k in keys}
|
|
33
36
|
|
|
34
37
|
|
|
35
38
|
def _include_model(node: dict, term_id: str):
|
|
@@ -280,9 +280,9 @@ def get_total_value_converted_with_min_ratio(
|
|
|
280
280
|
) for blank_node in blank_nodes
|
|
281
281
|
]
|
|
282
282
|
value_logs = log_as_table([{
|
|
283
|
-
'id': term_id,
|
|
284
|
-
'value': value,
|
|
285
|
-
prop_id: prop_value
|
|
283
|
+
'node-id': term_id,
|
|
284
|
+
'node-value': value,
|
|
285
|
+
f"{prop_id}-value": prop_value
|
|
286
286
|
} for term_id, value, prop_value in values])
|
|
287
287
|
|
|
288
288
|
total_value = list_sum([value for term_id, value, prop_value in values])
|
|
@@ -746,7 +746,7 @@ DATESTR_GAPFILL_MODE_TO_GAPFILL_FUNCTION = {
|
|
|
746
746
|
|
|
747
747
|
def _gapfill_datestr(datestr: str, mode: DatestrGapfillMode = DatestrGapfillMode.START) -> str:
|
|
748
748
|
"""
|
|
749
|
-
Gapfill incomplete datestrs and returns them in the format `YYYY-MM-DDTHH:
|
|
749
|
+
Gapfill incomplete datestrs and returns them in the format `YYYY-MM-DDTHH:mm:ss`.
|
|
750
750
|
"""
|
|
751
751
|
VALID_DATE_FORMATS = {
|
|
752
752
|
DatestrFormat.YEAR, DatestrFormat.YEAR_MONTH, DatestrFormat.YEAR_MONTH_DAY
|
|
@@ -768,7 +768,7 @@ def _datetime_range_duration(range: DatetimeRange, add_second=False) -> float:
|
|
|
768
768
|
"""
|
|
769
769
|
Determine the length of a `DatetimeRange` in seconds.
|
|
770
770
|
|
|
771
|
-
Option to `add_second` to account for 1 second between 23:59:59 and 00:00:00
|
|
771
|
+
Option to `add_second` to account for 1 second between 23:59:59 and 00:00:00
|
|
772
772
|
"""
|
|
773
773
|
return (range.end - range.start).total_seconds() + int(add_second)
|
|
774
774
|
|
|
@@ -779,7 +779,7 @@ def _calc_datetime_range_intersection_duration(
|
|
|
779
779
|
"""
|
|
780
780
|
Determine the length of a `DatetimeRange` in seconds.
|
|
781
781
|
|
|
782
|
-
Option to `add_second` to account for 1 second between 23:59:59 and 00:00:00
|
|
782
|
+
Option to `add_second` to account for 1 second between 23:59:59 and 00:00:00
|
|
783
783
|
"""
|
|
784
784
|
latest_start = max(range_a.start, range_b.start)
|
|
785
785
|
earliest_end = min(range_a.end, range_b.end)
|
|
@@ -793,7 +793,7 @@ def _calc_datetime_range_intersection_duration(
|
|
|
793
793
|
|
|
794
794
|
# if less than 0 the ranges do not intersect, so return 0.
|
|
795
795
|
return (
|
|
796
|
-
_datetime_range_duration(intersection_range
|
|
796
|
+
_datetime_range_duration(intersection_range, add_second=add_second)
|
|
797
797
|
if duration > 0 else 0
|
|
798
798
|
)
|
|
799
799
|
|
|
@@ -829,7 +829,10 @@ def _should_run_node_by_end_date(node: dict) -> bool:
|
|
|
829
829
|
"""
|
|
830
830
|
Validate nodes for `group_nodes_by_year` using the "startDate" and "endDate" fields.
|
|
831
831
|
"""
|
|
832
|
-
return
|
|
832
|
+
return (
|
|
833
|
+
_get_datestr_format(node.get("endDate")) in VALID_DATE_FORMATS_GROUP_NODES_BY_YEAR
|
|
834
|
+
and validate_start_date_end_date(node)
|
|
835
|
+
)
|
|
833
836
|
|
|
834
837
|
|
|
835
838
|
def _should_run_node_by_dates(node: dict) -> bool:
|
|
@@ -927,8 +930,8 @@ def _build_time_fraction_dict(
|
|
|
927
930
|
node_datetime_range, group_datetime_range, add_second=True
|
|
928
931
|
)
|
|
929
932
|
|
|
930
|
-
fraction_of_group_duration = intersection_duration / group_duration
|
|
931
|
-
fraction_of_node_duration = intersection_duration / node_duration
|
|
933
|
+
fraction_of_group_duration = intersection_duration / group_duration if group_duration > 0 else 0
|
|
934
|
+
fraction_of_node_duration = intersection_duration / node_duration if node_duration > 0 else 0
|
|
932
935
|
|
|
933
936
|
return {
|
|
934
937
|
"fraction_of_group_duration": fraction_of_group_duration,
|
|
@@ -1283,10 +1286,19 @@ def _group_nodes_by_consecutive_dates(nodes: list):
|
|
|
1283
1286
|
|
|
1284
1287
|
def _node_from_group(nodes: list):
|
|
1285
1288
|
# `nodes` contain list with consecutive dates
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1289
|
+
# if all nodes have the same dates, sum up the values
|
|
1290
|
+
same_startDate = len(set([n.get('startDate') for n in nodes])) == 1
|
|
1291
|
+
same_endDate = len(set([n.get('endDate') for n in nodes])) == 1
|
|
1292
|
+
total_value = list_sum(flatten([n.get('value', []) for n in nodes]))
|
|
1293
|
+
return nodes[0] if len(nodes) == 1 else (
|
|
1294
|
+
nodes[0] | {
|
|
1295
|
+
'value': [total_value] if isinstance(nodes[0]['value'], list) else total_value
|
|
1296
|
+
} if all([same_startDate, same_endDate])
|
|
1297
|
+
else nodes[0] | {
|
|
1298
|
+
'startDate': min(n.get('startDate') for n in nodes),
|
|
1299
|
+
'endDate': max(n.get('endDate') for n in nodes)
|
|
1300
|
+
}
|
|
1301
|
+
)
|
|
1290
1302
|
|
|
1291
1303
|
|
|
1292
1304
|
def _condense_nodes(nodes: list):
|
|
@@ -1457,3 +1469,11 @@ def convert_unit_properties(node_value: Union[int, float], node: dict, dest_unit
|
|
|
1457
1469
|
lambda value, conversion_property_field: _convert_via_property(node, value, conversion_property_field),
|
|
1458
1470
|
conversions, node_value
|
|
1459
1471
|
) if conversions else None
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
def validate_start_date_end_date(node: dict) -> bool:
|
|
1475
|
+
"""Return `True` if `node.startDate` is before `node.endDate`, `False` if otherwise."""
|
|
1476
|
+
start_date = _gapfill_datestr(node.get("startDate", OLDEST_DATE))
|
|
1477
|
+
end_date = _gapfill_datestr(node.get("endDate", OLDEST_DATE), DatestrGapfillMode.END)
|
|
1478
|
+
|
|
1479
|
+
return safe_parse_date(start_date) < safe_parse_date(end_date)
|