hestia-earth-models 0.75.1__py3-none-any.whl → 0.75.2__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/config/Cycle.json +15 -0
- hestia_earth/models/cycle/product/economicValueShare.py +4 -4
- hestia_earth/models/geospatialDatabase/histosol.py +31 -11
- hestia_earth/models/hestia/aboveGroundCropResidueTotal.py +2 -2
- hestia_earth/models/hestia/soilClassification.py +31 -13
- hestia_earth/models/ipcc2019/animal/pastureGrass.py +3 -1
- hestia_earth/models/ipcc2019/burning_utils.py +406 -4
- hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +26 -8
- hestia_earth/models/ipcc2019/ch4ToAirOrganicSoilCultivation.py +8 -11
- hestia_earth/models/ipcc2019/co2ToAirOrganicSoilCultivation.py +9 -12
- hestia_earth/models/ipcc2019/emissionsToAirOrganicSoilBurning.py +516 -0
- hestia_earth/models/ipcc2019/n2OToAirOrganicSoilCultivationDirect.py +10 -13
- hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +56 -433
- hestia_earth/models/ipcc2019/organicSoilCultivation_utils.py +2 -2
- hestia_earth/models/ipcc2019/pastureGrass.py +3 -1
- hestia_earth/models/mocking/search-results.json +1 -1
- hestia_earth/models/utils/blank_node.py +68 -0
- hestia_earth/models/utils/impact_assessment.py +3 -0
- hestia_earth/models/version.py +1 -1
- hestia_earth/orchestrator/strategies/merge/merge_node.py +32 -2
- {hestia_earth_models-0.75.1.dist-info → hestia_earth_models-0.75.2.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.75.1.dist-info → hestia_earth_models-0.75.2.dist-info}/RECORD +25 -24
- {hestia_earth_models-0.75.1.dist-info → hestia_earth_models-0.75.2.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.75.1.dist-info → hestia_earth_models-0.75.2.dist-info}/licenses/LICENSE +0 -0
- {hestia_earth_models-0.75.1.dist-info → hestia_earth_models-0.75.2.dist-info}/top_level.txt +0 -0
|
@@ -1294,6 +1294,21 @@
|
|
|
1294
1294
|
},
|
|
1295
1295
|
"stage": 2
|
|
1296
1296
|
},
|
|
1297
|
+
{
|
|
1298
|
+
"key": "emissions",
|
|
1299
|
+
"model": "ipcc2019",
|
|
1300
|
+
"value": "emissionsToAirOrganicSoilBurning",
|
|
1301
|
+
"runStrategy": "always",
|
|
1302
|
+
"runArgs": {
|
|
1303
|
+
"runNonMeasured": true,
|
|
1304
|
+
"runNonAddedTerm": true
|
|
1305
|
+
},
|
|
1306
|
+
"mergeStrategy": "list",
|
|
1307
|
+
"mergeArgs": {
|
|
1308
|
+
"replaceThreshold": ["value", 0.01]
|
|
1309
|
+
},
|
|
1310
|
+
"stage": 2
|
|
1311
|
+
},
|
|
1297
1312
|
{
|
|
1298
1313
|
"key": "emissions",
|
|
1299
1314
|
"model": "schmidt2007",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from hestia_earth.utils.model import find_term_match
|
|
2
|
-
from hestia_earth.utils.tools import list_sum
|
|
2
|
+
from hestia_earth.utils.tools import list_sum, to_precision
|
|
3
3
|
|
|
4
4
|
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
5
5
|
from hestia_earth.models.utils.term import get_lookup_value
|
|
@@ -43,7 +43,7 @@ MIN_COMPLETE_VALUE = 80 # when the products are complete lower the min threshol
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
def _product(product: dict, value: float):
|
|
46
|
-
return product | {MODEL_KEY: value}
|
|
46
|
+
return product | {MODEL_KEY: to_precision(value, 2 if value < 1 else 3 if value < 10 else 4)}
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _is_complete(cycle: dict): return cycle.get('completeness', {}).get('product', False)
|
|
@@ -57,11 +57,11 @@ def _total_evs(products: list): return sum([p.get(MODEL_KEY, 0) for p in product
|
|
|
57
57
|
|
|
58
58
|
def _product_with_value(product: dict):
|
|
59
59
|
value = product.get(MODEL_KEY, lookup_share(MODEL_KEY, product))
|
|
60
|
-
return product
|
|
60
|
+
return _product(product, value) if value is not None else product
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def _rescale_value(products: list, total: float):
|
|
64
|
-
return list(map(lambda p:
|
|
64
|
+
return list(map(lambda p: _product(p, p.get(MODEL_KEY) * 100 / total), products))
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
def _should_run_by_default(cycle: dict, products: list):
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
from hestia_earth.schema import MeasurementMethodClassification
|
|
1
|
+
from hestia_earth.schema import MeasurementMethodClassification, TermTermType
|
|
2
|
+
from hestia_earth.utils.model import filter_list_term_type
|
|
3
|
+
from hestia_earth.utils.blank_node import get_node_value
|
|
4
|
+
from hestia_earth.utils.tools import pick
|
|
2
5
|
|
|
3
|
-
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
|
-
from hestia_earth.models.utils.measurement import _new_measurement
|
|
6
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
7
|
+
from hestia_earth.models.utils.measurement import _new_measurement
|
|
5
8
|
from hestia_earth.models.utils.source import get_source
|
|
6
9
|
from .utils import download, has_geospatial_data, should_download
|
|
7
10
|
from . import MODEL
|
|
@@ -16,10 +19,10 @@ REQUIREMENTS = {
|
|
|
16
19
|
"none": {
|
|
17
20
|
"measurements": [{
|
|
18
21
|
"@type": "Measurement",
|
|
19
|
-
"value": "
|
|
22
|
+
"value": "> 0",
|
|
20
23
|
"depthUpper": "0",
|
|
21
24
|
"depthLower": "30",
|
|
22
|
-
"term.termType": "soilType"
|
|
25
|
+
"term.termType": ["soilType", "usdaSoilType"]
|
|
23
26
|
}]
|
|
24
27
|
}
|
|
25
28
|
}
|
|
@@ -39,12 +42,14 @@ EE_PARAMS = {
|
|
|
39
42
|
'reducer': 'mean'
|
|
40
43
|
}
|
|
41
44
|
BIBLIO_TITLE = 'Harmonized World Soil Database Version 1.2. Food and Agriculture Organization of the United Nations (FAO).' # noqa: E501
|
|
45
|
+
_DEPTH_UPPER = 0
|
|
46
|
+
_DEPTH_LOWER = 30
|
|
42
47
|
|
|
43
48
|
|
|
44
49
|
def _measurement(site: dict, value: float):
|
|
45
50
|
measurement = _new_measurement(term=TERM_ID, value=value)
|
|
46
|
-
measurement['depthUpper'] =
|
|
47
|
-
measurement['depthLower'] =
|
|
51
|
+
measurement['depthUpper'] = _DEPTH_UPPER
|
|
52
|
+
measurement['depthLower'] = _DEPTH_LOWER
|
|
48
53
|
measurement['methodClassification'] = MeasurementMethodClassification.GEOSPATIAL_DATASET.value
|
|
49
54
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
50
55
|
|
|
@@ -58,15 +63,30 @@ def _should_run(site: dict):
|
|
|
58
63
|
contains_geospatial_data = has_geospatial_data(site)
|
|
59
64
|
below_max_area_size = should_download(TERM_ID, site)
|
|
60
65
|
|
|
61
|
-
|
|
66
|
+
measurements = filter_list_term_type(site.get('measurements', []), [
|
|
67
|
+
TermTermType.SOILTYPE,
|
|
68
|
+
TermTermType.USDASOILTYPE
|
|
69
|
+
])
|
|
70
|
+
measurements = [m for m in measurements if all([
|
|
71
|
+
m.get('depthUpper', -1) == _DEPTH_UPPER,
|
|
72
|
+
m.get('depthLower', 0) == _DEPTH_LOWER,
|
|
73
|
+
get_node_value(m) > 0
|
|
74
|
+
])]
|
|
75
|
+
has_soil_type_measurements = len(measurements) > 0
|
|
62
76
|
|
|
63
77
|
logRequirements(site, model=MODEL, term=TERM_ID,
|
|
64
78
|
contains_geospatial_data=contains_geospatial_data,
|
|
65
79
|
below_max_area_size=below_max_area_size,
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
has_soil_type_measurements=has_soil_type_measurements,
|
|
81
|
+
soil_type_measurements=log_as_table([
|
|
82
|
+
{
|
|
83
|
+
'id': m.get('term', {}).get('@id'),
|
|
84
|
+
'termType': m.get('term', {}).get('termType'),
|
|
85
|
+
'value': get_node_value(m)
|
|
86
|
+
} | pick(m, ['depthUpper', 'depthLower']) for m in measurements
|
|
87
|
+
]))
|
|
68
88
|
|
|
69
|
-
should_run = all([contains_geospatial_data, below_max_area_size,
|
|
89
|
+
should_run = all([contains_geospatial_data, below_max_area_size, not has_soil_type_measurements])
|
|
70
90
|
logShouldRun(site, MODEL, TERM_ID, should_run)
|
|
71
91
|
return should_run
|
|
72
92
|
|
|
@@ -9,8 +9,8 @@ from . import MODEL
|
|
|
9
9
|
|
|
10
10
|
REQUIREMENTS = {
|
|
11
11
|
"Cycle": {
|
|
12
|
-
"practices": [{"@type": "Practice", "value": "", "term.termType": "
|
|
13
|
-
"products": [{"@type": "Product", "value": "", "term.termType": "
|
|
12
|
+
"practices": [{"@type": "Practice", "value": "", "term.termType": "cropResidueManagement"}],
|
|
13
|
+
"products": [{"@type": "Product", "value": "", "term.termType": "cropResidue"}]
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
RETURNS = {
|
|
@@ -19,16 +19,18 @@ from . import MODEL
|
|
|
19
19
|
REQUIREMENTS = {
|
|
20
20
|
"Site": {
|
|
21
21
|
"optional": {
|
|
22
|
-
"measurements": [
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
22
|
+
"measurements": [
|
|
23
|
+
{
|
|
24
|
+
"@type": "Measurement",
|
|
25
|
+
"value": "",
|
|
26
|
+
"depthUpper": "",
|
|
27
|
+
"depthLower": "",
|
|
28
|
+
"term.termType": ["soilType", "usdaSoilType"],
|
|
29
|
+
"optional": {
|
|
30
|
+
"dates": ""
|
|
31
|
+
}
|
|
30
32
|
}
|
|
31
|
-
|
|
33
|
+
]
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
}
|
|
@@ -41,7 +43,8 @@ RETURNS = {
|
|
|
41
43
|
}]
|
|
42
44
|
}
|
|
43
45
|
LOOKUPS = {
|
|
44
|
-
"soilType": "IPCC_SOIL_CATEGORY"
|
|
46
|
+
"soilType": "IPCC_SOIL_CATEGORY",
|
|
47
|
+
"usdaSoilType": "IPCC_SOIL_CATEGORY"
|
|
45
48
|
}
|
|
46
49
|
TERM_ID = 'organicSoils,mineralSoils'
|
|
47
50
|
|
|
@@ -50,6 +53,10 @@ ORGANIC_SOILS_TERM_ID = MEASUREMENT_TERM_IDS[0]
|
|
|
50
53
|
MINERAL_SOILS_TERM_ID = MEASUREMENT_TERM_IDS[1]
|
|
51
54
|
METHOD = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
|
|
52
55
|
|
|
56
|
+
_INPUT_TERM_TYPES = (
|
|
57
|
+
TermTermType.SOILTYPE,
|
|
58
|
+
TermTermType.USDASOILTYPE
|
|
59
|
+
)
|
|
53
60
|
TARGET_LOOKUP_VALUE = IPCC_SOIL_CATEGORY_TO_SOIL_TYPE_LOOKUP_VALUE[IpccSoilCategory.ORGANIC_SOILS]
|
|
54
61
|
|
|
55
62
|
IS_100_THRESHOLD = 99.5
|
|
@@ -65,6 +72,7 @@ def _measurement(term_id: str, **kwargs):
|
|
|
65
72
|
|
|
66
73
|
class _SoilTypeDatum(NamedTuple):
|
|
67
74
|
term_id: str
|
|
75
|
+
term_type: str
|
|
68
76
|
depth_upper: float
|
|
69
77
|
depth_lower: float
|
|
70
78
|
dates: list[str]
|
|
@@ -105,14 +113,16 @@ def _extract_soil_type_data(node: dict) -> _SoilTypeDatum:
|
|
|
105
113
|
depth_upper = node.get("depthUpper")
|
|
106
114
|
depth_lower = node.get("depthLower")
|
|
107
115
|
depth_interval = (depth_upper, depth_lower)
|
|
116
|
+
term_type = node.get("term", {}).get("termType")
|
|
108
117
|
|
|
109
118
|
return _SoilTypeDatum(
|
|
110
119
|
term_id=node.get("term", {}).get("@id"),
|
|
120
|
+
term_type=term_type,
|
|
111
121
|
depth_upper=depth_upper,
|
|
112
122
|
depth_lower=depth_lower,
|
|
113
123
|
dates=node.get("dates", []),
|
|
114
124
|
value=get_node_value(node),
|
|
115
|
-
is_organic=node_lookup_match(node, LOOKUPS[
|
|
125
|
+
is_organic=node_lookup_match(node, LOOKUPS[term_type], TARGET_LOOKUP_VALUE),
|
|
116
126
|
is_complete_depth=all(depth is not None for depth in depth_interval),
|
|
117
127
|
is_standard_depth=depth_interval in STANDARD_DEPTHS,
|
|
118
128
|
)
|
|
@@ -126,7 +136,7 @@ def _classify_soil_type_data(soil_type_data: list[_SoilTypeDatum]):
|
|
|
126
136
|
|
|
127
137
|
def classify(inventory: _SoilTypeInventory, datum: _SoilTypeDatum) -> _SoilTypeInventory:
|
|
128
138
|
"""
|
|
129
|
-
Sum the values of organic and mineral `soilType` Measurements by depth interval and date.
|
|
139
|
+
Sum the values of organic and mineral `soilType`/`usdaSoilType` Measurements by depth interval and date.
|
|
130
140
|
"""
|
|
131
141
|
keys = _soil_type_data_to_inventory_keys(datum)
|
|
132
142
|
|
|
@@ -252,7 +262,7 @@ def _filter_data_by_depth_availability(data: list[_SoilTypeDatum]):
|
|
|
252
262
|
|
|
253
263
|
def _should_run(site: dict):
|
|
254
264
|
soil_type_nodes = split_nodes_by_dates(
|
|
255
|
-
|
|
265
|
+
get_soil_type_nodes(site)
|
|
256
266
|
)
|
|
257
267
|
|
|
258
268
|
filtered_by, soil_type_data = _filter_data_by_depth_availability(
|
|
@@ -280,6 +290,14 @@ def _should_run(site: dict):
|
|
|
280
290
|
return should_run, inventory
|
|
281
291
|
|
|
282
292
|
|
|
293
|
+
def get_soil_type_nodes(site: dict) -> list[dict]:
|
|
294
|
+
measurements = site.get("measurements", [])
|
|
295
|
+
return next(
|
|
296
|
+
(nodes for term_type in _INPUT_TERM_TYPES if (nodes := filter_list_term_type(measurements, term_type))),
|
|
297
|
+
[]
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
|
|
283
301
|
_INVENTORY_KEY_TO_FIELD_KEY = {
|
|
284
302
|
"depth_upper": "depthUpper",
|
|
285
303
|
"depth_lower": "depthLower",
|
|
@@ -200,6 +200,7 @@ def _run_practice(
|
|
|
200
200
|
GE = (
|
|
201
201
|
calculate_GE([values], REM, REG, NEwool, NEm_feed, NEg_feed) / (meanDE/100)
|
|
202
202
|
) if meanDE else 0
|
|
203
|
+
has_positive_GE_value = GE >= 0
|
|
203
204
|
|
|
204
205
|
value = (GE / meanECHHV) * (list_sum(practice.get('value', [0])) / 100)
|
|
205
206
|
|
|
@@ -229,11 +230,12 @@ def _run_practice(
|
|
|
229
230
|
logRequirements(cycle, model=MODEL, term=input_term_id, animalId=animal.get('animalId'), model_key=MODEL_KEY,
|
|
230
231
|
feed_logs=log_as_table(log_feed),
|
|
231
232
|
has_positive_feed_values=has_positive_feed_values,
|
|
233
|
+
has_positive_GE_value=has_positive_GE_value,
|
|
232
234
|
animal_logs=logs,
|
|
233
235
|
animal_lookups=animal_lookups,
|
|
234
236
|
animal_properties=animal_properties)
|
|
235
237
|
|
|
236
|
-
should_run = all([has_positive_feed_values])
|
|
238
|
+
should_run = all([has_positive_feed_values, has_positive_GE_value])
|
|
237
239
|
logShouldRun(cycle, MODEL, input_term_id, should_run, animalId=animal.get('animalId'), model_key=MODEL_KEY)
|
|
238
240
|
|
|
239
241
|
return _input(input_term_id, value) if should_run else None
|