hestia-earth-models 0.61.6__py3-none-any.whl → 0.61.8__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/completeness/electricityFuel.py +56 -0
- hestia_earth/models/cycle/input/hestiaAggregatedData.py +1 -1
- hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +44 -59
- hestia_earth/models/geospatialDatabase/histosol.py +4 -0
- hestia_earth/models/ipcc2006/co2ToAirOrganicSoilCultivation.py +4 -2
- hestia_earth/models/ipcc2006/n2OToAirOrganicSoilCultivationDirect.py +1 -1
- hestia_earth/models/ipcc2019/aboveGroundCropResidueTotal.py +1 -1
- hestia_earth/models/ipcc2019/belowGroundCropResidue.py +1 -1
- hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +1 -1
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +511 -458
- hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +5 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +117 -3881
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +2060 -0
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +1630 -0
- hestia_earth/models/ipcc2019/organicCarbonPerHa_utils.py +324 -0
- hestia_earth/models/mocking/search-results.json +360 -260
- hestia_earth/models/schererPfister2015/pToDrainageWaterSoilFlux.py +1 -1
- hestia_earth/models/schererPfister2015/pToGroundwaterSoilFlux.py +1 -1
- hestia_earth/models/site/organicCarbonPerHa.py +58 -44
- hestia_earth/models/site/soilMeasurement.py +25 -38
- hestia_earth/models/utils/__init__.py +28 -0
- hestia_earth/models/utils/aquacultureManagement.py +2 -2
- hestia_earth/models/utils/array_builders.py +578 -0
- hestia_earth/models/utils/blank_node.py +2 -3
- hestia_earth/models/utils/crop.py +24 -1
- hestia_earth/models/utils/cycle.py +0 -23
- hestia_earth/models/utils/descriptive_stats.py +285 -0
- hestia_earth/models/utils/emission.py +73 -2
- hestia_earth/models/utils/inorganicFertiliser.py +2 -2
- hestia_earth/models/utils/lookup.py +6 -3
- hestia_earth/models/utils/measurement.py +118 -4
- hestia_earth/models/utils/site.py +25 -13
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.61.6.dist-info → hestia_earth_models-0.61.8.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.61.6.dist-info → hestia_earth_models-0.61.8.dist-info}/RECORD +52 -40
- tests/models/cycle/completeness/test_electricityFuel.py +21 -0
- tests/models/emepEea2019/test_nh3ToAirInorganicFertiliser.py +2 -2
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +54 -165
- tests/models/ipcc2019/test_organicCarbonPerHa.py +219 -460
- tests/models/ipcc2019/test_organicCarbonPerHa_tier_1_utils.py +471 -0
- tests/models/ipcc2019/test_organicCarbonPerHa_tier_2_utils.py +208 -0
- tests/models/ipcc2019/test_organicCarbonPerHa_utils.py +75 -0
- tests/models/site/test_organicCarbonPerHa.py +3 -12
- tests/models/site/test_soilMeasurement.py +5 -19
- tests/models/utils/test_array_builders.py +253 -0
- tests/models/utils/{test_cycle.py → test_crop.py} +2 -2
- tests/models/utils/test_descriptive_stats.py +134 -0
- tests/models/utils/test_emission.py +51 -1
- tests/models/utils/test_measurement.py +54 -2
- {hestia_earth_models-0.61.6.dist-info → hestia_earth_models-0.61.8.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.61.6.dist-info → hestia_earth_models-0.61.8.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.61.6.dist-info → hestia_earth_models-0.61.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Completeness Electricity Fuel
|
|
3
|
+
|
|
4
|
+
This model checks if we have the requirements below and updates the
|
|
5
|
+
[Data Completeness](https://hestia.earth/schema/Completeness#electricityFuel) value.
|
|
6
|
+
"""
|
|
7
|
+
from hestia_earth.schema import TermTermType
|
|
8
|
+
from hestia_earth.utils.model import filter_list_term_type
|
|
9
|
+
|
|
10
|
+
from hestia_earth.models.log import logRequirements, log_as_table
|
|
11
|
+
from hestia_earth.models.utils.blank_node import get_lookup_value
|
|
12
|
+
from . import MODEL
|
|
13
|
+
|
|
14
|
+
REQUIREMENTS = {
|
|
15
|
+
"Cycle": {
|
|
16
|
+
"completeness.electricityFuel": "False",
|
|
17
|
+
"practices": [
|
|
18
|
+
{"@type": "Practice", "value": "", "term.termType": "operation"}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
RETURNS = {
|
|
23
|
+
"Completeness": {
|
|
24
|
+
"electricityFuel": ""
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
LOOKUPS = {
|
|
28
|
+
"operation": ["fuelUse", "combustionType"]
|
|
29
|
+
}
|
|
30
|
+
MODEL_KEY = 'electricityFuel'
|
|
31
|
+
_VALID_COMBUSTION_TYPES = ['mobile', 'stationary']
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _lookup_value(practice: dict, lookup_name: str):
|
|
35
|
+
return get_lookup_value(practice.get('term', {}), lookup_name, model=MODEL, model_key=MODEL_KEY)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _practice_value(practice: dict):
|
|
39
|
+
term = practice.get('term', {})
|
|
40
|
+
fuel_use = _lookup_value(practice, LOOKUPS['operation'][0])
|
|
41
|
+
return {'id': term.get('@id'), 'fuel_use': fuel_use}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def run(cycle: dict):
|
|
45
|
+
practices = filter_list_term_type(cycle.get('practices', []), TermTermType.OPERATION)
|
|
46
|
+
combustion_practices = [
|
|
47
|
+
p for p in practices if _lookup_value(p, LOOKUPS['operation'][1]) in _VALID_COMBUSTION_TYPES
|
|
48
|
+
]
|
|
49
|
+
practices_values = list(map(_practice_value, combustion_practices))
|
|
50
|
+
|
|
51
|
+
logRequirements(cycle, model=MODEL, term=None, key=MODEL_KEY,
|
|
52
|
+
values=log_as_table(practices_values))
|
|
53
|
+
|
|
54
|
+
is_complete = all([p.get('fuel_use') for p in practices_values])
|
|
55
|
+
|
|
56
|
+
return is_complete
|
|
@@ -10,7 +10,7 @@ from hestia_earth.schema import TermTermType
|
|
|
10
10
|
from hestia_earth.utils.model import find_primary_product, find_term_match, linked_node
|
|
11
11
|
|
|
12
12
|
from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
|
|
13
|
-
from hestia_earth.models.utils.
|
|
13
|
+
from hestia_earth.models.utils.crop import valid_site_type
|
|
14
14
|
from hestia_earth.models.utils.term import get_generic_crop
|
|
15
15
|
from hestia_earth.models.utils.aggregated import (
|
|
16
16
|
should_link_input_to_impact, link_inputs_to_impact, find_closest_impact, aggregated_end_date
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
from functools import reduce
|
|
2
2
|
from hestia_earth.schema import EmissionMethodTier
|
|
3
|
-
from hestia_earth.utils.lookup import download_lookup
|
|
4
3
|
from hestia_earth.utils.model import find_term_match
|
|
5
|
-
from hestia_earth.utils.tools import list_sum
|
|
4
|
+
from hestia_earth.utils.tools import list_sum, non_empty_list
|
|
6
5
|
|
|
7
|
-
from hestia_earth.models.log import
|
|
6
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
8
7
|
from hestia_earth.models.utils import _filter_list_term_unit
|
|
9
8
|
from hestia_earth.models.utils.completeness import _is_term_type_complete
|
|
10
9
|
from hestia_earth.models.utils.inorganicFertiliser import (
|
|
11
|
-
get_NH3_emission_factor, get_terms, get_term_lookup,
|
|
10
|
+
get_NH3_emission_factor, get_terms, get_term_lookup, get_country_breakdown, get_cycle_inputs
|
|
12
11
|
)
|
|
13
12
|
from hestia_earth.models.utils.constant import Units
|
|
14
13
|
from hestia_earth.models.utils.emission import _new_emission
|
|
@@ -66,23 +65,21 @@ def _emission(value: float):
|
|
|
66
65
|
return emission
|
|
67
66
|
|
|
68
67
|
|
|
69
|
-
def
|
|
68
|
+
def _input_with_factor(soilPh: float, temperature: float):
|
|
70
69
|
def get_value(input: dict):
|
|
71
70
|
term_id = input.get('term', {}).get('@id')
|
|
72
|
-
factor = get_NH3_emission_factor(term_id, soilPh, temperature)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
factor = get_NH3_emission_factor(term_id, soilPh, temperature) if all([
|
|
72
|
+
soilPh is not None,
|
|
73
|
+
temperature is not None
|
|
74
|
+
]) else None
|
|
75
|
+
value = list_sum(input.get('value'), None)
|
|
76
|
+
return {'id': term_id, 'value': value, 'factor': factor} if all([
|
|
77
|
+
value is not None,
|
|
78
|
+
factor is not None
|
|
79
|
+
]) else None
|
|
79
80
|
return get_value
|
|
80
81
|
|
|
81
82
|
|
|
82
|
-
def _run(cycle: dict, temperature: float, soilPh: float, inputs: float):
|
|
83
|
-
return list_sum(list(map(_get_input_value(cycle, soilPh, temperature), inputs)))
|
|
84
|
-
|
|
85
|
-
|
|
86
83
|
def _get_groupings():
|
|
87
84
|
term_ids = get_terms()
|
|
88
85
|
|
|
@@ -93,23 +90,22 @@ def _get_groupings():
|
|
|
93
90
|
return reduce(get_grouping, term_ids, {})
|
|
94
91
|
|
|
95
92
|
|
|
96
|
-
def
|
|
97
|
-
|
|
98
|
-
value = get_country_breakdown(MODEL, TERM_ID, country_id, grouping)
|
|
99
|
-
debugValues(cycle, model=MODEL, term=TERM_ID,
|
|
100
|
-
grouping=grouping,
|
|
101
|
-
NH3_factor=factor,
|
|
102
|
-
country_breakdown=value)
|
|
103
|
-
return value * factor
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _run_with_unspecified(cycle: dict, temperature: float, soilPh: float, unspecifiedKgN_value: float, country_id: str):
|
|
93
|
+
def _unspecified_inputs_with_factor(temperature: float, soilPh: float, unspecifiedKgN_value: float, site: dict):
|
|
94
|
+
country_id = site.get('country', {}).get('@id')
|
|
107
95
|
# creates a dictionary grouping => term_id with only a single key per group (avoid counting twice)
|
|
108
96
|
groupings = _get_groupings()
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
97
|
+
breakdown_inputs = [(
|
|
98
|
+
term_id, get_country_breakdown(MODEL, TERM_ID, country_id, grouping)
|
|
99
|
+
) for grouping, term_id in groupings.items()] if all([country_id, unspecifiedKgN_value is not None]) else []
|
|
100
|
+
# create inputs from country breakdown
|
|
101
|
+
N_inputs = [
|
|
102
|
+
{
|
|
103
|
+
'term': {'@id': term_id},
|
|
104
|
+
'value': [value * unspecifiedKgN_value]
|
|
105
|
+
}
|
|
106
|
+
for term_id, value in breakdown_inputs if value is not None
|
|
107
|
+
]
|
|
108
|
+
return non_empty_list(map(_input_with_factor(soilPh, temperature), N_inputs))
|
|
113
109
|
|
|
114
110
|
|
|
115
111
|
def _should_run(cycle: dict):
|
|
@@ -121,49 +117,38 @@ def _should_run(cycle: dict):
|
|
|
121
117
|
measurements, 'temperatureAnnual', end_date) or most_relevant_measurement_value(
|
|
122
118
|
measurements, 'temperatureLongTermAnnualMean', end_date)
|
|
123
119
|
|
|
124
|
-
|
|
125
|
-
N_inputs = _filter_list_term_unit(inputs, Units.KG_N)
|
|
120
|
+
N_inputs = _filter_list_term_unit(get_cycle_inputs(cycle), Units.KG_N)
|
|
126
121
|
has_N_inputs = len(N_inputs) > 0
|
|
127
122
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
has_unspecifiedKgN = len(unspecifiedKgN) > 0 or fertiliser_complete
|
|
123
|
+
N_inputs_with_factor = non_empty_list(map(_input_with_factor(soilPh, temperature), N_inputs))
|
|
124
|
+
has_N_inputs_with_factor = len(N_inputs_with_factor) > 0
|
|
131
125
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
126
|
+
# fallback using country averages of fertilisers usage
|
|
127
|
+
unspecifiedKgN_value = list_sum(find_term_match(N_inputs, UNSPECIFIED_TERM_ID).get('value'), None)
|
|
128
|
+
unspecified_inputs_with_factor = _unspecified_inputs_with_factor(temperature, soilPh, unspecifiedKgN_value, site)
|
|
129
|
+
has_unspecified_inputs_with_factor = len(unspecified_inputs_with_factor) > 0
|
|
135
130
|
|
|
136
|
-
|
|
137
|
-
unspecifiedKgN = (
|
|
138
|
-
0 if len(unspecifiedKgN) == 0 and fertiliser_complete else list_sum(unspecifiedKgN, None)
|
|
139
|
-
) if run_with_unspecified else None
|
|
131
|
+
fertiliser_complete = _is_term_type_complete(cycle, 'fertiliser')
|
|
140
132
|
|
|
141
133
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
134
|
+
term_type_fertiliser_complete=fertiliser_complete,
|
|
142
135
|
temperature=temperature,
|
|
143
136
|
soilPh=soilPh,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
run_with_unspecified=run_with_unspecified,
|
|
148
|
-
has_N_inputs=has_N_inputs)
|
|
137
|
+
has_N_inputs=has_N_inputs,
|
|
138
|
+
inorganic_fertiliser_inputs=log_as_table(N_inputs_with_factor),
|
|
139
|
+
unspecified_fertiliser_inputs=log_as_table(unspecified_inputs_with_factor))
|
|
149
140
|
|
|
150
141
|
should_run = all([
|
|
142
|
+
fertiliser_complete,
|
|
151
143
|
temperature,
|
|
152
144
|
soilPh,
|
|
153
|
-
|
|
154
|
-
run_with_unspecified,
|
|
155
|
-
has_N_inputs,
|
|
156
|
-
not has_N_inputs and fertiliser_complete
|
|
157
|
-
])
|
|
145
|
+
not has_N_inputs or has_N_inputs_with_factor or has_unspecified_inputs_with_factor
|
|
158
146
|
])
|
|
159
147
|
logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
|
|
160
|
-
return should_run,
|
|
148
|
+
return should_run, N_inputs_with_factor or unspecified_inputs_with_factor
|
|
161
149
|
|
|
162
150
|
|
|
163
151
|
def run(cycle: dict):
|
|
164
|
-
should_run,
|
|
165
|
-
value =
|
|
166
|
-
_run_with_unspecified(cycle, temperature, soilPh, unspecifiedKgN, country_id)
|
|
167
|
-
if unspecifiedKgN is not None else None
|
|
168
|
-
) if should_run else None
|
|
152
|
+
should_run, N_inputs_with_factor = _should_run(cycle)
|
|
153
|
+
value = list_sum([i.get('value') * i.get('factor') for i in N_inputs_with_factor]) if should_run else None
|
|
169
154
|
return [_emission(value)] if value is not None else []
|
|
@@ -21,6 +21,8 @@ REQUIREMENTS = {
|
|
|
21
21
|
RETURNS = {
|
|
22
22
|
"Measurement": [{
|
|
23
23
|
"value": "",
|
|
24
|
+
"depthUpper": "0",
|
|
25
|
+
"depthLower": "30",
|
|
24
26
|
"methodClassification": "geospatial dataset"
|
|
25
27
|
}]
|
|
26
28
|
}
|
|
@@ -36,6 +38,8 @@ BIBLIO_TITLE = 'Harmonized World Soil Database Version 1.2. Food and Agriculture
|
|
|
36
38
|
def _measurement(site: dict, value: float):
|
|
37
39
|
measurement = _new_measurement(TERM_ID)
|
|
38
40
|
measurement['value'] = [round(value, 7)]
|
|
41
|
+
measurement['depthUpper'] = 0
|
|
42
|
+
measurement['depthLower'] = 30
|
|
39
43
|
measurement['methodClassification'] = MeasurementMethodClassification.GEOSPATIAL_DATASET.value
|
|
40
44
|
return measurement | get_source(site, BIBLIO_TITLE)
|
|
41
45
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from hestia_earth.schema import EmissionMethodTier
|
|
2
2
|
|
|
3
3
|
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
4
|
+
from hestia_earth.models.utils.constant import Units, get_atomic_conversion
|
|
4
5
|
from hestia_earth.models.utils.emission import _new_emission
|
|
5
6
|
from hestia_earth.models.utils.measurement import most_relevant_measurement_value
|
|
6
7
|
from hestia_earth.models.utils.ecoClimateZone import get_ecoClimateZone_lookup_value
|
|
@@ -39,7 +40,6 @@ RETURNS = {
|
|
|
39
40
|
}
|
|
40
41
|
TERM_ID = 'co2ToAirOrganicSoilCultivation'
|
|
41
42
|
TIER = EmissionMethodTier.TIER_1.value
|
|
42
|
-
CONVERT_FACTOR = 44 / 120
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
def _emission(value: float):
|
|
@@ -55,7 +55,9 @@ def _run(histosol: float, organic_soil_factor: float, land_occupation: float):
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
def _get_CO2_factor(eco_climate_zone: str, site_type: str):
|
|
58
|
-
return get_ecoClimateZone_lookup_value(
|
|
58
|
+
return get_ecoClimateZone_lookup_value(
|
|
59
|
+
eco_climate_zone, LOOKUPS['ecoClimateZone'], site_type
|
|
60
|
+
) * 1000 * get_atomic_conversion(Units.KG_CO2, Units.TO_C)
|
|
59
61
|
|
|
60
62
|
|
|
61
63
|
def _should_run(cycle: dict):
|
|
@@ -57,7 +57,7 @@ def _run(histosol: float, organic_soil_factor: float, land_occupation: float):
|
|
|
57
57
|
def _get_N2O_factor(eco_climate_zone: str):
|
|
58
58
|
return get_ecoClimateZone_lookup_value(
|
|
59
59
|
eco_climate_zone, LOOKUPS['ecoClimateZone']
|
|
60
|
-
) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
|
|
60
|
+
) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def _should_run(cycle: dict):
|
|
@@ -75,7 +75,7 @@ def _should_run(cycle: dict):
|
|
|
75
75
|
term_type_incomplete = _is_term_type_incomplete(cycle, TERM_ID)
|
|
76
76
|
|
|
77
77
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
78
|
-
|
|
78
|
+
has_crop_forage_products_with_dryMatter=has_crop_forage_products,
|
|
79
79
|
term_type_cropResidue_incomplete=term_type_incomplete)
|
|
80
80
|
|
|
81
81
|
should_run = all([term_type_incomplete, has_crop_forage_products])
|
|
@@ -82,7 +82,7 @@ def _should_run(cycle: dict):
|
|
|
82
82
|
term_type_incomplete = _is_term_type_incomplete(cycle, TERM_ID)
|
|
83
83
|
|
|
84
84
|
logRequirements(cycle, model=MODEL, term=TERM_ID,
|
|
85
|
-
|
|
85
|
+
has_crop_forage_products_with_dryMatter=has_crop_forage_products,
|
|
86
86
|
term_type_cropResidue_incomplete=term_type_incomplete)
|
|
87
87
|
|
|
88
88
|
should_run = all([term_type_incomplete, has_crop_forage_products])
|
|
@@ -95,7 +95,7 @@ def _get_excreta_b0(country: dict, input: dict):
|
|
|
95
95
|
)
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def _get_excretaManagement_MCF_from_lookup(term_id: str, ecoClimateZone: int, duration_key:
|
|
98
|
+
def _get_excretaManagement_MCF_from_lookup(term_id: str, ecoClimateZone: int, duration_key: DURATION):
|
|
99
99
|
lookup_name = 'excretaManagement-ecoClimateZone-CH4conv.csv'
|
|
100
100
|
lookup = download_lookup(lookup_name)
|
|
101
101
|
data_values = get_table_value(lookup, 'termid', term_id, str(ecoClimateZone))
|