hestia-earth-models 0.65.11__py3-none-any.whl → 0.67.0__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/cache_sites.py +7 -9
- hestia_earth/models/cml2001Baseline/abioticResourceDepletionFossilFuels.py +23 -54
- hestia_earth/models/cml2001Baseline/resourceUseEnergyDepletionDuringCycle.py +152 -0
- hestia_earth/models/cml2001Baseline/resourceUseEnergyDepletionInputsProduction.py +40 -0
- hestia_earth/models/cml2001Baseline/resourceUseMineralsAndMetalsDuringCycle.py +80 -0
- hestia_earth/models/cml2001Baseline/resourceUseMineralsAndMetalsInputsProduction.py +40 -0
- hestia_earth/models/config/Cycle.json +34 -16
- hestia_earth/models/config/ImpactAssessment.json +1867 -1832
- hestia_earth/models/config/Site.json +4 -1
- hestia_earth/models/cycle/completeness/freshForage.py +10 -2
- hestia_earth/models/cycle/cropResidueManagement.py +3 -1
- hestia_earth/models/cycle/input/hestiaAggregatedData.py +13 -10
- hestia_earth/models/ecoinventV3/__init__.py +2 -1
- hestia_earth/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/__init__.py +4 -3
- hestia_earth/models/environmentalFootprintV3_1/environmentalFootprintSingleOverallScore.py +135 -0
- hestia_earth/models/environmentalFootprintV3_1/marineEutrophicationPotential.py +36 -0
- hestia_earth/models/environmentalFootprintV3_1/scarcityWeightedWaterUse.py +40 -0
- hestia_earth/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/soilQualityIndexLandTransformation.py +17 -6
- hestia_earth/models/geospatialDatabase/{aware.py → awareWaterBasinId.py} +1 -1
- hestia_earth/models/hestia/landCover.py +42 -34
- hestia_earth/models/hestia/residueRemoved.py +80 -0
- hestia_earth/models/hestia/resourceUse_utils.py +43 -29
- hestia_earth/models/impact_assessment/product/value.py +1 -1
- hestia_earth/models/ipcc2019/aboveGroundBiomass.py +34 -13
- hestia_earth/models/ipcc2019/belowGroundBiomass.py +33 -12
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +17 -8
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +7 -4
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +2 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +29 -18
- hestia_earth/models/ipcc2019/pastureGrass_utils.py +8 -1
- hestia_earth/models/log.py +1 -1
- hestia_earth/models/mocking/search-results.json +872 -872
- hestia_earth/models/site/defaultMethodClassification.py +9 -2
- hestia_earth/models/site/defaultMethodClassificationDescription.py +4 -2
- hestia_earth/models/site/management.py +48 -30
- hestia_earth/models/site/pre_checks/cache_geospatialDatabase.py +19 -14
- hestia_earth/models/utils/__init__.py +6 -0
- hestia_earth/models/utils/aggregated.py +13 -10
- hestia_earth/models/utils/array_builders.py +4 -3
- hestia_earth/models/utils/blank_node.py +23 -13
- hestia_earth/models/utils/lookup.py +4 -2
- hestia_earth/models/utils/property.py +5 -2
- hestia_earth/models/version.py +1 -1
- hestia_earth/orchestrator/log.py +11 -0
- hestia_earth/orchestrator/models/__init__.py +8 -3
- hestia_earth/orchestrator/strategies/merge/merge_list.py +17 -6
- {hestia_earth_models-0.65.11.dist-info → hestia_earth_models-0.67.0.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.65.11.dist-info → hestia_earth_models-0.67.0.dist-info}/RECORD +86 -69
- tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +51 -87
- tests/models/cml2001Baseline/test_resourceUseEnergyDepletionDuringCycle.py +103 -0
- tests/models/cml2001Baseline/test_resourceUseEnergyDepletionInputsProduction.py +23 -0
- tests/models/cml2001Baseline/test_resourceUseMineralsAndMetalsDuringCycle.py +58 -0
- tests/models/cml2001Baseline/test_resourceUseMineralsAndMetalsInputsProduction.py +23 -0
- tests/models/environmentalFootprintV3_1/test_environmentalFootprintSingleOverallScore.py +93 -0
- tests/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/test_freshwaterEcotoxicityPotentialCtue.py +6 -5
- tests/models/environmentalFootprintV3_1/test_marineEutrophicationPotential.py +27 -0
- tests/models/environmentalFootprintV3_1/test_scarcityWeightedWaterUse.py +32 -0
- tests/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/test_soilQualityIndexLandOccupation.py +4 -3
- tests/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/test_soilQualityIndexLandTransformation.py +8 -22
- tests/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/test_soilQualityIndexTotalLandUseEffects.py +4 -4
- tests/models/faostat2018/product/test_price.py +1 -1
- tests/models/geospatialDatabase/{test_aware.py → test_awareWaterBasinId.py} +1 -1
- tests/models/hestia/test_landCover.py +2 -1
- tests/models/hestia/test_landTransformation20YearAverageDuringCycle.py +2 -1
- tests/models/hestia/test_residueRemoved.py +20 -0
- tests/models/impact_assessment/test_emissions.py +0 -1
- tests/models/ipcc2019/test_aboveGroundBiomass.py +3 -1
- tests/models/ipcc2019/test_belowGroundBiomass.py +4 -2
- tests/models/ipcc2019/test_organicCarbonPerHa.py +94 -1
- tests/models/site/pre_checks/test_cache_geospatialDatabase.py +22 -0
- tests/models/site/test_defaultMethodClassification.py +6 -0
- tests/models/site/test_defaultMethodClassificationDescription.py +6 -0
- tests/models/site/test_management.py +4 -4
- tests/models/test_cache_sites.py +2 -2
- tests/models/test_config.py +3 -3
- tests/models/test_ecoinventV3.py +0 -1
- tests/models/utils/test_array_builders.py +2 -2
- tests/orchestrator/strategies/merge/test_merge_list.py +11 -1
- /hestia_earth/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/freshwaterEcotoxicityPotentialCtue.py +0 -0
- /hestia_earth/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/soilQualityIndexLandOccupation.py +0 -0
- /hestia_earth/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/soilQualityIndexTotalLandUseEffects.py +0 -0
- /hestia_earth/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/utils.py +0 -0
- {hestia_earth_models-0.65.11.dist-info → hestia_earth_models-0.67.0.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.65.11.dist-info → hestia_earth_models-0.67.0.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.65.11.dist-info → hestia_earth_models-0.67.0.dist-info}/top_level.txt +0 -0
- /tests/models/{environmentalFootprintV3 → environmentalFootprintV3_1}/__init__.py +0 -0
@@ -8,7 +8,7 @@ from .log import logger
|
|
8
8
|
from .utils import CACHE_KEY, cached_value
|
9
9
|
from .utils.site import CACHE_YEARS_KEY
|
10
10
|
from .site.pre_checks.cache_geospatialDatabase import (
|
11
|
-
|
11
|
+
list_vectors, list_rasters, cache_site_results, _should_run
|
12
12
|
)
|
13
13
|
from .geospatialDatabase.utils import (
|
14
14
|
CACHE_VALUE as CACHE_GEOSPATIAL_KEY, CACHE_AREA_SIZE,
|
@@ -115,8 +115,9 @@ def _group_sites(sites: dict, check_has_cache: bool = True):
|
|
115
115
|
}
|
116
116
|
|
117
117
|
|
118
|
-
def _run(sites: list, years: list = [],
|
119
|
-
rasters
|
118
|
+
def _run(sites: list, years: list = [], years_only: bool = False):
|
119
|
+
rasters = list_rasters(years=years, years_only=years_only)
|
120
|
+
vectors = [] if years_only else list_vectors(sites)
|
120
121
|
filtered_data = _group_sites(sites, not years_only)
|
121
122
|
return flatten([
|
122
123
|
_run_values(filtered_data.get(param_type), param_type, rasters, vectors, years)
|
@@ -124,7 +125,7 @@ def _run(sites: list, years: list = [], include_region: bool = False, years_only
|
|
124
125
|
])
|
125
126
|
|
126
127
|
|
127
|
-
def run(sites: list, years: list = None
|
128
|
+
def run(sites: list, years: list = None):
|
128
129
|
"""
|
129
130
|
Run all queries at once for the list of provided Sites.
|
130
131
|
Note: Earth Engine needs to be initiliased with `init_gee()` before running this function.
|
@@ -135,11 +136,8 @@ def run(sites: list, years: list = None, include_region: bool = False):
|
|
135
136
|
List of Site as dict.
|
136
137
|
years : list[int]
|
137
138
|
List of related years to fetch annual data.
|
138
|
-
include_region : bool
|
139
|
-
Prefecth region IDs.
|
140
|
-
This will cache region-level data and will make the request slower. Only use if needed.
|
141
139
|
"""
|
142
|
-
sites = _run(sites
|
140
|
+
sites = _run(sites)
|
143
141
|
|
144
142
|
# avoid memory limit errors by running only a few years at a time
|
145
143
|
unique_years = sorted(list(set(years)))
|
@@ -149,6 +147,6 @@ def run(sites: list, years: list = None, include_region: bool = False):
|
|
149
147
|
for batch_index in batches:
|
150
148
|
logger.info(f"Processing sites in batch {batch_index + 1} of {len(batches)}...")
|
151
149
|
sub_years = unique_years[batch_index:batch_index + batch_size]
|
152
|
-
sites = _run(sites, sub_years,
|
150
|
+
sites = _run(sites, sub_years, years_only=True)
|
153
151
|
|
154
152
|
return sites
|
@@ -10,23 +10,18 @@ are converted into MJ.
|
|
10
10
|
|
11
11
|
Source : [Life Cycle Assessment & the EF methods - Comprehensive coverage of impacts](https://green-business.ec.europa.eu/environmental-footprint-methods/life-cycle-assessment-ef-methods_en)
|
12
12
|
|
13
|
-
The model accepts any non-renewable energy term
|
13
|
+
The model accepts any non-renewable energy term in MegaJoules, or that has been converted to MegaJoules.
|
14
14
|
|
15
15
|
Source: [JRC Technical reports Suggestions for updating the Product Environmental Footprint (PEF) method](https://eplca.jrc.ec.europa.eu/permalink/PEF_method.pdf#%5B%7B%22num%22%3A80%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C68%2C363%2C0%5D)
|
16
16
|
|
17
17
|
Source: [Differences between EF model versions](https://eplca.jrc.ec.europa.eu/EFVersioning.html)
|
18
18
|
""" # noqa: E501
|
19
19
|
from itertools import chain
|
20
|
-
from typing import Optional
|
21
|
-
|
22
|
-
from hestia_earth.schema import TermTermType
|
23
20
|
from hestia_earth.utils.lookup import download_lookup, column_name
|
24
|
-
from hestia_earth.utils.model import filter_list_term_type
|
25
21
|
from hestia_earth.utils.tools import list_sum, flatten
|
26
22
|
|
27
23
|
from hestia_earth.models.log import logShouldRun, logRequirements, log_as_table
|
28
24
|
from . import MODEL
|
29
|
-
from ..utils.blank_node import convert_unit
|
30
25
|
from ..utils.constant import Units
|
31
26
|
from ..utils.indicator import _new_indicator
|
32
27
|
from ..utils.lookup import _node_value
|
@@ -38,29 +33,13 @@ REQUIREMENTS = {
|
|
38
33
|
"@type": "Indicator",
|
39
34
|
"term.termType": "resourceUse",
|
40
35
|
"term.@id": ["resourceUseEnergyDepletionInputsProduction", "resourceUseEnergyDepletionDuringCycle"],
|
36
|
+
"term.units": "MJ",
|
41
37
|
"value": "> 0",
|
42
38
|
"inputs":
|
43
39
|
{
|
44
40
|
"@type": "Input",
|
45
41
|
"term.name": "non-renewable\" energy terms only,\"",
|
46
|
-
"term.
|
47
|
-
"term.termType": ["fuel", "electricity"],
|
48
|
-
"optional": {
|
49
|
-
"defaultProperties": [
|
50
|
-
{
|
51
|
-
"@type": "Property",
|
52
|
-
"value": "",
|
53
|
-
"term.@id": "energyContentHigherHeatingValue",
|
54
|
-
"term.units": "MJ / kg"
|
55
|
-
},
|
56
|
-
{
|
57
|
-
"@type": "Property",
|
58
|
-
"value": "",
|
59
|
-
"term.@id": "density",
|
60
|
-
"term.units": "kg / m3"
|
61
|
-
}
|
62
|
-
]
|
63
|
-
}
|
42
|
+
"term.termType": ["fuel", "electricity"]
|
64
43
|
}
|
65
44
|
}
|
66
45
|
]
|
@@ -68,8 +47,8 @@ REQUIREMENTS = {
|
|
68
47
|
}
|
69
48
|
|
70
49
|
LOOKUPS = {
|
71
|
-
"fuel": ["
|
72
|
-
"electricity": ["
|
50
|
+
"fuel": ["consideredFossilFuelUnderCml2001Baseline"],
|
51
|
+
"electricity": ["consideredFossilFuelUnderCml2001Baseline"]
|
73
52
|
}
|
74
53
|
|
75
54
|
RETURNS = {
|
@@ -79,39 +58,31 @@ RETURNS = {
|
|
79
58
|
}
|
80
59
|
TERM_ID = 'abioticResourceDepletionFossilFuels'
|
81
60
|
|
82
|
-
|
83
|
-
|
84
|
-
INPUTS_TYPES_UNITS = {
|
85
|
-
TermTermType.FUEL.value: [Units.KG.value, Units.M3.value, Units.MJ.value],
|
86
|
-
TermTermType.ELECTRICITY.value: [Units.KW_H.value, Units.MJ.value]
|
87
|
-
}
|
61
|
+
_ENERGY_CARRIERS_TERMIDS = REQUIREMENTS['ImpactAssessment']['emissionsResourceUse'][0]['term.@id']
|
88
62
|
|
89
63
|
|
90
|
-
def
|
64
|
+
def get_all_non_renewable_terms(lookup_file_name: str, column: str) -> list:
|
91
65
|
"""
|
92
66
|
returns all non renewable term ids in lookup files like `electricity.csv` or `fuel.csv`
|
93
67
|
"""
|
94
68
|
lookup = download_lookup(lookup_file_name)
|
95
|
-
results = lookup[
|
96
|
-
lookup[column_name("abioticResourceDepletionFossilFuelsCml2001Baseline")] == True # noqa: E712
|
97
|
-
]["termid"]
|
69
|
+
results = lookup[lookup[column_name(column)] == True]["termid"] # noqa: E712
|
98
70
|
return list(map(str, results))
|
99
71
|
|
100
72
|
|
101
73
|
def _valid_resource_indicator(resource: dict) -> bool:
|
102
|
-
return
|
103
|
-
|
104
|
-
_node_value(resource)
|
74
|
+
return (
|
75
|
+
len(resource.get('inputs', [])) == 1 and
|
76
|
+
isinstance(_node_value(resource), (int, float)) and
|
77
|
+
_node_value(resource) > 0 and
|
78
|
+
resource.get("term", {}).get("units", "") == Units.MJ.value
|
79
|
+
)
|
105
80
|
|
106
81
|
|
107
82
|
def _valid_input(input: dict) -> bool:
|
108
83
|
return input.get("@id") in list(chain.from_iterable([
|
109
|
-
|
110
|
-
]))
|
111
|
-
|
112
|
-
|
113
|
-
def _get_value_in_mj(input: dict, indicator: dict) -> Optional[float]:
|
114
|
-
return convert_unit(input, dest_unit=Units.MJ, node_value=_node_value(indicator)) if _valid_input(input) else None
|
84
|
+
get_all_non_renewable_terms(f"{termType}.csv", columns[0]) for termType, columns in LOOKUPS.items()
|
85
|
+
]))
|
115
86
|
|
116
87
|
|
117
88
|
def _indicator(value: float):
|
@@ -126,9 +97,9 @@ def _run(energy_resources_in_mj: list):
|
|
126
97
|
|
127
98
|
def _should_run(impact_assessment: dict) -> tuple[bool, list]:
|
128
99
|
emissions_resource_use = [
|
129
|
-
resource for resource in
|
130
|
-
|
131
|
-
|
100
|
+
resource for resource in impact_assessment.get('emissionsResourceUse', [])
|
101
|
+
if resource.get('term', {}).get('@id') in _ENERGY_CARRIERS_TERMIDS
|
102
|
+
]
|
132
103
|
|
133
104
|
has_resource_use_entries = bool(emissions_resource_use)
|
134
105
|
|
@@ -140,11 +111,8 @@ def _should_run(impact_assessment: dict) -> tuple[bool, list]:
|
|
140
111
|
"input-term-type": input.get('termType'),
|
141
112
|
"indicator-term-id": resource_indicator['term']['@id'],
|
142
113
|
"indicator-is-valid": _valid_resource_indicator(resource_indicator),
|
143
|
-
"input": input,
|
144
114
|
"indicator-input-is-valid": _valid_input(input),
|
145
|
-
"value": _node_value(resource_indicator),
|
146
|
-
"input-unit": input.get('units'),
|
147
|
-
"value-in-MJ": _get_value_in_mj(input, resource_indicator)
|
115
|
+
"value-in-MJ": _node_value(resource_indicator) if _valid_input(input) else None,
|
148
116
|
} for input in resource_indicator['inputs'] or [{}]]
|
149
117
|
for resource_indicator in emissions_resource_use
|
150
118
|
]
|
@@ -157,8 +125,9 @@ def _should_run(impact_assessment: dict) -> tuple[bool, list]:
|
|
157
125
|
|
158
126
|
energy_resources_in_mj = [energy_input['value-in-MJ'] for energy_input in resource_uses_unpacked]
|
159
127
|
valid_energy_resources_in_mj = [value for value in energy_resources_in_mj if value is not None]
|
160
|
-
all_inputs_have_valid_mj_value = all(
|
161
|
-
|
128
|
+
all_inputs_have_valid_mj_value = all(
|
129
|
+
[energy is not None for energy in energy_resources_in_mj] + [bool(energy_resources_in_mj)]
|
130
|
+
)
|
162
131
|
|
163
132
|
logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
|
164
133
|
has_resource_use_entries=has_resource_use_entries,
|
@@ -0,0 +1,152 @@
|
|
1
|
+
"""
|
2
|
+
This model converts all "energy" terms found in a `Cycle > Inputs` to `MJ` using optional
|
3
|
+
`energyContentHigherHeatingValue` and `density` properties or the term's "defaultProperties",
|
4
|
+
aggregates them, and places them inside a 'resourceUseEnergyDepletionDuringCycle' indicator per aggregated input id.
|
5
|
+
"""
|
6
|
+
from collections import defaultdict
|
7
|
+
from itertools import groupby
|
8
|
+
from typing import Tuple, Optional
|
9
|
+
|
10
|
+
from hestia_earth.schema import TermTermType
|
11
|
+
from hestia_earth.utils.model import filter_list_term_type
|
12
|
+
from hestia_earth.utils.tools import list_sum
|
13
|
+
|
14
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
15
|
+
from hestia_earth.models.utils import Units
|
16
|
+
from hestia_earth.models.utils.blank_node import convert_unit
|
17
|
+
from hestia_earth.models.utils.indicator import _new_indicator
|
18
|
+
from . import MODEL
|
19
|
+
from ..utils.lookup import _node_value
|
20
|
+
|
21
|
+
REQUIREMENTS = {
|
22
|
+
"Cycle": {
|
23
|
+
"inputs": [
|
24
|
+
{
|
25
|
+
"@type": "Input",
|
26
|
+
"term.units": ["kg", "m3", "kWh", "MJ"],
|
27
|
+
"term.termType": ["fuel", "electricity"],
|
28
|
+
"value": ">0",
|
29
|
+
"optional": {
|
30
|
+
"properties": [
|
31
|
+
{
|
32
|
+
"@type": "Property",
|
33
|
+
"value": "",
|
34
|
+
"term.@id": "energyContentHigherHeatingValue",
|
35
|
+
"term.units": "MJ / kg"
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"@type": "Property",
|
39
|
+
"value": "",
|
40
|
+
"term.@id": "density",
|
41
|
+
"term.units": "kg / m3"
|
42
|
+
}
|
43
|
+
]
|
44
|
+
}
|
45
|
+
}
|
46
|
+
]
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
RETURNS = {
|
51
|
+
"Indicator": [
|
52
|
+
{
|
53
|
+
"value": "",
|
54
|
+
"inputs": ""
|
55
|
+
}
|
56
|
+
]
|
57
|
+
}
|
58
|
+
|
59
|
+
LOOKUPS = {
|
60
|
+
"fuel": ["energyContentHigherHeatingValue", "density"]
|
61
|
+
}
|
62
|
+
|
63
|
+
TERM_ID = 'resourceUseEnergyDepletionDuringCycle'
|
64
|
+
|
65
|
+
INPUTS_TYPES_UNITS = {
|
66
|
+
TermTermType.FUEL.value: [Units.KG.value, Units.M3.value, Units.MJ.value],
|
67
|
+
TermTermType.ELECTRICITY.value: [Units.KW_H.value, Units.MJ.value]
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
def _indicator(values: list[float], cycle_input: dict):
|
72
|
+
indicator = _new_indicator(TERM_ID, MODEL)
|
73
|
+
indicator['value'] = list_sum(values)
|
74
|
+
indicator['inputs'] = [cycle_input | {"units": "MJ"}]
|
75
|
+
return indicator
|
76
|
+
|
77
|
+
|
78
|
+
def _run(grouped_energy_terms: dict):
|
79
|
+
indicators = [_indicator(values=[input['value-in-MJ'] for input in energy_term_group_vals],
|
80
|
+
cycle_input=energy_term_group_vals[0]['input']['term'])
|
81
|
+
for energy_term_group_vals in grouped_energy_terms.values()]
|
82
|
+
return indicators
|
83
|
+
|
84
|
+
|
85
|
+
def _valid_input(input: dict) -> bool:
|
86
|
+
return (isinstance(_node_value(input), (int, float))
|
87
|
+
and _node_value(input) > 0
|
88
|
+
and input.get("term", {}).get("units", "") in INPUTS_TYPES_UNITS.get(input.get("term", {}).get("termType")))
|
89
|
+
|
90
|
+
|
91
|
+
def _get_value_in_mj(input: dict) -> Optional[float]:
|
92
|
+
return convert_unit(input, dest_unit=Units.MJ, node_value=_node_value(input)) if _valid_input(input) else None
|
93
|
+
|
94
|
+
|
95
|
+
def _should_run(cycle: dict) -> Tuple[bool, dict]:
|
96
|
+
energy_input_terms = filter_list_term_type(cycle.get('inputs', []), [TermTermType.FUEL, TermTermType.ELECTRICITY])
|
97
|
+
|
98
|
+
has_energy_terms = bool(energy_input_terms)
|
99
|
+
|
100
|
+
energy_input_terms_unpacked = [
|
101
|
+
{
|
102
|
+
"id": input.get('term', {}).get('@id'),
|
103
|
+
"termType": input.get('term', {}).get('termType'),
|
104
|
+
"input-is-valid": _valid_input(input),
|
105
|
+
"value": _node_value(input),
|
106
|
+
"input": input,
|
107
|
+
"units": input.get('term', {}).get('units'),
|
108
|
+
"value-in-MJ": _get_value_in_mj(input)
|
109
|
+
}
|
110
|
+
for input in energy_input_terms
|
111
|
+
]
|
112
|
+
|
113
|
+
has_valid_input_requirements = all([energy_input['input-is-valid'] for energy_input in energy_input_terms_unpacked])
|
114
|
+
|
115
|
+
energy_input_terms_valid = [e for e in energy_input_terms_unpacked if e["value-in-MJ"] is not None]
|
116
|
+
|
117
|
+
energy_input_terms_in_mj = [energy_input['value-in-MJ'] for energy_input in energy_input_terms_unpacked]
|
118
|
+
all_inputs_have_valid_mj_value = all([mj_value is not None for mj_value in energy_input_terms_in_mj]
|
119
|
+
) and bool(energy_input_terms_in_mj)
|
120
|
+
|
121
|
+
grouped_energy_terms = defaultdict(list)
|
122
|
+
for k, v in groupby(energy_input_terms_valid, key=lambda x: x.get('id')):
|
123
|
+
grouped_energy_terms[k].extend(list(v))
|
124
|
+
|
125
|
+
logs = [
|
126
|
+
{
|
127
|
+
'id': input.get('@id'),
|
128
|
+
'units': input.get('units'),
|
129
|
+
'termType': input.get('termType'),
|
130
|
+
'value': input.get('value'),
|
131
|
+
'value-in-MJ': input.get('value-in-MJ'),
|
132
|
+
'properties': " ".join([
|
133
|
+
f"{p.get('term', {}).get('@id')}= {p.get('value')} ({p.get('term', {}).get('units')})"
|
134
|
+
for p in input.get('properties', [])
|
135
|
+
])
|
136
|
+
} for input in energy_input_terms_unpacked
|
137
|
+
]
|
138
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
139
|
+
has_energy_terms=has_energy_terms,
|
140
|
+
has_valid_input_requirements=has_valid_input_requirements,
|
141
|
+
all_inputs_have_valid_mj_value=all_inputs_have_valid_mj_value,
|
142
|
+
energy_resources_used=log_as_table(logs))
|
143
|
+
|
144
|
+
should_run = all([has_valid_input_requirements, all_inputs_have_valid_mj_value])
|
145
|
+
|
146
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
147
|
+
return should_run, grouped_energy_terms
|
148
|
+
|
149
|
+
|
150
|
+
def run(cycle: dict):
|
151
|
+
should_run, grouped_energy_terms = _should_run(cycle)
|
152
|
+
return _run(grouped_energy_terms) if should_run else []
|
@@ -0,0 +1,40 @@
|
|
1
|
+
from hestia_earth.models.linkedImpactAssessment.utils import run_inputs_production
|
2
|
+
|
3
|
+
REQUIREMENTS = {
|
4
|
+
"ImpactAssessment": {
|
5
|
+
"product": {"@type": "Term"},
|
6
|
+
"cycle": {
|
7
|
+
"@type": "Cycle",
|
8
|
+
"products": [{
|
9
|
+
"@type": "Product",
|
10
|
+
"primary": "True",
|
11
|
+
"value": "> 0",
|
12
|
+
"economicValueShare": "> 0"
|
13
|
+
}],
|
14
|
+
"inputs": [{
|
15
|
+
"@type": "Input",
|
16
|
+
"impactAssessment": {
|
17
|
+
"@type": "ImpactAssessment",
|
18
|
+
"emissionsResourceUse": [{
|
19
|
+
"@type": "Indicator",
|
20
|
+
"term.@id": [
|
21
|
+
"resourceUseEnergyDepletionDuringCycle",
|
22
|
+
"resourceUseEnergyDepletionInputsProduction"
|
23
|
+
],
|
24
|
+
"value": "> 0"
|
25
|
+
}]
|
26
|
+
}
|
27
|
+
}]
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
RETURNS = {
|
32
|
+
"Indicator": [{
|
33
|
+
"value": "",
|
34
|
+
"inputs": "units in MJ"
|
35
|
+
}]
|
36
|
+
}
|
37
|
+
TERM_ID = 'resourceUseEnergyDepletionInputsProduction'
|
38
|
+
|
39
|
+
|
40
|
+
def run(impact_assessment: dict): return run_inputs_production(impact_assessment, TERM_ID)
|
@@ -0,0 +1,80 @@
|
|
1
|
+
"""
|
2
|
+
This model converts most abiotic resources terms found in a `Cycle > Inputs`, aggregates them,
|
3
|
+
and converts them to one indicator per input.
|
4
|
+
"""
|
5
|
+
from collections import defaultdict
|
6
|
+
from itertools import groupby
|
7
|
+
from typing import Tuple
|
8
|
+
from hestia_earth.schema import TermTermType
|
9
|
+
from hestia_earth.utils.model import filter_list_term_type
|
10
|
+
from hestia_earth.utils.tools import list_sum
|
11
|
+
|
12
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
13
|
+
from hestia_earth.models.utils import _filter_list_term_unit, Units
|
14
|
+
from hestia_earth.models.utils.blank_node import _sum_nodes_value
|
15
|
+
from hestia_earth.models.utils.indicator import _new_indicator
|
16
|
+
from . import MODEL
|
17
|
+
|
18
|
+
REQUIREMENTS = {
|
19
|
+
"Cycle": {
|
20
|
+
"inputs": [
|
21
|
+
{
|
22
|
+
"@type": "Input",
|
23
|
+
"term.units": "kg",
|
24
|
+
"term.termType": ["material", "soilAmendment", "otherInorganicChemical"]}
|
25
|
+
]
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
RETURNS = {
|
30
|
+
"Indicator": [{
|
31
|
+
"value": "",
|
32
|
+
"inputs": ""
|
33
|
+
}]
|
34
|
+
}
|
35
|
+
TERM_ID = 'resourceUseMineralsAndMetalsDuringCycle'
|
36
|
+
|
37
|
+
authorised_term_types = [TermTermType.MATERIAL, TermTermType.SOILAMENDMENT, TermTermType.OTHERINORGANICCHEMICAL]
|
38
|
+
|
39
|
+
|
40
|
+
def _indicator(value: list[float], cycle_input: dict):
|
41
|
+
indicator = _new_indicator(TERM_ID, MODEL)
|
42
|
+
indicator['value'] = list_sum(value)
|
43
|
+
indicator['inputs'] = [cycle_input]
|
44
|
+
return indicator
|
45
|
+
|
46
|
+
|
47
|
+
def _run(grouped_abiotic_terms: dict):
|
48
|
+
indicators = [
|
49
|
+
_indicator(value=_sum_nodes_value(abiotic_term_group_vals),
|
50
|
+
cycle_input=abiotic_term_group_vals[0]['term'])
|
51
|
+
for abiotic_term_group_vals in grouped_abiotic_terms.values()
|
52
|
+
]
|
53
|
+
return indicators
|
54
|
+
|
55
|
+
|
56
|
+
def _should_run(cycle: dict) -> Tuple[bool, dict]:
|
57
|
+
abiotic_terms = filter_list_term_type(cycle.get('inputs', []), authorised_term_types)
|
58
|
+
abiotic_terms_valid_units = _filter_list_term_unit(abiotic_terms, Units.KG)
|
59
|
+
|
60
|
+
has_abiotic_terms = bool(abiotic_terms)
|
61
|
+
has_valid_terms = bool(abiotic_terms_valid_units)
|
62
|
+
|
63
|
+
grouped_abiotic_terms = defaultdict(list)
|
64
|
+
for k, v in groupby(abiotic_terms_valid_units,
|
65
|
+
key=lambda x: (x['term']['@id'], x['term']['units'], x['term']['termType'])):
|
66
|
+
grouped_abiotic_terms[k].extend(list(v))
|
67
|
+
|
68
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
69
|
+
has_abiotic_terms=has_abiotic_terms,
|
70
|
+
has_valid_terms=has_valid_terms,
|
71
|
+
)
|
72
|
+
|
73
|
+
should_run = all([has_valid_terms])
|
74
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
75
|
+
return should_run, grouped_abiotic_terms
|
76
|
+
|
77
|
+
|
78
|
+
def run(cycle: dict):
|
79
|
+
should_run, grouped_abiotic_terms = _should_run(cycle)
|
80
|
+
return _run(grouped_abiotic_terms) if should_run else []
|
@@ -0,0 +1,40 @@
|
|
1
|
+
from hestia_earth.models.linkedImpactAssessment.utils import run_inputs_production
|
2
|
+
|
3
|
+
REQUIREMENTS = {
|
4
|
+
"ImpactAssessment": {
|
5
|
+
"product": {"@type": "Term"},
|
6
|
+
"cycle": {
|
7
|
+
"@type": "Cycle",
|
8
|
+
"products": [{
|
9
|
+
"@type": "Product",
|
10
|
+
"primary": "True",
|
11
|
+
"value": "> 0",
|
12
|
+
"economicValueShare": "> 0"
|
13
|
+
}],
|
14
|
+
"inputs": [{
|
15
|
+
"@type": "Input",
|
16
|
+
"impactAssessment": {
|
17
|
+
"@type": "ImpactAssessment",
|
18
|
+
"emissionsResourceUse": [{
|
19
|
+
"@type": "Indicator",
|
20
|
+
"term.@id": [
|
21
|
+
"resourceUseMineralsAndMetalsDuringCycle",
|
22
|
+
"resourceUseMineralsAndMetalsInputsProduction"
|
23
|
+
],
|
24
|
+
"value": "> 0"
|
25
|
+
}]
|
26
|
+
}
|
27
|
+
}]
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
RETURNS = {
|
32
|
+
"Indicator": [{
|
33
|
+
"value": "",
|
34
|
+
"inputs": ""
|
35
|
+
}]
|
36
|
+
}
|
37
|
+
TERM_ID = 'resourceUseMineralsAndMetalsInputsProduction'
|
38
|
+
|
39
|
+
|
40
|
+
def run(impact_assessment: dict): return run_inputs_production(impact_assessment, TERM_ID)
|
@@ -166,6 +166,14 @@
|
|
166
166
|
"mergeStrategy": "list",
|
167
167
|
"stage": 1
|
168
168
|
},
|
169
|
+
{
|
170
|
+
"key": "practices",
|
171
|
+
"model": "hestia",
|
172
|
+
"value": "residueRemoved",
|
173
|
+
"runStrategy": "add_blank_node_if_missing",
|
174
|
+
"mergeStrategy": "list",
|
175
|
+
"stage": 1
|
176
|
+
},
|
169
177
|
{
|
170
178
|
"key": "practices",
|
171
179
|
"model": "cycle",
|
@@ -287,22 +295,6 @@
|
|
287
295
|
"mergeStrategy": "list",
|
288
296
|
"stage": 1
|
289
297
|
},
|
290
|
-
{
|
291
|
-
"key": "inputs",
|
292
|
-
"model": "faostat2018",
|
293
|
-
"value": "seed",
|
294
|
-
"runStrategy": "add_blank_node_if_missing",
|
295
|
-
"mergeStrategy": "list",
|
296
|
-
"stage": 1
|
297
|
-
},
|
298
|
-
{
|
299
|
-
"key": "inputs",
|
300
|
-
"model": "pooreNemecek2018",
|
301
|
-
"value": "saplingsDepreciatedAmountPerCycle",
|
302
|
-
"runStrategy": "add_blank_node_if_missing",
|
303
|
-
"mergeStrategy": "list",
|
304
|
-
"stage": 1
|
305
|
-
},
|
306
298
|
{
|
307
299
|
"key": "practices",
|
308
300
|
"model": "cycle",
|
@@ -441,6 +433,32 @@
|
|
441
433
|
"stage": 1
|
442
434
|
}
|
443
435
|
],
|
436
|
+
[
|
437
|
+
{
|
438
|
+
"key": "inputs",
|
439
|
+
"model": "faostat2018",
|
440
|
+
"value": "seed",
|
441
|
+
"runStrategy": "add_blank_node_if_missing",
|
442
|
+
"mergeStrategy": "list",
|
443
|
+
"stage": 1
|
444
|
+
},
|
445
|
+
{
|
446
|
+
"key": "inputs",
|
447
|
+
"model": "pooreNemecek2018",
|
448
|
+
"value": "saplingsDepreciatedAmountPerCycle",
|
449
|
+
"runStrategy": "add_blank_node_if_missing",
|
450
|
+
"mergeStrategy": "list",
|
451
|
+
"stage": 1
|
452
|
+
}
|
453
|
+
],
|
454
|
+
{
|
455
|
+
"key": "completeness",
|
456
|
+
"model": "cycle",
|
457
|
+
"value": "completeness",
|
458
|
+
"runStrategy": "always",
|
459
|
+
"mergeStrategy": "node",
|
460
|
+
"stage": 1
|
461
|
+
},
|
444
462
|
[
|
445
463
|
{
|
446
464
|
"key": "animals",
|