hestia-earth-models 0.62.6__py3-none-any.whl → 0.64.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.
Potentially problematic release.
This version of hestia-earth-models might be problematic. Click here for more details.
- hestia_earth/models/cycle/longFallowRatio.py +9 -9
- hestia_earth/models/cycle/unknownPreSeasonWaterRegime.py +51 -0
- hestia_earth/models/ecoinventV3/__init__.py +18 -2
- hestia_earth/models/faostat2018/landTransformationFromCropland100YearAverage.py +1 -1
- hestia_earth/models/faostat2018/landTransformationFromCropland20YearAverage.py +1 -1
- hestia_earth/models/faostat2018/utils.py +2 -2
- hestia_earth/models/geospatialDatabase/clayContent.py +44 -17
- hestia_earth/models/geospatialDatabase/organicCarbonPerKgSoil.py +43 -17
- hestia_earth/models/geospatialDatabase/sandContent.py +43 -16
- hestia_earth/models/geospatialDatabase/siltContent.py +58 -18
- hestia_earth/models/geospatialDatabase/soilPh.py +43 -16
- hestia_earth/models/geospatialDatabase/totalNitrogenPerKgSoil.py +45 -15
- hestia_earth/models/geospatialDatabase/utils.py +11 -5
- hestia_earth/models/hyde32/landTransformationFromCropland100YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hyde32/landTransformationFromCropland20YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hyde32/landTransformationFromForest100YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hyde32/landTransformationFromForest20YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hyde32/landTransformationFromOtherNaturalVegetation100YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hyde32/landTransformationFromOtherNaturalVegetation20YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hyde32/landTransformationFromPermanentPasture100YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hyde32/landTransformationFromPermanentPasture20YearAverageDuringCycle.py +2 -1
- hestia_earth/models/hyde32/utils.py +7 -4
- hestia_earth/models/impact_assessment/allocationMethod.py +39 -0
- hestia_earth/models/impact_assessment/emissions.py +3 -1
- hestia_earth/models/mocking/search-results.json +60 -18
- hestia_earth/models/pooreNemecek2018/{longFallowPeriod.py → longFallowDuration.py} +2 -2
- hestia_earth/models/pooreNemecek2018/rotationDuration.py +5 -5
- hestia_earth/models/site/management.py +15 -1
- hestia_earth/models/site/pre_checks/cache_geospatialDatabase.py +23 -16
- hestia_earth/models/utils/cycle.py +2 -2
- hestia_earth/models/utils/indicator.py +3 -1
- hestia_earth/models/utils/term.py +34 -0
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.62.6.dist-info → hestia_earth_models-0.64.0.dist-info}/METADATA +2 -2
- {hestia_earth_models-0.62.6.dist-info → hestia_earth_models-0.64.0.dist-info}/RECORD +59 -55
- tests/models/cycle/test_longFallowRatio.py +5 -5
- tests/models/cycle/test_unknownPreSeasonWaterRegime.py +36 -0
- tests/models/geospatialDatabase/test_clayContent.py +16 -2
- tests/models/geospatialDatabase/test_organicCarbonPerKgSoil.py +16 -2
- tests/models/geospatialDatabase/test_sandContent.py +16 -2
- tests/models/geospatialDatabase/test_siltContent.py +2 -2
- tests/models/geospatialDatabase/test_soilPh.py +16 -2
- tests/models/geospatialDatabase/test_totalNitrogenPerKgSoil.py +16 -2
- tests/models/hyde32/test_landTransformationFromCropland100YearAverageDuringCycle.py +1 -0
- tests/models/hyde32/test_landTransformationFromCropland20YearAverageDuringCycle.py +1 -0
- tests/models/hyde32/test_landTransformationFromForest100YearAverageDuringCycle.py +1 -0
- tests/models/hyde32/test_landTransformationFromForest20YearAverageDuringCycle.py +1 -0
- tests/models/hyde32/test_landTransformationFromOtherNaturalVegetation100YearAverageDuringCycle.py +1 -0
- tests/models/hyde32/test_landTransformationFromOtherNaturalVegetation20YearAverageDuringCycle.py +1 -0
- tests/models/hyde32/test_landTransformationFromPermanentPasture100YearAverageDuringCycle.py +1 -0
- tests/models/hyde32/test_landTransformationFromPermanentPasture20YearAverageDuringCycle.py +1 -0
- tests/models/impact_assessment/test_allocationMethod.py +48 -0
- tests/models/pooreNemecek2018/{test_longFallowPeriod.py → test_longFallowDuration.py} +1 -1
- tests/models/test_cache_sites.py +10 -4
- tests/models/test_ecoinventV3.py +1 -0
- tests/models/utils/test_source.py +1 -1
- {hestia_earth_models-0.62.6.dist-info → hestia_earth_models-0.64.0.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.62.6.dist-info → hestia_earth_models-0.64.0.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.62.6.dist-info → hestia_earth_models-0.64.0.dist-info}/top_level.txt +0 -0
|
@@ -8,7 +8,7 @@ from . import MODEL
|
|
|
8
8
|
REQUIREMENTS = {
|
|
9
9
|
"Cycle": {
|
|
10
10
|
"practices": [
|
|
11
|
-
{"@type": "Practice", "value": "> 0", "term.@id": "
|
|
11
|
+
{"@type": "Practice", "value": "> 0", "term.@id": "longFallowDuration"},
|
|
12
12
|
{"@type": "Practice", "value": "> 0", "term.@id": "rotationDuration"}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -27,26 +27,26 @@ def _practice(value: float):
|
|
|
27
27
|
return practice
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def _run(
|
|
31
|
-
value = rotationDuration / (rotationDuration -
|
|
30
|
+
def _run(longFallowDuration: float, rotationDuration: float):
|
|
31
|
+
value = rotationDuration / (rotationDuration - longFallowDuration)
|
|
32
32
|
return [_practice(value)]
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
def _should_run(cycle: dict):
|
|
36
36
|
practices = cycle.get('practices', [])
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
longFallowDuration = list_sum(find_term_match(practices, 'longFallowDuration', {}).get('value', 0), 0)
|
|
39
39
|
rotationDuration = list_sum(find_term_match(practices, 'rotationDuration', {}).get('value', 0), 0)
|
|
40
40
|
|
|
41
41
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
42
|
-
|
|
42
|
+
longFallowDuration=longFallowDuration,
|
|
43
43
|
rotationDuration=rotationDuration)
|
|
44
44
|
|
|
45
|
-
should_run = all([
|
|
45
|
+
should_run = all([longFallowDuration > 0, rotationDuration > 0])
|
|
46
46
|
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
47
|
-
return should_run,
|
|
47
|
+
return should_run, longFallowDuration, rotationDuration
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
def run(cycle: dict):
|
|
51
|
-
should_run,
|
|
52
|
-
return _run(
|
|
51
|
+
should_run, longFallowDuration, rotationDuration = _should_run(cycle)
|
|
52
|
+
return _run(longFallowDuration, rotationDuration) if should_run else []
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
2
|
+
from hestia_earth.models.utils.term import get_flooded_pre_season_terms
|
|
3
|
+
from hestia_earth.models.utils.practice import _new_practice
|
|
4
|
+
from . import MODEL
|
|
5
|
+
|
|
6
|
+
REQUIREMENTS = {
|
|
7
|
+
"Cycle": {
|
|
8
|
+
"none": {
|
|
9
|
+
"practices": [{
|
|
10
|
+
"@type": "Practice",
|
|
11
|
+
"term.termType": "landUseManagement",
|
|
12
|
+
"term.@id": [
|
|
13
|
+
"nonFloodedPreSeasonLessThan180Days",
|
|
14
|
+
"nonFloodedPreSeasonMoreThan180Days",
|
|
15
|
+
"nonFloodedPreSeasonMoreThan365Days",
|
|
16
|
+
"floodedPreSeasonMoreThan30Days"
|
|
17
|
+
]
|
|
18
|
+
}]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
RETURNS = {
|
|
23
|
+
"Practice": [{
|
|
24
|
+
"value": "100"
|
|
25
|
+
}]
|
|
26
|
+
}
|
|
27
|
+
TERM_ID = 'unknownPreSeasonWaterRegime'
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _practice():
|
|
31
|
+
practice = _new_practice(TERM_ID)
|
|
32
|
+
practice['value'] = [100]
|
|
33
|
+
return practice
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _should_run(cycle: dict):
|
|
37
|
+
practices = cycle.get('practices', [])
|
|
38
|
+
flooded_terms = get_flooded_pre_season_terms()
|
|
39
|
+
print(flooded_terms)
|
|
40
|
+
existing_practice = next((p for p in practices if p.get('term', {}).get('@id') in flooded_terms), None)
|
|
41
|
+
|
|
42
|
+
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
43
|
+
existing_practice=existing_practice)
|
|
44
|
+
|
|
45
|
+
should_run = all([not existing_practice])
|
|
46
|
+
logShouldRun(cycle, MODEL, TERM_ID, should_run)
|
|
47
|
+
return should_run
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def run(cycle: dict):
|
|
51
|
+
return [_practice()] if _should_run(cycle) else []
|
|
@@ -19,6 +19,7 @@ from hestia_earth.utils.tools import flatten, list_sum
|
|
|
19
19
|
|
|
20
20
|
from hestia_earth.models.log import debugValues, logShouldRun, logRequirements
|
|
21
21
|
from hestia_earth.models.data.ecoinventV3 import ecoinventV3_emissions
|
|
22
|
+
from hestia_earth.models.utils import is_from_model
|
|
22
23
|
from hestia_earth.models.utils.emission import _new_emission
|
|
23
24
|
from hestia_earth.models.utils.blank_node import group_by_keys
|
|
24
25
|
from hestia_earth.models.utils.pesticideAI import get_pesticides_from_inputs
|
|
@@ -109,18 +110,33 @@ def _add_emission(cycle: dict, input: dict):
|
|
|
109
110
|
|
|
110
111
|
|
|
111
112
|
def _run_input(cycle: dict):
|
|
113
|
+
emissions = cycle.get('emissions', [])
|
|
114
|
+
|
|
112
115
|
def run(inputs: list):
|
|
113
116
|
input = inputs[0]
|
|
114
117
|
input_term_id = input.get('term', {}).get('@id')
|
|
118
|
+
operation_term_id = input.get('operation', {}).get('@id')
|
|
119
|
+
animal_term_id = input.get('animal', {}).get('@id')
|
|
115
120
|
input_value = list_sum(flatten(input.get('value', []) for input in inputs))
|
|
116
121
|
mappings = get_input_mappings(MODEL, cycle, input)
|
|
117
122
|
has_mappings = len(mappings) > 0
|
|
123
|
+
# skip input that has background emissions we have already gap-filled (model run before)
|
|
124
|
+
has_no_gap_filled_background_emissions = not any([
|
|
125
|
+
is_from_model(e)
|
|
126
|
+
for e in emissions
|
|
127
|
+
if all([
|
|
128
|
+
any([i.get('@id') == input_term_id for i in e.get('inputs', [])]),
|
|
129
|
+
e.get('operation', {}).get('@id') == operation_term_id,
|
|
130
|
+
e.get('animal', {}).get('@id') == animal_term_id
|
|
131
|
+
])
|
|
132
|
+
])
|
|
118
133
|
|
|
119
134
|
logRequirements(cycle, model=MODEL, term=input_term_id,
|
|
120
135
|
has_ecoinvent_mappings=has_mappings,
|
|
121
|
-
ecoinvent_mappings=';'.join([v[0] for v in mappings])
|
|
136
|
+
ecoinvent_mappings=';'.join([v[0] for v in mappings]),
|
|
137
|
+
has_no_gap_filled_background_emissions=has_no_gap_filled_background_emissions)
|
|
122
138
|
|
|
123
|
-
should_run = all([has_mappings])
|
|
139
|
+
should_run = all([has_mappings, has_no_gap_filled_background_emissions])
|
|
124
140
|
logShouldRun(cycle, MODEL, input_term_id, should_run, methodTier=TIER)
|
|
125
141
|
grouped_emissions = reduce(_add_emission(cycle, input), mappings, {}) if should_run else {}
|
|
126
142
|
return [
|
|
@@ -62,14 +62,14 @@ def _cropland_split_delta(table_value: str, start_year: int, end_year: int):
|
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
def get_cropland_ratio(country: str, start_year: int, end_year: int):
|
|
65
|
-
lookup = download_lookup('region-
|
|
65
|
+
lookup = download_lookup('region-faostatArea.csv')
|
|
66
66
|
total_delta = _cropland_split_delta(
|
|
67
67
|
get_table_value(lookup, 'termid', country, column_name('Cropland')), start_year, end_year
|
|
68
68
|
)
|
|
69
69
|
|
|
70
70
|
# get both values and only return result if we have both
|
|
71
71
|
permanent_delta = _cropland_split_delta(
|
|
72
|
-
get_table_value(lookup, 'termid', country, column_name('
|
|
72
|
+
get_table_value(lookup, 'termid', country, column_name('Permanent crops')), start_year, end_year
|
|
73
73
|
)
|
|
74
74
|
temporary_delta = _cropland_split_delta(
|
|
75
75
|
get_table_value(lookup, 'termid', country, column_name('Arable land')), start_year, end_year
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from hestia_earth.schema import MeasurementMethodClassification
|
|
2
|
+
from hestia_earth.utils.tools import non_empty_list
|
|
2
3
|
|
|
3
4
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
5
|
from hestia_earth.models.utils.blank_node import has_original_by_ids
|
|
@@ -29,37 +30,63 @@ REQUIREMENTS = {
|
|
|
29
30
|
RETURNS = {
|
|
30
31
|
"Measurement": [{
|
|
31
32
|
"value": "",
|
|
32
|
-
"depthUpper": "
|
|
33
|
-
"depthLower": "
|
|
33
|
+
"depthUpper": "",
|
|
34
|
+
"depthLower": "",
|
|
34
35
|
"methodClassification": "geospatial dataset"
|
|
35
36
|
}]
|
|
36
37
|
}
|
|
37
38
|
TERM_ID = 'clayContent'
|
|
38
|
-
EE_PARAMS =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
EE_PARAMS = [
|
|
40
|
+
{
|
|
41
|
+
'collection': 'T_CLAY_v2_depth_1',
|
|
42
|
+
'ee_type': 'raster',
|
|
43
|
+
'reducer': 'mean',
|
|
44
|
+
'depthUpper': 0,
|
|
45
|
+
'depthLower': 20
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
'collection': 'T_CLAY_v2_depth_2',
|
|
49
|
+
'ee_type': 'raster',
|
|
50
|
+
'reducer': 'mean',
|
|
51
|
+
'depthUpper': 20,
|
|
52
|
+
'depthLower': 40
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
'collection': 'T_CLAY_v2_depth_3',
|
|
56
|
+
'ee_type': 'raster',
|
|
57
|
+
'reducer': 'mean',
|
|
58
|
+
'depthUpper': 40,
|
|
59
|
+
'depthLower': 60
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
'collection': 'T_CLAY_v2_depth_4',
|
|
63
|
+
'ee_type': 'raster',
|
|
64
|
+
'reducer': 'mean',
|
|
65
|
+
'depthUpper': 60,
|
|
66
|
+
'depthLower': 80
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
BIBLIO_TITLE = 'Harmonized World Soil Database Version 2.0.'
|
|
44
70
|
|
|
45
71
|
|
|
46
|
-
def _measurement(site: dict, value: int):
|
|
47
|
-
measurement = _new_measurement(TERM_ID
|
|
72
|
+
def _measurement(site: dict, value: int, depthUpper: int, depthLower: int):
|
|
73
|
+
measurement = _new_measurement(TERM_ID)
|
|
48
74
|
measurement['value'] = [value]
|
|
49
|
-
measurement['depthUpper'] =
|
|
50
|
-
measurement['depthLower'] =
|
|
75
|
+
measurement['depthUpper'] = depthUpper
|
|
76
|
+
measurement['depthLower'] = depthLower
|
|
51
77
|
measurement['methodClassification'] = MeasurementMethodClassification.GEOSPATIAL_DATASET.value
|
|
52
78
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
53
79
|
|
|
54
80
|
|
|
55
|
-
def
|
|
56
|
-
value = download(TERM_ID, site,
|
|
57
|
-
return None if value is None else
|
|
81
|
+
def _run_depths(site: dict, params: dict):
|
|
82
|
+
value = download(TERM_ID, site, params)
|
|
83
|
+
return None if value is None else (
|
|
84
|
+
_measurement(site, round(value, 2), params.get('depthUpper'), params.get('depthLower'))
|
|
85
|
+
)
|
|
58
86
|
|
|
59
87
|
|
|
60
88
|
def _run(site: dict):
|
|
61
|
-
|
|
62
|
-
return [_measurement(site, value)] if value is not None else []
|
|
89
|
+
return non_empty_list([_run_depths(site, params) for params in EE_PARAMS])
|
|
63
90
|
|
|
64
91
|
|
|
65
92
|
def _should_run(site: dict):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from hestia_earth.schema import MeasurementMethodClassification
|
|
2
|
-
from hestia_earth.utils.tools import safe_parse_float
|
|
2
|
+
from hestia_earth.utils.tools import safe_parse_float, non_empty_list
|
|
3
3
|
|
|
4
4
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
5
5
|
from hestia_earth.models.utils.measurement import _new_measurement
|
|
@@ -19,37 +19,63 @@ REQUIREMENTS = {
|
|
|
19
19
|
RETURNS = {
|
|
20
20
|
"Measurement": [{
|
|
21
21
|
"value": "",
|
|
22
|
-
"depthUpper": "
|
|
23
|
-
"depthLower": "
|
|
22
|
+
"depthUpper": "",
|
|
23
|
+
"depthLower": "",
|
|
24
24
|
"methodClassification": "geospatial dataset"
|
|
25
25
|
}]
|
|
26
26
|
}
|
|
27
27
|
TERM_ID = 'organicCarbonPerKgSoil'
|
|
28
|
-
EE_PARAMS =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
EE_PARAMS = [
|
|
29
|
+
{
|
|
30
|
+
'collection': 'T_OC_v2_depth_1',
|
|
31
|
+
'ee_type': 'raster',
|
|
32
|
+
'reducer': 'mean',
|
|
33
|
+
'depthUpper': 0,
|
|
34
|
+
'depthLower': 20
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
'collection': 'T_OC_v2_depth_2',
|
|
38
|
+
'ee_type': 'raster',
|
|
39
|
+
'reducer': 'mean',
|
|
40
|
+
'depthUpper': 20,
|
|
41
|
+
'depthLower': 40
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
'collection': 'T_OC_v2_depth_3',
|
|
45
|
+
'ee_type': 'raster',
|
|
46
|
+
'reducer': 'mean',
|
|
47
|
+
'depthUpper': 40,
|
|
48
|
+
'depthLower': 60
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
'collection': 'T_OC_v2_depth_4',
|
|
52
|
+
'ee_type': 'raster',
|
|
53
|
+
'reducer': 'mean',
|
|
54
|
+
'depthUpper': 60,
|
|
55
|
+
'depthLower': 80
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
BIBLIO_TITLE = 'Harmonized World Soil Database Version 2.0.'
|
|
34
59
|
|
|
35
60
|
|
|
36
|
-
def _measurement(site: dict, value:
|
|
61
|
+
def _measurement(site: dict, value: int, depthUpper: int, depthLower: int):
|
|
37
62
|
measurement = _new_measurement(TERM_ID)
|
|
38
63
|
measurement['value'] = [value]
|
|
39
|
-
measurement['depthUpper'] =
|
|
40
|
-
measurement['depthLower'] =
|
|
64
|
+
measurement['depthUpper'] = depthUpper
|
|
65
|
+
measurement['depthLower'] = depthLower
|
|
41
66
|
measurement['methodClassification'] = MeasurementMethodClassification.GEOSPATIAL_DATASET.value
|
|
42
67
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
43
68
|
|
|
44
69
|
|
|
45
|
-
def
|
|
46
|
-
value = download(TERM_ID, site,
|
|
47
|
-
return
|
|
70
|
+
def _run_depths(site: dict, params: dict):
|
|
71
|
+
value = download(TERM_ID, site, params)
|
|
72
|
+
return None if value is None else (
|
|
73
|
+
_measurement(site, safe_parse_float(value) * 10, params.get('depthUpper'), params.get('depthLower'))
|
|
74
|
+
)
|
|
48
75
|
|
|
49
76
|
|
|
50
77
|
def _run(site: dict):
|
|
51
|
-
|
|
52
|
-
return [_measurement(site, value)] if value is not None else []
|
|
78
|
+
return non_empty_list([_run_depths(site, params) for params in EE_PARAMS])
|
|
53
79
|
|
|
54
80
|
|
|
55
81
|
def _should_run(site: dict):
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from hestia_earth.schema import MeasurementMethodClassification
|
|
2
|
+
from hestia_earth.utils.tools import non_empty_list
|
|
2
3
|
|
|
3
4
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
5
|
from hestia_earth.models.utils.blank_node import has_original_by_ids
|
|
@@ -29,37 +30,63 @@ REQUIREMENTS = {
|
|
|
29
30
|
RETURNS = {
|
|
30
31
|
"Measurement": [{
|
|
31
32
|
"value": "",
|
|
32
|
-
"depthUpper": "
|
|
33
|
-
"depthLower": "
|
|
33
|
+
"depthUpper": "",
|
|
34
|
+
"depthLower": "",
|
|
34
35
|
"methodClassification": "geospatial dataset"
|
|
35
36
|
}]
|
|
36
37
|
}
|
|
37
38
|
TERM_ID = 'sandContent'
|
|
38
|
-
EE_PARAMS =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
EE_PARAMS = [
|
|
40
|
+
{
|
|
41
|
+
'collection': 'T_SAND_v2_depth_1',
|
|
42
|
+
'ee_type': 'raster',
|
|
43
|
+
'reducer': 'mean',
|
|
44
|
+
'depthUpper': 0,
|
|
45
|
+
'depthLower': 20
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
'collection': 'T_SAND_v2_depth_2',
|
|
49
|
+
'ee_type': 'raster',
|
|
50
|
+
'reducer': 'mean',
|
|
51
|
+
'depthUpper': 20,
|
|
52
|
+
'depthLower': 40
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
'collection': 'T_SAND_v2_depth_3',
|
|
56
|
+
'ee_type': 'raster',
|
|
57
|
+
'reducer': 'mean',
|
|
58
|
+
'depthUpper': 40,
|
|
59
|
+
'depthLower': 60
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
'collection': 'T_SAND_v2_depth_4',
|
|
63
|
+
'ee_type': 'raster',
|
|
64
|
+
'reducer': 'mean',
|
|
65
|
+
'depthUpper': 60,
|
|
66
|
+
'depthLower': 80
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
BIBLIO_TITLE = 'Harmonized World Soil Database Version 2.0.'
|
|
44
70
|
|
|
45
71
|
|
|
46
|
-
def _measurement(site: dict, value: int):
|
|
72
|
+
def _measurement(site: dict, value: int, depthUpper: int, depthLower: int):
|
|
47
73
|
measurement = _new_measurement(TERM_ID)
|
|
48
74
|
measurement['value'] = [value]
|
|
49
|
-
measurement['depthUpper'] =
|
|
50
|
-
measurement['depthLower'] =
|
|
75
|
+
measurement['depthUpper'] = depthUpper
|
|
76
|
+
measurement['depthLower'] = depthLower
|
|
51
77
|
measurement['methodClassification'] = MeasurementMethodClassification.GEOSPATIAL_DATASET.value
|
|
52
78
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
53
79
|
|
|
54
80
|
|
|
55
|
-
def
|
|
56
|
-
value = download(TERM_ID, site,
|
|
57
|
-
return None if value is None else
|
|
81
|
+
def _run_depths(site: dict, params: dict):
|
|
82
|
+
value = download(TERM_ID, site, params)
|
|
83
|
+
return None if value is None else (
|
|
84
|
+
_measurement(site, round(value, 2), params.get('depthUpper'), params.get('depthLower'))
|
|
85
|
+
)
|
|
58
86
|
|
|
59
87
|
|
|
60
88
|
def _run(site: dict):
|
|
61
|
-
|
|
62
|
-
return [_measurement(site, value)] if value is not None else []
|
|
89
|
+
return non_empty_list([_run_depths(site, params) for params in EE_PARAMS])
|
|
63
90
|
|
|
64
91
|
|
|
65
92
|
def _should_run(site: dict):
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
from hestia_earth.schema import MeasurementMethodClassification
|
|
2
|
+
from hestia_earth.utils.model import find_term_match
|
|
3
|
+
from hestia_earth.utils.tools import non_empty_list, flatten
|
|
2
4
|
|
|
3
|
-
from hestia_earth.models.log import logRequirements, logShouldRun,
|
|
4
|
-
from hestia_earth.models.utils.measurement import _new_measurement, measurement_value
|
|
5
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
6
|
+
from hestia_earth.models.utils.measurement import _new_measurement, measurement_value, group_measurements_by_depth
|
|
5
7
|
from hestia_earth.models.utils.source import get_source
|
|
6
8
|
from . import MODEL, clayContent, sandContent
|
|
7
9
|
|
|
8
10
|
REQUIREMENTS = {
|
|
9
11
|
"Site": {
|
|
12
|
+
"measurements": [
|
|
13
|
+
{
|
|
14
|
+
"@type": "Measurement",
|
|
15
|
+
"term.@id": "clayContent",
|
|
16
|
+
"value": ">= 0",
|
|
17
|
+
"depthUpper": ">= 0",
|
|
18
|
+
"depthLower": ">= 0"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"@type": "Measurement",
|
|
22
|
+
"term.@id": "sandContent",
|
|
23
|
+
"value": ">= 0",
|
|
24
|
+
"depthUpper": ">= 0",
|
|
25
|
+
"depthLower": ">= 0"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
10
28
|
"or": [
|
|
11
29
|
{"latitude": "", "longitude": ""},
|
|
12
30
|
{"boundary": {}},
|
|
@@ -17,8 +35,8 @@ REQUIREMENTS = {
|
|
|
17
35
|
RETURNS = {
|
|
18
36
|
"Measurement": [{
|
|
19
37
|
"value": "",
|
|
20
|
-
"depthUpper": "
|
|
21
|
-
"depthLower": "
|
|
38
|
+
"depthUpper": "",
|
|
39
|
+
"depthLower": "",
|
|
22
40
|
"methodClassification": "geospatial dataset"
|
|
23
41
|
}]
|
|
24
42
|
}
|
|
@@ -27,39 +45,61 @@ OTHER_TERM_IDS = [
|
|
|
27
45
|
clayContent.TERM_ID,
|
|
28
46
|
sandContent.TERM_ID
|
|
29
47
|
]
|
|
30
|
-
BIBLIO_TITLE = 'Harmonized World Soil Database Version
|
|
48
|
+
BIBLIO_TITLE = 'Harmonized World Soil Database Version 2.0.'
|
|
31
49
|
|
|
32
50
|
|
|
33
|
-
def _measurement(site: dict, value: int):
|
|
51
|
+
def _measurement(site: dict, value: int, depthUpper: int, depthLower: int):
|
|
34
52
|
measurement = _new_measurement(TERM_ID)
|
|
35
53
|
measurement['value'] = [value]
|
|
36
|
-
measurement['depthUpper'] =
|
|
37
|
-
measurement['depthLower'] =
|
|
54
|
+
measurement['depthUpper'] = depthUpper
|
|
55
|
+
measurement['depthLower'] = depthLower
|
|
38
56
|
measurement['methodClassification'] = MeasurementMethodClassification.GEOSPATIAL_DATASET.value
|
|
39
57
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
40
58
|
|
|
41
59
|
|
|
42
60
|
def _run(site: dict, measurements: list):
|
|
43
61
|
value = 100 - sum([measurement_value(m) for m in measurements])
|
|
44
|
-
return [_measurement(site, value)]
|
|
62
|
+
return [_measurement(site, value, measurements[0].get('depthUpper'), measurements[0].get('depthLower'))]
|
|
45
63
|
|
|
46
64
|
|
|
47
65
|
def _should_run(site: dict):
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
66
|
+
grouped_measurements = group_measurements_by_depth(site.get('measurements', []), include_dates=False)
|
|
67
|
+
relevant_measurements = [
|
|
68
|
+
[
|
|
69
|
+
m for m in measurements if all([
|
|
70
|
+
m.get('term', {}).get('@id') in OTHER_TERM_IDS,
|
|
71
|
+
len(m.get('value', [])) > 0,
|
|
72
|
+
m.get('depthUpper', -1) >= 0,
|
|
73
|
+
m.get('depthLower', -1) >= 0
|
|
74
|
+
])
|
|
75
|
+
]
|
|
76
|
+
for measurements in grouped_measurements.values()
|
|
77
|
+
]
|
|
78
|
+
valid_measurements = [
|
|
79
|
+
values for values in relevant_measurements if len(values) == len(OTHER_TERM_IDS)
|
|
51
80
|
]
|
|
52
|
-
|
|
81
|
+
|
|
82
|
+
has_valid_measurements = len(valid_measurements) > 0
|
|
53
83
|
|
|
54
84
|
logRequirements(site, model=MODEL, term=TERM_ID,
|
|
55
|
-
|
|
56
|
-
|
|
85
|
+
has_valid_measurements=has_valid_measurements,
|
|
86
|
+
measurements=log_as_table([
|
|
87
|
+
{
|
|
88
|
+
'depths': '-'.join(non_empty_list([
|
|
89
|
+
str(values[0].get('depthUpper', '')),
|
|
90
|
+
str(values[0].get('depthLower', ''))
|
|
91
|
+
]))
|
|
92
|
+
} | {
|
|
93
|
+
term_id: measurement_value(find_term_match(values, term_id))
|
|
94
|
+
for term_id in OTHER_TERM_IDS
|
|
95
|
+
} for values in valid_measurements
|
|
96
|
+
]))
|
|
57
97
|
|
|
58
|
-
should_run = all([
|
|
98
|
+
should_run = all([has_valid_measurements])
|
|
59
99
|
logShouldRun(site, MODEL, TERM_ID, should_run)
|
|
60
|
-
return should_run,
|
|
100
|
+
return should_run, valid_measurements
|
|
61
101
|
|
|
62
102
|
|
|
63
103
|
def run(site: dict):
|
|
64
104
|
should_run, measurements = _should_run(site)
|
|
65
|
-
return _run(site, measurements) if should_run else []
|
|
105
|
+
return flatten([_run(site, values) for values in measurements]) if should_run else []
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from hestia_earth.schema import MeasurementMethodClassification
|
|
2
|
+
from hestia_earth.utils.tools import non_empty_list
|
|
2
3
|
|
|
3
4
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
5
|
from hestia_earth.models.utils.measurement import _new_measurement
|
|
@@ -18,37 +19,63 @@ REQUIREMENTS = {
|
|
|
18
19
|
RETURNS = {
|
|
19
20
|
"Measurement": [{
|
|
20
21
|
"value": "",
|
|
21
|
-
"depthUpper": "
|
|
22
|
-
"depthLower": "
|
|
22
|
+
"depthUpper": "",
|
|
23
|
+
"depthLower": "",
|
|
23
24
|
"methodClassification": "geospatial dataset"
|
|
24
25
|
}]
|
|
25
26
|
}
|
|
26
27
|
TERM_ID = 'soilPh'
|
|
27
|
-
EE_PARAMS =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
EE_PARAMS = [
|
|
29
|
+
{
|
|
30
|
+
'collection': 'T_PH_H2O_v2_depth_1',
|
|
31
|
+
'ee_type': 'raster',
|
|
32
|
+
'reducer': 'mean',
|
|
33
|
+
'depthUpper': 0,
|
|
34
|
+
'depthLower': 20
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
'collection': 'T_PH_H2O_v2_depth_2',
|
|
38
|
+
'ee_type': 'raster',
|
|
39
|
+
'reducer': 'mean',
|
|
40
|
+
'depthUpper': 20,
|
|
41
|
+
'depthLower': 40
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
'collection': 'T_PH_H2O_v2_depth_3',
|
|
45
|
+
'ee_type': 'raster',
|
|
46
|
+
'reducer': 'mean',
|
|
47
|
+
'depthUpper': 40,
|
|
48
|
+
'depthLower': 60
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
'collection': 'T_PH_H2O_v2_depth_4',
|
|
52
|
+
'ee_type': 'raster',
|
|
53
|
+
'reducer': 'mean',
|
|
54
|
+
'depthUpper': 60,
|
|
55
|
+
'depthLower': 80
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
BIBLIO_TITLE = 'Harmonized World Soil Database Version 2.0.'
|
|
33
59
|
|
|
34
60
|
|
|
35
|
-
def _measurement(site: dict, value:
|
|
61
|
+
def _measurement(site: dict, value: int, depthUpper: int, depthLower: int):
|
|
36
62
|
measurement = _new_measurement(TERM_ID)
|
|
37
63
|
measurement['value'] = [value]
|
|
38
|
-
measurement['depthUpper'] =
|
|
39
|
-
measurement['depthLower'] =
|
|
64
|
+
measurement['depthUpper'] = depthUpper
|
|
65
|
+
measurement['depthLower'] = depthLower
|
|
40
66
|
measurement['methodClassification'] = MeasurementMethodClassification.GEOSPATIAL_DATASET.value
|
|
41
67
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
42
68
|
|
|
43
69
|
|
|
44
|
-
def
|
|
45
|
-
value = download(TERM_ID, site,
|
|
46
|
-
return None if value is None else
|
|
70
|
+
def _run_depths(site: dict, params: dict):
|
|
71
|
+
value = download(TERM_ID, site, params)
|
|
72
|
+
return None if value is None else (
|
|
73
|
+
_measurement(site, round(value, 7), params.get('depthUpper'), params.get('depthLower'))
|
|
74
|
+
)
|
|
47
75
|
|
|
48
76
|
|
|
49
77
|
def _run(site: dict):
|
|
50
|
-
|
|
51
|
-
return [] if value is None else [_measurement(site, value)]
|
|
78
|
+
return non_empty_list([_run_depths(site, params) for params in EE_PARAMS])
|
|
52
79
|
|
|
53
80
|
|
|
54
81
|
def _should_run(site: dict):
|