hestia-earth-models 0.64.9__py3-none-any.whl → 0.64.10__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/cml2001Baseline/abioticResourceDepletionFossilFuels.py +175 -0
- hestia_earth/models/cml2001Baseline/abioticResourceDepletionMineralsAndMetals.py +136 -0
- hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandTransformation.py +2 -2
- hestia_earth/models/ipcc2019/aboveGroundBiomass.py +31 -243
- hestia_earth/models/ipcc2019/belowGroundBiomass.py +529 -0
- hestia_earth/models/ipcc2019/biomass_utils.py +406 -0
- hestia_earth/models/ipcc2019/{co2ToAirAboveGroundBiomassStockChangeLandUseChange.py → co2ToAirAboveGroundBiomassStockChange.py} +19 -7
- hestia_earth/models/ipcc2019/{co2ToAirBelowGroundBiomassStockChangeLandUseChange.py → co2ToAirBelowGroundBiomassStockChange.py} +19 -7
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +402 -73
- hestia_earth/models/ipcc2019/{co2ToAirSoilOrganicCarbonStockChangeManagementChange.py → co2ToAirSoilOrganicCarbonStockChange.py} +20 -8
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +3 -1
- hestia_earth/models/ipcc2019/pastureGrass_utils.py +6 -7
- hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthParticulateMatterFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToMarineEcosystemsMarineEutrophication.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthParticulateMatterFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToMarineEcosystemsMarineEutrophication.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthParticulateMatterFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToMarineEcosystemsMarineEutrophication.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthParticulateMatterFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToMarineEcosystemsMarineEutrophication.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
- hestia_earth/models/mocking/build_mock_search.py +44 -0
- hestia_earth/models/mocking/mock_search.py +8 -49
- hestia_earth/models/mocking/search-results.json +3075 -578
- hestia_earth/models/poschEtAl2008/terrestrialAcidificationPotentialAccumulatedExceedance.py +3 -3
- hestia_earth/models/poschEtAl2008/terrestrialEutrophicationPotentialAccumulatedExceedance.py +3 -3
- hestia_earth/models/preload_requests.py +1 -1
- hestia_earth/models/schmidt2007/utils.py +13 -4
- hestia_earth/models/utils/blank_node.py +73 -3
- hestia_earth/models/utils/constant.py +8 -1
- hestia_earth/models/utils/cycle.py +10 -13
- hestia_earth/models/utils/fuel.py +1 -1
- hestia_earth/models/utils/impact_assessment.py +31 -16
- hestia_earth/models/utils/lookup.py +36 -7
- hestia_earth/models/utils/pesticideAI.py +1 -1
- hestia_earth/models/utils/property.py +11 -4
- hestia_earth/models/utils/term.py +15 -8
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/METADATA +2 -2
- {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/RECORD +78 -71
- {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/WHEEL +1 -1
- tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +196 -0
- tests/models/cml2001Baseline/test_abioticResourceDepletionMineralsAndMetals.py +124 -0
- tests/models/edip2003/test_ozoneDepletionPotential.py +1 -13
- tests/models/environmentalFootprintV3/test_soilQualityIndexLandTransformation.py +1 -2
- tests/models/impact_assessment/test_emissions.py +1 -0
- tests/models/ipcc2019/test_aboveGroundBiomass.py +27 -63
- tests/models/ipcc2019/test_belowGroundBiomass.py +146 -0
- tests/models/ipcc2019/test_biomass_utils.py +115 -0
- tests/models/ipcc2019/{test_co2ToAirAboveGroundBiomassStockChangeLandUseChange.py → test_co2ToAirAboveGroundBiomassStockChange.py} +5 -5
- tests/models/ipcc2019/{test_co2ToAirBelowGroundBiomassStockChangeLandUseChange.py → test_co2ToAirBelowGroundBiomassStockChange.py} +5 -5
- tests/models/ipcc2019/{test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py → test_co2ToAirSoilOrganicCarbonStockChange.py} +5 -5
- tests/models/ipcc2021/test_gwp100.py +2 -2
- hestia_earth/models/ipcc2019/aboveGroundBiomass_utils.py +0 -180
- tests/models/ipcc2019/test_aboveGroundBiomass_utils.py +0 -92
- {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/top_level.txt +0 -0
|
@@ -36,8 +36,8 @@ def _indicator(value: float):
|
|
|
36
36
|
|
|
37
37
|
def run(impact_assessment: dict):
|
|
38
38
|
value = impact_country_value(MODEL, TERM_ID, impact_assessment, f"{list(LOOKUPS.keys())[0]}.csv",
|
|
39
|
-
country_fallback=True
|
|
39
|
+
country_fallback=True)
|
|
40
40
|
logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
|
|
41
41
|
value=value)
|
|
42
|
-
logShouldRun(impact_assessment, MODEL, TERM_ID,
|
|
43
|
-
return _indicator(value)
|
|
42
|
+
logShouldRun(impact_assessment, MODEL, TERM_ID, value is not None)
|
|
43
|
+
return None if value is None else _indicator(value)
|
hestia_earth/models/poschEtAl2008/terrestrialEutrophicationPotentialAccumulatedExceedance.py
CHANGED
|
@@ -36,8 +36,8 @@ def _indicator(value: float):
|
|
|
36
36
|
|
|
37
37
|
def run(impact_assessment: dict):
|
|
38
38
|
value = impact_country_value(MODEL, TERM_ID, impact_assessment, f"{list(LOOKUPS.keys())[0]}.csv",
|
|
39
|
-
country_fallback=True
|
|
39
|
+
country_fallback=True)
|
|
40
40
|
logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
|
|
41
41
|
value=value)
|
|
42
|
-
logShouldRun(impact_assessment, MODEL, TERM_ID,
|
|
43
|
-
return _indicator(value)
|
|
42
|
+
logShouldRun(impact_assessment, MODEL, TERM_ID, value is not None)
|
|
43
|
+
return None if value is None else _indicator(value)
|
|
@@ -3,14 +3,23 @@ from hestia_earth.utils.model import filter_list_term_type
|
|
|
3
3
|
from hestia_earth.utils.tools import non_empty_list
|
|
4
4
|
|
|
5
5
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
6
|
-
from hestia_earth.models.utils.lookup import
|
|
6
|
+
from hestia_earth.models.utils.lookup import all_factor_value
|
|
7
|
+
from . import MODEL
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def get_waste_values(term_id: str, cycle: dict, lookup_col: str):
|
|
10
11
|
products = filter_list_term_type(cycle.get('products', []), TermTermType.WASTE)
|
|
11
|
-
|
|
12
|
+
value = all_factor_value(
|
|
13
|
+
model=MODEL,
|
|
14
|
+
term_id=term_id,
|
|
15
|
+
node=cycle,
|
|
16
|
+
lookup_name=f"{TermTermType.WASTE.value}.csv",
|
|
17
|
+
lookup_col=lookup_col,
|
|
18
|
+
blank_nodes=products,
|
|
19
|
+
default_no_values=None
|
|
20
|
+
)
|
|
12
21
|
return [0] if all([
|
|
13
|
-
|
|
22
|
+
value is None,
|
|
14
23
|
_is_term_type_complete(cycle, TermTermType.WASTE),
|
|
15
24
|
cycle.get('@type', cycle.get('type')) == NodeType.CYCLE.value # ignore adding 0 value for Transformation
|
|
16
|
-
]) else
|
|
25
|
+
]) else non_empty_list([value])
|
|
@@ -28,14 +28,14 @@ from hestia_earth.utils.tools import (
|
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
from . import is_from_model, _filter_list_term_unit, is_iterable, full_date_str
|
|
31
|
-
from .constant import Units
|
|
31
|
+
from .constant import Units, get_atomic_conversion
|
|
32
32
|
from .lookup import (
|
|
33
33
|
is_model_siteType_allowed,
|
|
34
34
|
is_siteType_allowed,
|
|
35
35
|
is_product_id_allowed, is_product_termType_allowed,
|
|
36
|
-
is_input_id_allowed, is_input_termType_allowed
|
|
36
|
+
is_input_id_allowed, is_input_termType_allowed, _node_value
|
|
37
37
|
)
|
|
38
|
-
from .property import get_node_property, get_node_property_value
|
|
38
|
+
from .property import get_node_property, get_node_property_value, find_term_property
|
|
39
39
|
from .term import get_lookup_value
|
|
40
40
|
from ..log import debugValues, log_as_table
|
|
41
41
|
|
|
@@ -1387,3 +1387,73 @@ def most_relevant_blank_node_by_id(nodes: list, term_id: str, date: str):
|
|
|
1387
1387
|
return {} if len(filtered_nodes) == 0 \
|
|
1388
1388
|
else _shallowest_node(_most_recent_nodes(filtered_nodes, date)) \
|
|
1389
1389
|
if date and len(filtered_nodes) > 1 else filtered_nodes[0]
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
PROPERTY_UNITS_CONVERSIONS = {
|
|
1393
|
+
Units.KG.value: {
|
|
1394
|
+
Units.MJ.value: [
|
|
1395
|
+
'energyContentHigherHeatingValue', # "kg" to "mj"
|
|
1396
|
+
]
|
|
1397
|
+
},
|
|
1398
|
+
Units.M3.value: {
|
|
1399
|
+
Units.MJ.value: [
|
|
1400
|
+
'density', # "m3" to "kg"
|
|
1401
|
+
'energyContentHigherHeatingValue', # "kg" to "mj"
|
|
1402
|
+
]
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
|
|
1407
|
+
def _convert_via_property(node: dict, node_value: Union[int, float], property_field: str) -> Optional[float]:
|
|
1408
|
+
"""
|
|
1409
|
+
Converts a node_value number from one unit to another using a property_field associated
|
|
1410
|
+
with a term inside term node such as "density" or 'energyContentHigherHeatingValue' or listed
|
|
1411
|
+
in https://www.hestia.earth/glossary?page=1&termType=property
|
|
1412
|
+
|
|
1413
|
+
Will return none if the property_field is not found
|
|
1414
|
+
|
|
1415
|
+
Parameters
|
|
1416
|
+
----------
|
|
1417
|
+
node: a dict containing a term
|
|
1418
|
+
node_value: value to be converted as float or int
|
|
1419
|
+
property_field: str such as "density"
|
|
1420
|
+
|
|
1421
|
+
Returns float or None
|
|
1422
|
+
-------
|
|
1423
|
+
"""
|
|
1424
|
+
node_property = find_term_property(node, property_field, default={}, keep_in_memory=True)
|
|
1425
|
+
node_property_value = safe_parse_float(node_property.get("value", 0))
|
|
1426
|
+
|
|
1427
|
+
return node_value * node_property_value if node_value is not None and bool(node_property_value) else None
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
def convert_unit(node, dest_unit: Units, node_value: Union[int, float] = None) -> Optional[Union[int, float]]:
|
|
1431
|
+
"""
|
|
1432
|
+
Convert a number `value` inside a node or a optional `node_value` belonging to a term `node`, to unit `dest_unit`
|
|
1433
|
+
using the ATOMIC_WEIGHT_CONVERSIONS map or failing that, the PROPERTY_UNITS_CONVERSIONS map and lookups
|
|
1434
|
+
"""
|
|
1435
|
+
src_unit = node.get("units", "")
|
|
1436
|
+
|
|
1437
|
+
node_value = _node_value(node) if node_value is None else node_value
|
|
1438
|
+
|
|
1439
|
+
return node_value if src_unit == dest_unit.value else (
|
|
1440
|
+
node_value * get_atomic_conversion(src_unit, dest_unit)
|
|
1441
|
+
if get_atomic_conversion(src_unit, dest_unit, default_value=None) is not None
|
|
1442
|
+
else convert_unit_properties(node_value, node, dest_unit)
|
|
1443
|
+
) if node_value else None
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
def convert_unit_properties(node_value: Union[int, float], node: dict, dest_unit: Units) -> Optional[Union[int, float]]:
|
|
1447
|
+
"""
|
|
1448
|
+
Convert a number `node_value` belonging to a term `node`, to unit `to_units` by chaining multiple unit conversions
|
|
1449
|
+
together.
|
|
1450
|
+
Uses terms properties for the conversion.
|
|
1451
|
+
Uses cached calls to download_hestia() internally for speedup
|
|
1452
|
+
Returns None if no conversion possible.
|
|
1453
|
+
"""
|
|
1454
|
+
src_unit = node.get('units', '')
|
|
1455
|
+
conversions = PROPERTY_UNITS_CONVERSIONS.get(src_unit, {}).get(dest_unit.value, [])
|
|
1456
|
+
return reduce(
|
|
1457
|
+
lambda value, conversion_property_field: _convert_via_property(node, value, conversion_property_field),
|
|
1458
|
+
conversions, node_value
|
|
1459
|
+
) if conversions else None
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
+
|
|
2
3
|
from hestia_earth.utils.tools import list_sum
|
|
3
4
|
|
|
4
5
|
|
|
@@ -35,6 +36,9 @@ class Units(Enum):
|
|
|
35
36
|
PERCENTAGE_AREA = '% area'
|
|
36
37
|
TO_C = '-C'
|
|
37
38
|
TO_N = '-N'
|
|
39
|
+
KW_H = 'kWh'
|
|
40
|
+
MJ = 'MJ'
|
|
41
|
+
M3 = "m3"
|
|
38
42
|
|
|
39
43
|
|
|
40
44
|
C = 12.012
|
|
@@ -93,7 +97,10 @@ ATOMIC_WEIGHT_CONVERSIONS = {
|
|
|
93
97
|
},
|
|
94
98
|
Units.KG_NH4.value: {
|
|
95
99
|
Units.TO_N.value: (N + H*4) / N # Conv_Mol_NH4N_NH4
|
|
96
|
-
}
|
|
100
|
+
},
|
|
101
|
+
Units.KW_H.value: {
|
|
102
|
+
Units.MJ.value: 3.6
|
|
103
|
+
},
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
|
|
@@ -3,7 +3,7 @@ from hestia_earth.utils.model import filter_list_term_type, find_term_match, fin
|
|
|
3
3
|
from hestia_earth.utils.tools import list_sum, safe_parse_float, safe_parse_date, non_empty_list
|
|
4
4
|
|
|
5
5
|
from ..log import logRequirements, debugValues
|
|
6
|
-
from .lookup import
|
|
6
|
+
from .lookup import all_factor_value, is_siteType_allowed
|
|
7
7
|
from .term import get_lookup_value
|
|
8
8
|
from .property import get_node_property
|
|
9
9
|
from .completeness import _is_term_type_complete
|
|
@@ -386,9 +386,7 @@ def cycle_end_year(cycle: dict):
|
|
|
386
386
|
return date.year if date else None
|
|
387
387
|
|
|
388
388
|
|
|
389
|
-
def impact_lookup_value(
|
|
390
|
-
model: str, term_id: str, blank_nodes: list, lookup_col: str, allow_missing: bool = True
|
|
391
|
-
) -> float:
|
|
389
|
+
def impact_lookup_value(model: str, term_id: str, cycle: dict, blank_nodes: list, lookup_col: str) -> float:
|
|
392
390
|
"""
|
|
393
391
|
Calculate the value of the impact based on lookup factors and cycle values.
|
|
394
392
|
|
|
@@ -409,15 +407,14 @@ def impact_lookup_value(
|
|
|
409
407
|
The impact total value.
|
|
410
408
|
"""
|
|
411
409
|
term_type = blank_nodes[0].get('term', {}).get('termType') if len(blank_nodes) > 0 else None
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
return list_sum(values) if len(values) > 0 and (allow_missing or all_nodes_have_value) else None
|
|
410
|
+
return all_factor_value(
|
|
411
|
+
model=model,
|
|
412
|
+
term_id=term_id,
|
|
413
|
+
node=cycle,
|
|
414
|
+
lookup_name=f"{term_type}.csv",
|
|
415
|
+
lookup_col=lookup_col,
|
|
416
|
+
blank_nodes=blank_nodes
|
|
417
|
+
)
|
|
421
418
|
|
|
422
419
|
|
|
423
420
|
def get_ecoClimateZone(cycle: dict) -> int:
|
|
@@ -13,7 +13,7 @@ def impact_lookup_value(model: str, term_id: str, impact_assessment: dict, looku
|
|
|
13
13
|
fuels = filter_list_term_type(cycle.get('inputs', []), TermTermType.FUEL)
|
|
14
14
|
has_fuels_inputs = len(fuels) > 0
|
|
15
15
|
fuels_total_value = convert_value_from_cycle(
|
|
16
|
-
product, cycle_lookup_value(model, term_id, fuels, lookup_col), model=model, term_id=term_id
|
|
16
|
+
product, cycle_lookup_value(model, term_id, cycle, fuels, lookup_col), model=model, term_id=term_id
|
|
17
17
|
) if has_fuels_inputs else None
|
|
18
18
|
logRequirements(impact_assessment, model=model, term=term_id,
|
|
19
19
|
term_type_electricityFuel_complete=fuel_complete,
|
|
@@ -4,10 +4,10 @@ from hestia_earth.utils.lookup import download_lookup
|
|
|
4
4
|
from hestia_earth.utils.model import find_term_match
|
|
5
5
|
from hestia_earth.utils.tools import list_sum, safe_parse_date
|
|
6
6
|
|
|
7
|
-
from .
|
|
7
|
+
from hestia_earth.models.log import logRequirements, debugValues, log_as_table
|
|
8
|
+
from .lookup import all_factor_value, _term_factor_value, _aware_factor_value, fallback_country
|
|
8
9
|
from .product import find_by_product
|
|
9
10
|
from .site import region_level_1_id
|
|
10
|
-
from ..log import logRequirements
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def impact_end_year(impact_assessment: dict) -> int:
|
|
@@ -110,15 +110,19 @@ def impact_lookup_value(model: str, term_id: str, impact: dict, lookup_col: str,
|
|
|
110
110
|
int
|
|
111
111
|
The impact total value.
|
|
112
112
|
"""
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
return all_factor_value(
|
|
114
|
+
model=model,
|
|
115
|
+
term_id=term_id,
|
|
116
|
+
node=impact,
|
|
117
|
+
lookup_name='emission.csv',
|
|
118
|
+
lookup_col=lookup_col,
|
|
119
|
+
blank_nodes=impact.get('emissionsResourceUse', []),
|
|
120
|
+
grouped_key=grouped_key
|
|
121
|
+
)
|
|
118
122
|
|
|
119
123
|
|
|
120
124
|
def impact_country_value(model: str, term_id: str, impact: dict, lookup: str, group_key: str = None,
|
|
121
|
-
country_fallback: bool = False
|
|
125
|
+
country_fallback: bool = False) -> float:
|
|
122
126
|
"""
|
|
123
127
|
Calculate the value of the impact based on lookup factors and `site.country.@id`.
|
|
124
128
|
|
|
@@ -137,8 +141,6 @@ def impact_country_value(model: str, term_id: str, impact: dict, lookup: str, gr
|
|
|
137
141
|
country_fallback : bool
|
|
138
142
|
Optional: if True fallback to default `region-world` country_id if country_id in `ImpactAssessment` not found in
|
|
139
143
|
lookup file containing factors.
|
|
140
|
-
default_no_emissions :
|
|
141
|
-
Optional: if set, will return this value if no contributing terms found in emissionsResourceUse
|
|
142
144
|
|
|
143
145
|
Returns
|
|
144
146
|
-------
|
|
@@ -149,9 +151,17 @@ def impact_country_value(model: str, term_id: str, impact: dict, lookup: str, gr
|
|
|
149
151
|
country_id = get_country_id(impact)
|
|
150
152
|
country_id = fallback_country(country_id, [download_lookup(lookup)]) if country_fallback else country_id
|
|
151
153
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
values = list(map(_term_factor_value(model, term_id, lookup, country_id, group_key), nodes))
|
|
155
|
+
debugValues(impact, model=model, term=term_id,
|
|
156
|
+
values_used=log_as_table(values))
|
|
157
|
+
|
|
158
|
+
all_with_factors = all([v.get('coefficient') is not None for v in values if v.get('value') is not None])
|
|
159
|
+
values = [float((v.get('value') or 0) * (v.get('coefficient') or 0)) for v in values]
|
|
160
|
+
|
|
161
|
+
# fail if some factors are missing
|
|
162
|
+
return None if not all_with_factors else (
|
|
163
|
+
list_sum(values) if len(values) > 0 else 0
|
|
164
|
+
)
|
|
155
165
|
|
|
156
166
|
|
|
157
167
|
def impact_aware_value(model: str, term_id: str, impact: dict, lookup: str, group_key: str = None) -> float:
|
|
@@ -210,9 +220,14 @@ def impact_endpoint_value(model: str, term_id: str, impact: dict, lookup_col: st
|
|
|
210
220
|
i.get('methodModel').get('@id') == model or
|
|
211
221
|
not i.get('methodModel').get('@id').startswith(model[0:6]) # allow other non-related models to be accounted for
|
|
212
222
|
)]
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
223
|
+
return all_factor_value(
|
|
224
|
+
model=model,
|
|
225
|
+
term_id=term_id,
|
|
226
|
+
node=impact,
|
|
227
|
+
lookup_name='characterisedIndicator.csv',
|
|
228
|
+
lookup_col=lookup_col,
|
|
229
|
+
blank_nodes=nodes
|
|
230
|
+
)
|
|
216
231
|
|
|
217
232
|
|
|
218
233
|
def emission_value(impact_assessment: dict, term_id: str):
|
|
@@ -6,7 +6,7 @@ from hestia_earth.utils.lookup import (
|
|
|
6
6
|
)
|
|
7
7
|
from hestia_earth.utils.tools import list_sum, safe_parse_float, non_empty_list
|
|
8
8
|
|
|
9
|
-
from ..log import debugValues
|
|
9
|
+
from ..log import debugValues, log_as_table, debugMissingLookup
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def _node_value(node):
|
|
@@ -14,7 +14,7 @@ def _node_value(node):
|
|
|
14
14
|
return list_sum(value) if isinstance(value, list) else value
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
def
|
|
17
|
+
def _factor_value(model: str, term_id: str, lookup_name: str, lookup_col: str, grouped_key: Optional[str] = None):
|
|
18
18
|
lookup = download_lookup(lookup_name)
|
|
19
19
|
|
|
20
20
|
def get_value(data: dict):
|
|
@@ -33,11 +33,41 @@ def factor_value(model: str, term_id: str, lookup_name: str, lookup_col: str, gr
|
|
|
33
33
|
operation=data.get('operation', {}).get('@id'),
|
|
34
34
|
value=value,
|
|
35
35
|
coefficient=coefficient)
|
|
36
|
-
|
|
37
|
-
return None
|
|
36
|
+
return {'id': node_term_id, 'value': value, 'coefficient': coefficient}
|
|
38
37
|
return get_value
|
|
39
38
|
|
|
40
39
|
|
|
40
|
+
def all_factor_value(
|
|
41
|
+
model: str,
|
|
42
|
+
term_id: str,
|
|
43
|
+
node: dict,
|
|
44
|
+
lookup_name: str,
|
|
45
|
+
lookup_col: str,
|
|
46
|
+
blank_nodes: List[dict],
|
|
47
|
+
grouped_key: Optional[str] = None,
|
|
48
|
+
default_no_values=0
|
|
49
|
+
):
|
|
50
|
+
values = list(map(_factor_value(model, term_id, lookup_name, lookup_col, grouped_key), blank_nodes))
|
|
51
|
+
|
|
52
|
+
missing_values = set([v.get('id') for v in values if v.get('value') is not None and v.get('coefficient') is None])
|
|
53
|
+
all_with_factors = all([v.get('coefficient') is not None for v in values if v.get('value') is not None])
|
|
54
|
+
|
|
55
|
+
for term_id in missing_values:
|
|
56
|
+
debugMissingLookup(lookup_name, 'termid', term_id, lookup_col, None)
|
|
57
|
+
|
|
58
|
+
debugValues(node, model=model, term=term_id,
|
|
59
|
+
all_with_factors=all_with_factors,
|
|
60
|
+
missing_lookup_factor=';'.join(missing_values),
|
|
61
|
+
values_used=log_as_table(values))
|
|
62
|
+
|
|
63
|
+
values = [float((v.get('value') or 0) * (v.get('coefficient') or 0)) for v in values]
|
|
64
|
+
|
|
65
|
+
# fail if some factors are missing
|
|
66
|
+
return None if not all_with_factors else (
|
|
67
|
+
list_sum(values) if len(values) > 0 else default_no_values
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
41
71
|
def _term_factor_value(model: str, term_id: str, lookup_name: str, lookup_term_id: str, group_key: str = None):
|
|
42
72
|
lookup = download_lookup(lookup_name, False) # avoid saving in memory as there could be many different files used
|
|
43
73
|
|
|
@@ -45,11 +75,10 @@ def _term_factor_value(model: str, term_id: str, lookup_name: str, lookup_term_i
|
|
|
45
75
|
node_term_id = data.get('term', {}).get('@id')
|
|
46
76
|
value = _node_value(data)
|
|
47
77
|
coefficient = get_table_value(lookup, 'termid', lookup_term_id, column_name(node_term_id))
|
|
48
|
-
coefficient = safe_parse_float(extract_grouped_data(coefficient, group_key)
|
|
78
|
+
coefficient = safe_parse_float(extract_grouped_data(coefficient, group_key) if group_key else coefficient)
|
|
49
79
|
if value is not None and coefficient is not None:
|
|
50
80
|
debugValues(data, model=model, term=term_id, node=node_term_id, value=value, coefficient=coefficient)
|
|
51
|
-
|
|
52
|
-
return None
|
|
81
|
+
return {'id': node_term_id, 'value': value, 'coefficient': coefficient}
|
|
53
82
|
return get_value
|
|
54
83
|
|
|
55
84
|
|
|
@@ -22,7 +22,7 @@ def impact_lookup_value(model: str, term_id: str, impact_assessment: dict, looku
|
|
|
22
22
|
get_pesticides_from_inputs(cycle)
|
|
23
23
|
has_pesticides_inputs = len(pesticides) > 0
|
|
24
24
|
pesticides_total_value = convert_value_from_cycle(
|
|
25
|
-
product, cycle_lookup_value(model, term_id, pesticides, lookup_col
|
|
25
|
+
product, cycle_lookup_value(model, term_id, cycle, pesticides, lookup_col), model=model, term_id=term_id
|
|
26
26
|
) if has_pesticides_inputs else None
|
|
27
27
|
|
|
28
28
|
logRequirements(impact_assessment, model=model, term=term_id,
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
from functools import cache
|
|
2
|
+
|
|
1
3
|
from hestia_earth.schema import SchemaType, TermTermType
|
|
2
4
|
from hestia_earth.utils.api import download_hestia
|
|
3
|
-
from hestia_earth.utils.model import find_term_match, linked_node
|
|
4
5
|
from hestia_earth.utils.lookup import download_lookup, extract_grouped_data, get_table_value, column_name
|
|
6
|
+
from hestia_earth.utils.model import find_term_match, linked_node
|
|
5
7
|
from hestia_earth.utils.tools import list_sum, safe_parse_float
|
|
6
8
|
|
|
7
|
-
from ..log import debugMissingLookup
|
|
8
9
|
from . import _term_id, _include_methodModel
|
|
9
10
|
from .term import get_lookup_value
|
|
11
|
+
from ..log import debugMissingLookup
|
|
12
|
+
|
|
13
|
+
download_hestia_cached = cache(download_hestia)
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
def _new_property(term, model=None):
|
|
@@ -26,7 +30,7 @@ def get_property_lookup_value(model: str, term_id: str, column: str):
|
|
|
26
30
|
return get_lookup_value(term, column, model=model, term=term_id)
|
|
27
31
|
|
|
28
32
|
|
|
29
|
-
def find_term_property(term, property: str, default=None) -> dict:
|
|
33
|
+
def find_term_property(term, property: str, default=None, keep_in_memory=False) -> dict:
|
|
30
34
|
"""
|
|
31
35
|
Get the property by `@id` linked to the `Term` in the glossary.
|
|
32
36
|
|
|
@@ -38,15 +42,18 @@ def find_term_property(term, property: str, default=None) -> dict:
|
|
|
38
42
|
The `term.@id` of the property. Example: `nitrogenContent`.
|
|
39
43
|
default : Any
|
|
40
44
|
The default value if the property is not found. Defaults to `None`.
|
|
45
|
+
keep_in_memory: bool
|
|
46
|
+
Should we cache results from download_hestia(). Default False
|
|
41
47
|
|
|
42
48
|
Returns
|
|
43
49
|
-------
|
|
44
50
|
dict
|
|
45
51
|
The property if found, `default` otherwise.
|
|
46
52
|
"""
|
|
53
|
+
download_func = download_hestia_cached if keep_in_memory else download_hestia
|
|
47
54
|
props = term.get('defaultProperties', []) if isinstance(term, dict) else []
|
|
48
55
|
term_id = _term_id(term)
|
|
49
|
-
props = (
|
|
56
|
+
props = (download_func(term_id) or {}).get('defaultProperties', []) if len(props) == 0 and term_id else props
|
|
50
57
|
return find_term_match(props, property, default)
|
|
51
58
|
|
|
52
59
|
|
|
@@ -673,8 +673,8 @@ def get_land_cover_siteTypes():
|
|
|
673
673
|
return search({
|
|
674
674
|
"bool": {
|
|
675
675
|
"must": [
|
|
676
|
-
{"match": {"@type":
|
|
677
|
-
{"match": {"termType":
|
|
676
|
+
{"match": {"@type": SchemaType.TERM.value}},
|
|
677
|
+
{"match": {"termType": TermTermType.LANDCOVER.value}}
|
|
678
678
|
],
|
|
679
679
|
"should": [{"match": {"name": siteType.value}} for siteType in SiteSiteType],
|
|
680
680
|
"minimum_should_match": 1
|
|
@@ -682,13 +682,20 @@ def get_land_cover_siteTypes():
|
|
|
682
682
|
}, limit=LIMIT)
|
|
683
683
|
|
|
684
684
|
|
|
685
|
-
def
|
|
686
|
-
|
|
685
|
+
def get_land_cover_terms():
|
|
686
|
+
"""
|
|
687
|
+
Find all `Land Cover` terms from the Glossary: https://hestia.earth/glossary?termType=landCover
|
|
688
|
+
|
|
689
|
+
Returns
|
|
690
|
+
-------
|
|
691
|
+
List of landCover terms with associated siteTypes.
|
|
692
|
+
"""
|
|
693
|
+
terms = search({
|
|
687
694
|
"bool": {
|
|
688
695
|
"must": [
|
|
689
|
-
{"match": {"@type":
|
|
690
|
-
{"match": {"termType":
|
|
696
|
+
{"match": {"@type": SchemaType.TERM.value}},
|
|
697
|
+
{"match": {"termType": TermTermType.LANDCOVER.value}}
|
|
691
698
|
]
|
|
692
699
|
},
|
|
693
|
-
}, fields=['@id'
|
|
694
|
-
return
|
|
700
|
+
}, limit=LIMIT, fields=['@id'])
|
|
701
|
+
return list(map(lambda n: n["@id"], terms))
|
hestia_earth/models/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
VERSION = '0.64.
|
|
1
|
+
VERSION = '0.64.10'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hestia-earth-models
|
|
3
|
-
Version: 0.64.
|
|
3
|
+
Version: 0.64.10
|
|
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==30.*
|
|
15
|
-
Requires-Dist: hestia-earth.utils>=0.13.
|
|
15
|
+
Requires-Dist: hestia-earth.utils>=0.13.9
|
|
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
|