hestia-earth-models 0.69.1__py3-none-any.whl → 0.70.1__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/cache_sites.py +3 -2
- hestia_earth/models/cml2001Baseline/abioticResourceDepletionFossilFuels.py +2 -1
- hestia_earth/models/cml2001Baseline/abioticResourceDepletionMineralsAndMetals.py +3 -2
- hestia_earth/models/config/Cycle.json +82 -60
- hestia_earth/models/config/ImpactAssessment.json +12 -4
- hestia_earth/models/config/Site.json +33 -22
- hestia_earth/models/cycle/animal/input/hestiaAggregatedData.py +1 -1
- hestia_earth/models/cycle/animal/input/properties.py +1 -1
- hestia_earth/models/cycle/cycleDuration.py +2 -2
- hestia_earth/models/cycle/input/hestiaAggregatedData.py +12 -14
- hestia_earth/models/cycle/input/properties.py +1 -1
- hestia_earth/models/cycle/siteDuration.py +3 -3
- 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/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +1 -1
- hestia_earth/models/geospatialDatabase/croppingIntensity.py +4 -4
- hestia_earth/models/geospatialDatabase/longFallowRatio.py +4 -4
- hestia_earth/models/geospatialDatabase/region.py +3 -2
- hestia_earth/models/geospatialDatabase/utils.py +6 -5
- hestia_earth/models/haversineFormula/transport/distance.py +5 -4
- hestia_earth/models/{koble2014 → hestia}/aboveGroundCropResidue.py +4 -5
- hestia_earth/models/{cycle → hestia}/aboveGroundCropResidueTotal.py +2 -2
- 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 +2 -2
- hestia_earth/models/{cycle → hestia}/excretaKgMass.py +7 -2
- 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 +31 -27
- hestia_earth/models/hestia/landTransformation100YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hestia/landTransformation20YearAverageDuringCycle.py +2 -1
- 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 +5 -3
- 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/{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/hestia/seed_emissions.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/impact_assessment/emissions.py +1 -1
- hestia_earth/models/impact_assessment/product/economicValueShare.py +1 -1
- hestia_earth/models/impact_assessment/product/value.py +1 -1
- hestia_earth/models/ipcc2019/aboveGroundBiomass.py +1 -1
- hestia_earth/models/ipcc2019/animal/fatContent.py +2 -2
- hestia_earth/models/ipcc2019/animal/milkYieldPerAnimal.py +2 -2
- hestia_earth/models/ipcc2019/animal/trueProteinContent.py +2 -2
- hestia_earth/models/ipcc2019/belowGroundBiomass.py +1 -1
- hestia_earth/models/ipcc2019/biomass_utils.py +2 -4
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +7 -2
- hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +163 -78
- hestia_earth/models/ipcc2019/co2ToAirAboveGroundBiomassStockChange.py +1 -0
- hestia_earth/models/ipcc2019/co2ToAirBelowGroundBiomassStockChange.py +2 -1
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +31 -20
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChange.py +2 -1
- hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +16 -9
- hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +36 -47
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1.py +94 -9
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2.py +167 -13
- hestia_earth/models/ipcc2019/organicCarbonPerHa_utils.py +7 -5
- hestia_earth/models/koble2014/cropResidueManagement.py +1 -1
- hestia_earth/models/koble2014/residueBurnt.py +1 -1
- hestia_earth/models/koble2014/residueRemoved.py +1 -1
- hestia_earth/models/koble2014/utils.py +3 -3
- hestia_earth/models/mocking/search-results.json +1263 -1229
- hestia_earth/models/pooreNemecek2018/excretaKgN.py +1 -1
- hestia_earth/models/pooreNemecek2018/freshwaterWithdrawalsDuringCycle.py +1 -1
- hestia_earth/models/pooreNemecek2018/utils.py +12 -3
- hestia_earth/models/schmidt2007/ch4ToAirWasteTreatment.py +1 -6
- hestia_earth/models/schmidt2007/h2SToAirWasteTreatment.py +1 -6
- hestia_earth/models/schmidt2007/n2OToAirWasteTreatmentDirect.py +1 -6
- hestia_earth/models/schmidt2007/nh3ToAirWasteTreatment.py +1 -6
- hestia_earth/models/site/pre_checks/country.py +4 -2
- hestia_earth/models/transformation/input/excreta.py +1 -1
- hestia_earth/models/utils/aggregated.py +12 -15
- hestia_earth/models/utils/background_emissions.py +52 -0
- hestia_earth/models/utils/blank_node.py +24 -6
- 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 +1 -1
- hestia_earth/models/utils/source.py +2 -1
- hestia_earth/models/utils/term.py +26 -1
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/METADATA +2 -2
- {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/RECORD +214 -209
- tests/models/aware/test_scarcityWeightedWaterUse.py +1 -12
- tests/models/cycle/input/test_hestiaAggregatedData.py +18 -16
- 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/geospatialDatabase/test_region.py +1 -1
- tests/models/geospatialDatabase/test_utils.py +1 -1
- tests/models/haversineFormula/transport/test_distance.py +2 -2
- tests/models/{koble2014 → hestia}/test_aboveGroundCropResidue.py +3 -3
- 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 +1 -1
- 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/{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 +2 -2
- 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 +11 -0
- tests/models/ipcc2019/test_ch4ToAirFloodedRice.py +10 -42
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChange.py +2 -1
- tests/models/ipcc2019/test_nonCo2EmissionsToAirNaturalVegetationBurning.py +22 -8
- tests/models/ipcc2019/test_organicCarbonPerHa.py +4 -2
- tests/models/pooreNemecek2018/test_landOccupationDuringCycle.py +3 -0
- tests/models/site/pre_checks/test_country.py +4 -3
- tests/models/test_ecoinventV3.py +2 -2
- tests/models/test_ecoinventV3AndEmberClimate.py +2 -2
- tests/models/test_emissionNotRelevant.py +0 -8
- tests/models/utils/test_measurement.py +1 -1
- tests/models/utils/test_source.py +15 -5
- tests/orchestrator/test_models.py +1 -0
- 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.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/top_level.txt +0 -0
@@ -31,12 +31,18 @@ def run_products_average(cycle: dict, term_id: str, get_value_func):
|
|
31
31
|
return list_average(values) if should_run else None
|
32
32
|
|
33
33
|
|
34
|
+
def _excreta_product_id(data: str, term_id):
|
35
|
+
value = extract_grouped_data(data, term_id) or ''
|
36
|
+
return value.split('|')[0] if '|' in value else value
|
37
|
+
|
38
|
+
|
34
39
|
def get_excreta_product_with_ratio(cycle: dict, lookup: str, **log_args):
|
35
40
|
product = find_primary_product(cycle) or {}
|
36
41
|
|
37
42
|
data = get_lookup_value(product.get('term'), lookup, model=MODEL, **log_args)
|
38
43
|
|
39
|
-
|
44
|
+
# TODO: handle multiple products delimited by `|`
|
45
|
+
default_product_id = _excreta_product_id(data, 'default')
|
40
46
|
|
41
47
|
# find matching practices and assign a ratio for each
|
42
48
|
# if no matches, use default id with 100% ratio
|
@@ -44,7 +50,7 @@ def get_excreta_product_with_ratio(cycle: dict, lookup: str, **log_args):
|
|
44
50
|
practices = [
|
45
51
|
{
|
46
52
|
'id': practice.get('term', {}).get('@id'),
|
47
|
-
'product-id':
|
53
|
+
'product-id': _excreta_product_id(data, practice.get('term', {}).get('@id')) or default_product_id,
|
48
54
|
'value': list_sum(practice.get('value'))
|
49
55
|
}
|
50
56
|
for practice in practices
|
@@ -80,7 +86,10 @@ def get_excreta_product_with_ratio(cycle: dict, lookup: str, **log_args):
|
|
80
86
|
) | {'value': [practice.get('ratio')]}
|
81
87
|
for product, practice in practices_with_products
|
82
88
|
# ignore matching products with an existing value
|
83
|
-
if
|
89
|
+
if all([
|
90
|
+
not product or not product.get('value', []),
|
91
|
+
product or practice.get('product-id')
|
92
|
+
])
|
84
93
|
] if practices_with_products else None
|
85
94
|
|
86
95
|
return products or non_empty_list([{
|
@@ -8,12 +8,7 @@ from . import MODEL
|
|
8
8
|
|
9
9
|
REQUIREMENTS = {
|
10
10
|
"Cycle": {
|
11
|
-
"
|
12
|
-
"product": [
|
13
|
-
{"@type": "Product", "value": "", "term.termType": "waste"}
|
14
|
-
],
|
15
|
-
"completeness.waste": ""
|
16
|
-
}
|
11
|
+
"products": [{"@type": "Product", "value": ""}]
|
17
12
|
}
|
18
13
|
}
|
19
14
|
RETURNS = {
|
@@ -8,12 +8,7 @@ from . import MODEL
|
|
8
8
|
|
9
9
|
REQUIREMENTS = {
|
10
10
|
"Cycle": {
|
11
|
-
"
|
12
|
-
"product": [
|
13
|
-
{"@type": "Product", "value": "", "term.termType": "waste"}
|
14
|
-
],
|
15
|
-
"completeness.waste": ""
|
16
|
-
}
|
11
|
+
"products": [{"@type": "Product", "value": ""}]
|
17
12
|
}
|
18
13
|
}
|
19
14
|
RETURNS = {
|
@@ -8,12 +8,7 @@ from . import MODEL
|
|
8
8
|
|
9
9
|
REQUIREMENTS = {
|
10
10
|
"Cycle": {
|
11
|
-
"
|
12
|
-
"product": [
|
13
|
-
{"@type": "Product", "value": "", "term.termType": "waste"}
|
14
|
-
],
|
15
|
-
"completeness.waste": ""
|
16
|
-
}
|
11
|
+
"products": [{"@type": "Product", "value": ""}]
|
17
12
|
}
|
18
13
|
}
|
19
14
|
RETURNS = {
|
@@ -8,12 +8,7 @@ from . import MODEL
|
|
8
8
|
|
9
9
|
REQUIREMENTS = {
|
10
10
|
"Cycle": {
|
11
|
-
"
|
12
|
-
"product": [
|
13
|
-
{"@type": "Product", "value": "", "term.termType": "waste"}
|
14
|
-
],
|
15
|
-
"completeness.waste": ""
|
16
|
-
}
|
11
|
+
"products": [{"@type": "Product", "value": ""}]
|
17
12
|
}
|
18
13
|
}
|
19
14
|
RETURNS = {
|
@@ -1,4 +1,6 @@
|
|
1
|
-
from hestia_earth.
|
1
|
+
from hestia_earth.schema import TermTermType
|
2
2
|
|
3
|
+
from hestia_earth.models.utils.term import download_term
|
3
4
|
|
4
|
-
|
5
|
+
|
6
|
+
def run(site: dict): return site | {'country': download_term(site.get('country', {}).get('@id'), TermTermType.REGION)}
|
@@ -10,7 +10,6 @@ from . import current_year
|
|
10
10
|
from .cycle import is_organic
|
11
11
|
|
12
12
|
MODEL_KEY = 'impactAssessment'
|
13
|
-
MATCH_WORLD_QUERY = {'match': {'country.name.keyword': {'query': 'World', 'boost': 1}}}
|
14
13
|
|
15
14
|
|
16
15
|
def aggregated_end_date(end_date: str):
|
@@ -18,26 +17,25 @@ def aggregated_end_date(end_date: str):
|
|
18
17
|
return min([round(math.floor(year / 10) * 10) + 9, current_year()])
|
19
18
|
|
20
19
|
|
21
|
-
def
|
22
|
-
|
20
|
+
def _match_country_query(name: str = 'World', boost: int = 1):
|
21
|
+
return {'match': {'country.name.keyword': {'query': name, 'boost': boost}}}
|
22
|
+
|
23
|
+
|
24
|
+
def _match_country(country: dict):
|
23
25
|
country_name = country.get('name') if country else None
|
24
26
|
return {
|
25
27
|
'bool': {
|
26
28
|
# either get with exact country, or default to global
|
27
29
|
'should': non_empty_list([
|
28
|
-
(
|
29
|
-
|
30
|
-
{'match': {'country.name.keyword': {'query': country_name, 'boost': 1000}}} if country_name else
|
31
|
-
None
|
32
|
-
),
|
33
|
-
MATCH_WORLD_QUERY
|
30
|
+
_match_country_query(name=country_name, boost=1000) if country_name else None,
|
31
|
+
_match_country_query()
|
34
32
|
]),
|
35
33
|
'minimum_should_match': 1
|
36
34
|
}
|
37
35
|
}
|
38
36
|
|
39
37
|
|
40
|
-
def find_closest_impact(cycle: dict, end_date: str, term: dict,
|
38
|
+
def find_closest_impact(cycle: dict, end_date: str, term: dict, country: dict, must_queries=[]):
|
41
39
|
query = {
|
42
40
|
'bool': {
|
43
41
|
'must': non_empty_list([
|
@@ -54,7 +52,7 @@ def find_closest_impact(cycle: dict, end_date: str, term: dict, region: dict, co
|
|
54
52
|
'minimum_should_match': 1
|
55
53
|
}
|
56
54
|
} if term else None,
|
57
|
-
|
55
|
+
_match_country(country)
|
58
56
|
]) + must_queries,
|
59
57
|
'should': [
|
60
58
|
# if the Cycle is organic, we can try to match organic aggregate first
|
@@ -76,14 +74,13 @@ def _link_input_to_impact(model: str, cycle: dict, date: int):
|
|
76
74
|
def run(input: dict):
|
77
75
|
term = input.get('term', {})
|
78
76
|
term_id = term.get('@id')
|
79
|
-
region = input.get('region')
|
80
77
|
country = input.get('country')
|
81
|
-
impact = find_closest_impact(cycle, date, term,
|
78
|
+
impact = find_closest_impact(cycle, date, term, country)
|
82
79
|
|
83
|
-
|
80
|
+
search_by_country_id = (country or {}).get('@id') or 'region-world'
|
84
81
|
debugValues(cycle, model=model, term=term_id, key=MODEL_KEY,
|
85
82
|
search_by_input_term_id=term_id,
|
86
|
-
|
83
|
+
search_by_country_id=search_by_country_id,
|
87
84
|
search_by_end_date=str(date),
|
88
85
|
impact_assessment_id_found=(impact or {}).get('@id'))
|
89
86
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
from hestia_earth.utils.model import find_term_match
|
2
|
+
from hestia_earth.utils.tools import flatten
|
3
|
+
|
4
|
+
from . import is_from_model
|
5
|
+
|
6
|
+
|
7
|
+
def _animal_inputs(animal: dict):
|
8
|
+
inputs = animal.get('inputs', [])
|
9
|
+
return [(input | {'animal': animal.get('term', {})}) for input in inputs]
|
10
|
+
|
11
|
+
|
12
|
+
def _should_run_input(products: list):
|
13
|
+
def should_run(input: dict):
|
14
|
+
return all([
|
15
|
+
# make sure Input is not a Product as well or we might double-count emissions
|
16
|
+
find_term_match(products, input.get('term', {}).get('@id'), None) is None,
|
17
|
+
# ignore inputs which are flagged as Product of the Cycle
|
18
|
+
not input.get('fromCycle', False),
|
19
|
+
not input.get('producedInCycle', False)
|
20
|
+
])
|
21
|
+
return should_run
|
22
|
+
|
23
|
+
|
24
|
+
def get_background_inputs(cycle: dict, extra_inputs: list = []):
|
25
|
+
# add all the properties of some Term that inlcude others with the mapping
|
26
|
+
inputs = flatten(
|
27
|
+
cycle.get('inputs', []) +
|
28
|
+
list(map(_animal_inputs, cycle.get('animals', []))) +
|
29
|
+
extra_inputs
|
30
|
+
)
|
31
|
+
return list(filter(_should_run_input(cycle.get('products', [])), inputs))
|
32
|
+
|
33
|
+
|
34
|
+
def no_gap_filled_background_emissions(cycle: dict):
|
35
|
+
emissions = cycle.get('emissions', [])
|
36
|
+
|
37
|
+
def check_input(input: dict):
|
38
|
+
input_term_id = input.get('term', {}).get('@id')
|
39
|
+
operation_term_id = input.get('operation', {}).get('@id')
|
40
|
+
animal_term_id = input.get('animal', {}).get('@id')
|
41
|
+
|
42
|
+
return not any([
|
43
|
+
is_from_model(emission)
|
44
|
+
for emission in emissions
|
45
|
+
if all([
|
46
|
+
any([i.get('@id') == input_term_id for i in emission.get('inputs', [])]),
|
47
|
+
emission.get('operation', {}).get('@id') == operation_term_id,
|
48
|
+
emission.get('animal', {}).get('@id') == animal_term_id
|
49
|
+
])
|
50
|
+
])
|
51
|
+
|
52
|
+
return check_input
|
@@ -27,6 +27,7 @@ from hestia_earth.utils.tools import (
|
|
27
27
|
)
|
28
28
|
from hestia_earth.utils.lookup_utils import (
|
29
29
|
is_model_siteType_allowed,
|
30
|
+
is_model_product_id_allowed,
|
30
31
|
is_siteType_allowed,
|
31
32
|
is_product_id_allowed,
|
32
33
|
is_product_termType_allowed,
|
@@ -124,13 +125,16 @@ def _module_term_id(term_id: str, module):
|
|
124
125
|
return getattr(module, 'TERM_ID', term_id_str).split(',')[0]
|
125
126
|
|
126
127
|
|
127
|
-
def _run_model_required(model: str, term_id: str, data: dict):
|
128
|
+
def _run_model_required(model: str, term_id: str, data: dict, skip_logs: bool = False):
|
128
129
|
siteType_allowed = is_model_siteType_allowed(model, term_id, data)
|
130
|
+
product_id_allowed = is_model_product_id_allowed(model, term_id, data)
|
129
131
|
|
130
|
-
run_required = all([siteType_allowed])
|
131
|
-
|
132
|
-
|
133
|
-
|
132
|
+
run_required = all([siteType_allowed, product_id_allowed])
|
133
|
+
if not skip_logs:
|
134
|
+
debugValues(data, model=model, term=term_id,
|
135
|
+
run_required=run_required,
|
136
|
+
siteType_allowed=siteType_allowed,
|
137
|
+
product_id_allowed=product_id_allowed)
|
134
138
|
return run_required
|
135
139
|
|
136
140
|
|
@@ -398,9 +402,17 @@ def convert_to_nitrogen(node: dict, model: str, blank_nodes: list, **log_args):
|
|
398
402
|
return value or get_node_property_value(model, input, 'crudeProteinContent', default=0, **log_args) / 6.25
|
399
403
|
|
400
404
|
values = [(i, prop_value(i)) for i in blank_nodes]
|
401
|
-
missing_nitrogen_property = [i.get('term', {}).get('@id') for i,
|
405
|
+
missing_nitrogen_property = [i.get('term', {}).get('@id') for i, value in values if not value]
|
402
406
|
|
403
407
|
debugValues(node, model=model,
|
408
|
+
convertion_details=log_as_table([
|
409
|
+
{
|
410
|
+
'id': i.get('term', {}).get('@id'),
|
411
|
+
'value': list_sum(i.get('value', [])),
|
412
|
+
'conversion-factor': value
|
413
|
+
}
|
414
|
+
for i, value in values
|
415
|
+
]),
|
404
416
|
missing_nitrogen_property=';'.join(set(missing_nitrogen_property)),
|
405
417
|
**log_args)
|
406
418
|
|
@@ -1010,6 +1022,7 @@ def group_nodes_by_year(
|
|
1010
1022
|
nodes: list[dict],
|
1011
1023
|
default_node_duration: int = 1,
|
1012
1024
|
sort_result: bool = True,
|
1025
|
+
include_spillovers: bool = False,
|
1013
1026
|
inner_key: Union[Any, None] = None,
|
1014
1027
|
mode: GroupNodesByYearMode = GroupNodesByYearMode.START_AND_END_DATE
|
1015
1028
|
) -> dict[int, list[dict]]:
|
@@ -1026,6 +1039,10 @@ def group_nodes_by_year(
|
|
1026
1039
|
Default duration of a node years if start date is not available, by default 1.
|
1027
1040
|
sort_result : bool, optional
|
1028
1041
|
Flag to sort the result by year, by default True.
|
1042
|
+
include_spillovers : bool, optional
|
1043
|
+
If grouping by start and end date, flag to determine whether nodes should be included in year groups that they
|
1044
|
+
spill-over into. If `False` year groups will not include nodes that overlap with them by less than 30% of a
|
1045
|
+
year, unless it is the only year group it overlaps with. By default False.
|
1029
1046
|
inner_key: Any | None
|
1030
1047
|
An optional inner dictionary key for the outputted annualised groups (can be used to merge annualised
|
1031
1048
|
dictionaries together), default value: `None`.
|
@@ -1066,6 +1083,7 @@ def group_nodes_by_year(
|
|
1066
1083
|
|
1067
1084
|
should_run = (
|
1068
1085
|
mode == GroupNodesByYearMode.DATES
|
1086
|
+
or include_spillovers
|
1069
1087
|
or _validate_time_fraction_dict(
|
1070
1088
|
time_fraction_dict,
|
1071
1089
|
is_final_year
|
@@ -3,7 +3,7 @@ from hestia_earth.schema import TermTermType
|
|
3
3
|
from hestia_earth.utils.model import find_term_match, filter_list_term_type
|
4
4
|
from hestia_earth.utils.tools import list_sum, safe_parse_date
|
5
5
|
|
6
|
-
from hestia_earth.models.log import debugValues
|
6
|
+
from hestia_earth.models.log import debugValues
|
7
7
|
from .lookup import all_factor_value, _term_factor_value, _aware_factor_value, fallback_country
|
8
8
|
from .product import find_by_product
|
9
9
|
from .site import region_level_1_id
|
@@ -157,22 +157,22 @@ def impact_country_value(
|
|
157
157
|
The impact total value.
|
158
158
|
"""
|
159
159
|
term_type = TermTermType.RESOURCEUSE.value if 'resourceUse' in lookup else TermTermType.EMISSION.value
|
160
|
-
|
160
|
+
blank_nodes = filter_list_term_type(impact.get('emissionsResourceUse', []), term_type)
|
161
161
|
|
162
162
|
country_id = get_country_id(impact)
|
163
163
|
country_id = fallback_country(country_id, [lookup]) if country_fallback else country_id
|
164
164
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
165
|
+
return all_factor_value(
|
166
|
+
model=model,
|
167
|
+
term_id=term_id,
|
168
|
+
node=impact,
|
169
|
+
lookup_name=lookup,
|
170
|
+
lookup_col=country_id,
|
171
|
+
blank_nodes=blank_nodes,
|
172
|
+
grouped_key=group_key,
|
173
|
+
default_no_values=None,
|
174
|
+
factor_value_func=_term_factor_value
|
175
|
+
)
|
176
176
|
|
177
177
|
|
178
178
|
def impact_aware_value(model: str, term_id: str, impact: dict, lookup: str, group_key: str = None) -> float:
|
@@ -197,14 +197,23 @@ def impact_aware_value(model: str, term_id: str, impact: dict, lookup: str, grou
|
|
197
197
|
int
|
198
198
|
The impact total value.
|
199
199
|
"""
|
200
|
-
|
200
|
+
blank_nodes = impact.get('emissionsResourceUse', [])
|
201
201
|
site = get_site(impact)
|
202
202
|
aware_id = site.get('awareWaterBasinId')
|
203
203
|
if aware_id is None:
|
204
204
|
return None
|
205
|
-
|
206
|
-
|
207
|
-
|
205
|
+
|
206
|
+
return all_factor_value(
|
207
|
+
model=model,
|
208
|
+
term_id=term_id,
|
209
|
+
node=impact,
|
210
|
+
lookup_name=lookup,
|
211
|
+
lookup_col=aware_id,
|
212
|
+
blank_nodes=blank_nodes,
|
213
|
+
grouped_key=group_key,
|
214
|
+
default_no_values=None,
|
215
|
+
factor_value_func=_aware_factor_value
|
216
|
+
)
|
208
217
|
|
209
218
|
|
210
219
|
def impact_endpoint_value(model: str, term_id: str, impact: dict, lookup_col: str) -> float:
|
@@ -26,7 +26,8 @@ def _factor_value(model: str, term_id: str, lookup_name: str, lookup_col: str, g
|
|
26
26
|
coefficient = get_region_lookup_value(lookup_name, node_term_id, lookup_col, model=model, term=term_id)
|
27
27
|
# value is either a number or matching between a model and a value (restrict value to specific model only)
|
28
28
|
coefficient = safe_parse_float(
|
29
|
-
extract_grouped_data(coefficient, grouped_data_key),
|
29
|
+
extract_grouped_data(coefficient, grouped_data_key),
|
30
|
+
default=None
|
30
31
|
) if ':' in str(coefficient) else safe_parse_float(coefficient, None)
|
31
32
|
if value is not None and coefficient is not None:
|
32
33
|
if model:
|
@@ -39,43 +40,15 @@ def _factor_value(model: str, term_id: str, lookup_name: str, lookup_col: str, g
|
|
39
40
|
return get_value
|
40
41
|
|
41
42
|
|
42
|
-
def all_factor_value(
|
43
|
-
model: str,
|
44
|
-
term_id: str,
|
45
|
-
node: dict,
|
46
|
-
lookup_name: str,
|
47
|
-
lookup_col: str,
|
48
|
-
blank_nodes: List[dict],
|
49
|
-
grouped_key: Optional[str] = None,
|
50
|
-
default_no_values=0
|
51
|
-
):
|
52
|
-
values = list(map(_factor_value(model, term_id, lookup_name, lookup_col, grouped_key), blank_nodes))
|
53
|
-
|
54
|
-
has_values = len(values) > 0
|
55
|
-
missing_values = set([v.get('id') for v in values if v.get('value') and v.get('coefficient') is None])
|
56
|
-
all_with_factors = not missing_values
|
57
|
-
|
58
|
-
for missing_value in missing_values:
|
59
|
-
debugMissingLookup(lookup_name, 'termid', missing_value, lookup_col, None, model=model, term=term_id)
|
60
|
-
|
61
|
-
debugValues(node, model=model, term=term_id,
|
62
|
-
all_with_factors=all_with_factors,
|
63
|
-
missing_lookup_factor=';'.join(missing_values),
|
64
|
-
has_values=has_values,
|
65
|
-
values_used=log_as_table(values))
|
66
|
-
|
67
|
-
values = [float((v.get('value') or 0) * (v.get('coefficient') or 0)) for v in values]
|
68
|
-
|
69
|
-
# fail if some factors are missing
|
70
|
-
return None if not all_with_factors else (list_sum(values) if has_values else default_no_values)
|
71
|
-
|
72
|
-
|
73
43
|
def _term_factor_value(model: str, term_id: str, lookup_name: str, lookup_term_id: str, group_key: str = None):
|
74
44
|
def get_value(data: dict):
|
75
45
|
node_term_id = data.get('term', {}).get('@id')
|
76
46
|
value = _node_value(data)
|
77
47
|
coefficient = get_region_lookup_value(lookup_name, lookup_term_id, node_term_id, model=model, term=term_id)
|
78
|
-
coefficient = safe_parse_float(
|
48
|
+
coefficient = safe_parse_float(
|
49
|
+
extract_grouped_data(coefficient, group_key) if group_key else coefficient,
|
50
|
+
default=None
|
51
|
+
)
|
79
52
|
if value is not None and coefficient is not None:
|
80
53
|
debugValues(data, model=model, term=term_id,
|
81
54
|
node=node_term_id,
|
@@ -90,23 +63,59 @@ def _aware_factor_value(model: str, term_id: str, lookup_name: str, aware_id: st
|
|
90
63
|
lookup_col = column_name('awareWaterBasinId')
|
91
64
|
|
92
65
|
def get_value(data: dict):
|
66
|
+
node_term_id = data.get('term', {}).get('@id')
|
67
|
+
value = _node_value(data)
|
68
|
+
|
93
69
|
try:
|
94
|
-
node_term_id = data.get('term', {}).get('@id')
|
95
|
-
value = _node_value(data)
|
96
70
|
coefficient = _get_single_table_value(lookup, lookup_col, int(aware_id), column_name(node_term_id))
|
97
|
-
coefficient = safe_parse_float(
|
71
|
+
coefficient = safe_parse_float(
|
72
|
+
extract_grouped_data(coefficient, group_key),
|
73
|
+
default=None
|
74
|
+
) if group_key else coefficient
|
98
75
|
if value is not None and coefficient is not None:
|
99
76
|
debugValues(data, model=model, term=term_id,
|
100
77
|
node=node_term_id,
|
101
78
|
value=value,
|
102
79
|
coefficient=coefficient)
|
103
|
-
return value * coefficient
|
104
|
-
return None
|
105
80
|
except ValueError: # factor does not exist
|
106
|
-
|
81
|
+
coefficient = None
|
82
|
+
|
83
|
+
return {'id': node_term_id, 'value': value, 'coefficient': coefficient}
|
107
84
|
return get_value
|
108
85
|
|
109
86
|
|
87
|
+
def all_factor_value(
|
88
|
+
model: str,
|
89
|
+
term_id: str,
|
90
|
+
node: dict,
|
91
|
+
lookup_name: str,
|
92
|
+
lookup_col: str,
|
93
|
+
blank_nodes: List[dict],
|
94
|
+
grouped_key: Optional[str] = None,
|
95
|
+
default_no_values=0,
|
96
|
+
factor_value_func=_factor_value
|
97
|
+
):
|
98
|
+
values = list(map(factor_value_func(model, term_id, lookup_name, lookup_col, grouped_key), blank_nodes))
|
99
|
+
|
100
|
+
has_values = len(values) > 0
|
101
|
+
missing_values = set([v.get('id') for v in values if v.get('value') and v.get('coefficient') is None])
|
102
|
+
all_with_factors = not missing_values
|
103
|
+
|
104
|
+
for missing_value in missing_values:
|
105
|
+
debugMissingLookup(lookup_name, 'termid', missing_value, lookup_col, None, model=model, term=term_id)
|
106
|
+
|
107
|
+
debugValues(node, model=model, term=term_id,
|
108
|
+
all_with_factors=all_with_factors,
|
109
|
+
missing_lookup_factor=';'.join(missing_values),
|
110
|
+
has_values=has_values,
|
111
|
+
values_used=log_as_table(values))
|
112
|
+
|
113
|
+
values = [float((v.get('value') or 0) * (v.get('coefficient') or 0)) for v in values]
|
114
|
+
|
115
|
+
# fail if some factors are missing
|
116
|
+
return None if not all_with_factors else (list_sum(values) if has_values else default_no_values)
|
117
|
+
|
118
|
+
|
110
119
|
def _country_in_lookup(country_id: str):
|
111
120
|
def in_lookup(lookup_name: str):
|
112
121
|
return (
|
@@ -10,7 +10,7 @@ from hestia_earth.utils.date import diff_in_days
|
|
10
10
|
|
11
11
|
from . import flatten_args
|
12
12
|
from .blank_node import most_relevant_blank_node_by_id
|
13
|
-
from .method import
|
13
|
+
from .method import include_method
|
14
14
|
from .term import download_term, get_lookup_value
|
15
15
|
|
16
16
|
|
@@ -26,10 +26,10 @@ MEASUREMENT_REDUCE = {
|
|
26
26
|
MEASUREMENT_METHOD_CLASSIFICATIONS = [e.value for e in MeasurementMethodClassification]
|
27
27
|
|
28
28
|
|
29
|
-
def _new_measurement(term,
|
29
|
+
def _new_measurement(term, method=None):
|
30
30
|
node = {'@type': SchemaType.MEASUREMENT.value}
|
31
31
|
node['term'] = linked_node(term if isinstance(term, dict) else download_term(term))
|
32
|
-
return
|
32
|
+
return include_method(node, term_id=method)
|
33
33
|
|
34
34
|
|
35
35
|
def measurement_value(measurement: dict, is_larger_unit: bool = False) -> float:
|
@@ -153,7 +153,7 @@ def get_animal_produced_nitrogen(model: str, products: list) -> float:
|
|
153
153
|
def product_value(product: dict):
|
154
154
|
value = convert_product_to_unit(product, Units.KG_LIVEWEIGHT)
|
155
155
|
property = prop_value(product)
|
156
|
-
return value * property
|
156
|
+
return value * property if all([value, property]) else 0
|
157
157
|
|
158
158
|
return list_sum(list(map(product_value, products)))
|
159
159
|
|
@@ -52,7 +52,8 @@ def _extract(content: str):
|
|
52
52
|
|
53
53
|
def _list_sources():
|
54
54
|
dir = pathlib.Path(ROOT_DIR)
|
55
|
-
|
55
|
+
# ignore current file
|
56
|
+
files = list(filter(lambda f: not str(f).endswith('utils/source.py'), list(dir.rglob('**/*.py'))))
|
56
57
|
return list(set(flatten([_extract(open(f, 'r').read().replace('\n', '')) for f in files])))
|
57
58
|
|
58
59
|
|
@@ -715,7 +715,7 @@ def get_land_cover_terms():
|
|
715
715
|
|
716
716
|
Returns
|
717
717
|
-------
|
718
|
-
List of landCover terms
|
718
|
+
List of landCover terms IDs.
|
719
719
|
"""
|
720
720
|
terms = search({
|
721
721
|
"bool": {
|
@@ -726,3 +726,28 @@ def get_land_cover_terms():
|
|
726
726
|
},
|
727
727
|
}, limit=LIMIT, fields=['@id'])
|
728
728
|
return list(map(lambda n: n["@id"], terms))
|
729
|
+
|
730
|
+
|
731
|
+
def get_ionophore_terms():
|
732
|
+
"""
|
733
|
+
Find all `Ionophore` terms from the Glossary: https://hestia.earth/glossary?query=ionophore
|
734
|
+
|
735
|
+
Returns
|
736
|
+
-------
|
737
|
+
List of ionophore term IDs.
|
738
|
+
"""
|
739
|
+
terms = search({
|
740
|
+
"bool": {
|
741
|
+
"must": [
|
742
|
+
{"match": {"@type": SchemaType.TERM.value}},
|
743
|
+
{"match_phrase_prefix": {"name": "ionophore"}}
|
744
|
+
],
|
745
|
+
"should": [
|
746
|
+
{"match": {"termType": TermTermType.FEEDFOODADDITIVE.value}},
|
747
|
+
{"match": {"termType": TermTermType.VETERINARYDRUG.value}},
|
748
|
+
|
749
|
+
],
|
750
|
+
"minimum_should_match": 1
|
751
|
+
},
|
752
|
+
}, limit=LIMIT, fields=['@id'])
|
753
|
+
return list(map(lambda n: n["@id"], terms))
|
hestia_earth/models/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
VERSION = '0.
|
1
|
+
VERSION = '0.70.1'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: hestia-earth-models
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.70.1
|
4
4
|
Summary: HESTIA's set of modules for filling gaps in the activity data using external datasets (e.g. populating soil properties with a geospatial dataset using provided coordinates) and internal lookups (e.g. populating machinery use from fuel use). Includes rules for when gaps should be filled versus not (e.g. never gap fill yield, gap fill crop residue if yield provided etc.).
|
5
5
|
Home-page: https://gitlab.com/hestia-earth/hestia-engine-models
|
6
6
|
Author: HESTIA Team
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.6
|
|
12
12
|
Description-Content-Type: text/markdown
|
13
13
|
License-File: LICENSE
|
14
14
|
Requires-Dist: hestia-earth-schema==31.*
|
15
|
-
Requires-Dist: hestia-earth-utils>=0.14.
|
15
|
+
Requires-Dist: hestia-earth-utils>=0.14.1
|
16
16
|
Requires-Dist: python-dateutil>=2.8.1
|
17
17
|
Requires-Dist: CurrencyConverter==0.16.8
|
18
18
|
Requires-Dist: haversine>=2.7.0
|