hestia-earth-models 0.57.2__py3-none-any.whl → 0.59.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/aboveGroundCropResidueTotal.py +17 -12
- hestia_earth/models/cycle/excretaKgMass.py +4 -5
- hestia_earth/models/cycle/excretaKgN.py +4 -5
- hestia_earth/models/cycle/excretaKgVs.py +4 -5
- hestia_earth/models/cycle/inorganicFertiliser.py +2 -2
- hestia_earth/models/cycle/{irrigated.py → irrigatedTypeUnspecified.py} +4 -4
- hestia_earth/models/cycle/liveAnimal.py +9 -11
- hestia_earth/models/cycle/milkYield.py +154 -0
- hestia_earth/models/cycle/residueIncorporated.py +1 -1
- hestia_earth/models/cycle/utils.py +6 -0
- hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +3 -3
- hestia_earth/models/faostat2018/seed.py +2 -3
- hestia_earth/models/geospatialDatabase/clayContent.py +17 -4
- hestia_earth/models/geospatialDatabase/sandContent.py +17 -4
- hestia_earth/models/geospatialDatabase/siltContent.py +2 -2
- hestia_earth/models/impact_assessment/irrigated.py +0 -3
- hestia_earth/models/ipcc2006/co2ToAirOrganicSoilCultivation.py +2 -2
- hestia_earth/models/ipcc2006/n2OToAirCropResidueDecompositionIndirect.py +2 -2
- hestia_earth/models/ipcc2006/n2OToAirExcretaDirect.py +1 -1
- hestia_earth/models/ipcc2006/n2OToAirExcretaIndirect.py +8 -4
- hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserDirect.py +4 -1
- hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserDirect.py +1 -1
- hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2006/utils.py +11 -8
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +4 -4
- hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +16 -7
- hestia_earth/models/ipcc2019/co2ToAirSoilCarbonStockChangeManagementChange.py +759 -0
- hestia_earth/models/ipcc2019/croppingDuration.py +12 -6
- hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionDirect.py +5 -52
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserDirect.py +104 -0
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserDirect.py +105 -0
- hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/no3ToGroundwaterCropResidueDecomposition.py +1 -1
- hestia_earth/models/ipcc2019/no3ToGroundwaterExcreta.py +1 -1
- hestia_earth/models/ipcc2019/no3ToGroundwaterInorganicFertiliser.py +1 -1
- hestia_earth/models/ipcc2019/no3ToGroundwaterOrganicFertiliser.py +1 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +1088 -1268
- hestia_earth/models/ipcc2019/pastureGrass.py +4 -4
- hestia_earth/models/ipcc2019/utils.py +102 -1
- hestia_earth/models/koble2014/aboveGroundCropResidue.py +15 -17
- hestia_earth/models/koble2014/cropResidueManagement.py +2 -2
- hestia_earth/models/koble2014/utils.py +19 -3
- hestia_earth/models/linkedImpactAssessment/__init__.py +4 -2
- hestia_earth/models/log.py +15 -3
- hestia_earth/models/mocking/search-results.json +184 -118
- hestia_earth/models/pooreNemecek2018/excretaKgN.py +6 -7
- hestia_earth/models/pooreNemecek2018/excretaKgVs.py +7 -6
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterCropResidueDecomposition.py +3 -2
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterExcreta.py +3 -2
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterInorganicFertiliser.py +3 -2
- hestia_earth/models/pooreNemecek2018/saplings.py +0 -1
- hestia_earth/models/site/management.py +168 -0
- hestia_earth/models/site/organicCarbonPerHa.py +251 -89
- hestia_earth/models/stehfestBouwman2006/n2OToAirCropResidueDecompositionDirect.py +3 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirExcretaDirect.py +3 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirInorganicFertiliserDirect.py +3 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirOrganicFertiliserDirect.py +3 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirCropResidueDecomposition.py +3 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirExcreta.py +3 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirInorganicFertiliser.py +3 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirOrganicFertiliser.py +3 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirCropResidueDecomposition.py +3 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirExcreta.py +3 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirInorganicFertiliser.py +3 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirOrganicFertiliser.py +3 -2
- hestia_earth/models/utils/aggregated.py +1 -0
- hestia_earth/models/utils/blank_node.py +394 -72
- hestia_earth/models/utils/cropResidue.py +13 -0
- hestia_earth/models/utils/cycle.py +18 -9
- hestia_earth/models/utils/measurement.py +1 -1
- hestia_earth/models/utils/property.py +4 -4
- hestia_earth/models/utils/term.py +48 -3
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/METADATA +5 -9
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/RECORD +109 -97
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/WHEEL +1 -1
- tests/models/cycle/animal/input/test_hestiaAggregatedData.py +2 -14
- tests/models/cycle/input/test_hestiaAggregatedData.py +4 -16
- tests/models/cycle/test_coldCarcassWeightPerHead.py +1 -1
- tests/models/cycle/test_coldDressedCarcassWeightPerHead.py +1 -1
- tests/models/cycle/{test_irrigated.py → test_irrigatedTypeUnspecified.py} +1 -1
- tests/models/cycle/test_milkYield.py +58 -0
- tests/models/cycle/test_readyToCookWeightPerHead.py +1 -1
- tests/models/emepEea2019/test_nh3ToAirInorganicFertiliser.py +1 -1
- tests/models/geospatialDatabase/test_clayContent.py +9 -3
- tests/models/geospatialDatabase/test_sandContent.py +9 -3
- tests/models/ipcc2006/test_n2OToAirExcretaDirect.py +7 -2
- tests/models/ipcc2006/test_n2OToAirExcretaIndirect.py +1 -1
- tests/models/ipcc2006/test_n2OToAirInorganicFertiliserDirect.py +7 -2
- tests/models/ipcc2006/test_n2OToAirInorganicFertiliserIndirect.py +7 -2
- tests/models/ipcc2006/test_n2OToAirOrganicFertiliserDirect.py +7 -2
- tests/models/ipcc2006/test_n2OToAirOrganicFertiliserIndirect.py +7 -2
- tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +1 -1
- tests/models/ipcc2019/test_co2ToAirSoilCarbonStockChangeManagementChange.py +228 -0
- tests/models/ipcc2019/test_n2OToAirInorganicFertiliserDirect.py +74 -0
- tests/models/ipcc2019/test_n2OToAirOrganicFertiliserDirect.py +74 -0
- tests/models/ipcc2019/test_organicCarbonPerHa.py +303 -1044
- tests/models/koble2014/test_residueBurnt.py +1 -2
- tests/models/koble2014/test_residueLeftOnField.py +1 -2
- tests/models/koble2014/test_residueRemoved.py +1 -2
- tests/models/koble2014/test_utils.py +52 -0
- tests/models/site/test_management.py +117 -0
- tests/models/site/test_organicCarbonPerHa.py +51 -5
- tests/models/utils/test_blank_node.py +230 -34
- tests/models/utils/test_term.py +17 -3
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/top_level.txt +0 -0
|
@@ -22,7 +22,7 @@ from . import MODEL
|
|
|
22
22
|
REQUIREMENTS = {
|
|
23
23
|
"Cycle": {
|
|
24
24
|
"completeness.animalFeed": "True",
|
|
25
|
-
"completeness.
|
|
25
|
+
"completeness.freshForage": "False",
|
|
26
26
|
"site": {
|
|
27
27
|
"@type": "Site",
|
|
28
28
|
"siteType": "permanent pasture"
|
|
@@ -584,7 +584,7 @@ def _should_run_practice(cycle: dict):
|
|
|
584
584
|
def _should_run(cycle: dict, practices: dict):
|
|
585
585
|
systems = filter_list_term_type(cycle.get('practices', []), TermTermType.SYSTEM)
|
|
586
586
|
animalFeed_complete = _is_term_type_complete(cycle, 'animalFeed')
|
|
587
|
-
|
|
587
|
+
freshForage_incomplete = _is_term_type_incomplete(cycle, 'freshForage')
|
|
588
588
|
all_animals_have_value = all([a.get('value', 0) > 0 for a in cycle.get('animals', [])])
|
|
589
589
|
|
|
590
590
|
meanDE = _calculate_meanDE(practices)
|
|
@@ -592,7 +592,7 @@ def _should_run(cycle: dict, practices: dict):
|
|
|
592
592
|
GE = _calculate_GE(cycle, meanDE, systems[0]) if all([meanDE > 0, len(systems) > 0]) else 0
|
|
593
593
|
|
|
594
594
|
should_run = all([
|
|
595
|
-
animalFeed_complete,
|
|
595
|
+
animalFeed_complete, freshForage_incomplete,
|
|
596
596
|
all_animals_have_value,
|
|
597
597
|
len(systems) > 0, len(practices) > 0,
|
|
598
598
|
GE > 0, meanECHHV > 0
|
|
@@ -601,7 +601,7 @@ def _should_run(cycle: dict, practices: dict):
|
|
|
601
601
|
for term_id in [MODEL_KEY] + [_practice_input_id(p) for p in practices]:
|
|
602
602
|
logRequirements(cycle, model=MODEL, term=term_id,
|
|
603
603
|
term_type_animalFeed_complete=animalFeed_complete,
|
|
604
|
-
|
|
604
|
+
term_type_freshForage_incomplete=freshForage_incomplete,
|
|
605
605
|
all_animals_have_value=all_animals_have_value,
|
|
606
606
|
meanDE=meanDE,
|
|
607
607
|
meanECHHV=meanECHHV,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from hestia_earth.
|
|
1
|
+
from hestia_earth.schema import TermTermType
|
|
2
|
+
from hestia_earth.utils.model import find_term_match, filter_list_term_type
|
|
2
3
|
from hestia_earth.utils.tools import safe_parse_float
|
|
3
4
|
|
|
4
5
|
from hestia_earth.models.log import debugValues
|
|
@@ -7,6 +8,7 @@ from hestia_earth.models.utils.cycle import get_ecoClimateZone
|
|
|
7
8
|
from hestia_earth.models.utils.constant import Units, get_atomic_conversion
|
|
8
9
|
from hestia_earth.models.utils.blank_node import find_terms_value
|
|
9
10
|
from hestia_earth.models.utils.term import get_lookup_value, get_milkYield_terms
|
|
11
|
+
from hestia_earth.models.utils.ecoClimateZone import get_ecoClimateZone_lookup_value
|
|
10
12
|
from . import MODEL
|
|
11
13
|
|
|
12
14
|
# From IPCC2019 Indirect N2O emission factor, in N [avg, min, max, std]
|
|
@@ -69,3 +71,102 @@ def get_yield_dm(term_id: str, term: dict):
|
|
|
69
71
|
def get_milkYield_practice(node: dict):
|
|
70
72
|
terms = get_milkYield_terms()
|
|
71
73
|
return next((p for p in node.get('practices', []) if p.get('term', {}).get('@id') in terms), {})
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def check_consecutive(ints: list[int]) -> bool:
|
|
77
|
+
"""
|
|
78
|
+
Checks whether a list of integers are consecutive.
|
|
79
|
+
|
|
80
|
+
Used to determine whether annualised data is complete from every year from beggining to end.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
ints : list[int]
|
|
85
|
+
A list of integer values.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
bool
|
|
90
|
+
Whether or not the list of integers is consecutive.
|
|
91
|
+
"""
|
|
92
|
+
range_list = list(range(min(ints), max(ints)+1)) if ints else []
|
|
93
|
+
return all(a == b for a, b in zip(ints, range_list))
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
N2O_FACTORS = {
|
|
97
|
+
# All N inputs in dry climate
|
|
98
|
+
'dry': {
|
|
99
|
+
'value': 0.005,
|
|
100
|
+
'min': 0,
|
|
101
|
+
'max': 0.011
|
|
102
|
+
},
|
|
103
|
+
'wet': {
|
|
104
|
+
# Synthetic fertiliser inputs in wet climate
|
|
105
|
+
TermTermType.INORGANICFERTILISER: {
|
|
106
|
+
'value': 0.016,
|
|
107
|
+
'min': 0.013,
|
|
108
|
+
'max': 0.019
|
|
109
|
+
},
|
|
110
|
+
# Other N inputs in wet climate
|
|
111
|
+
TermTermType.ORGANICFERTILISER: {
|
|
112
|
+
'value': 0.006,
|
|
113
|
+
'min': 0.001,
|
|
114
|
+
'max': 0.011
|
|
115
|
+
},
|
|
116
|
+
TermTermType.CROPRESIDUE: {
|
|
117
|
+
'value': 0.006,
|
|
118
|
+
'min': 0.001,
|
|
119
|
+
'max': 0.011
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
'default': {
|
|
123
|
+
'value': 0.01,
|
|
124
|
+
'min': 0.001,
|
|
125
|
+
'max': 0.018
|
|
126
|
+
},
|
|
127
|
+
'flooded_rice': {
|
|
128
|
+
'value': 0.004,
|
|
129
|
+
'min': 0,
|
|
130
|
+
'max': 0.029
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _get_waterRegime_lookup(model_term_id: str, practice: dict, col: str):
|
|
136
|
+
return safe_parse_float(get_lookup_value(practice.get('term', {}), col, model=MODEL, term=model_term_id), None)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _is_wet(ecoClimateZone: str = None):
|
|
140
|
+
return get_ecoClimateZone_lookup_value(ecoClimateZone, 'wet') == 1 if ecoClimateZone else None
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _ecoClimate_factors(input_term_type: TermTermType, ecoClimateZone: str = None):
|
|
144
|
+
is_wet = _is_wet(ecoClimateZone)
|
|
145
|
+
factors_key = 'default' if is_wet is None else 'wet' if is_wet else 'dry'
|
|
146
|
+
factors = N2O_FACTORS[factors_key]
|
|
147
|
+
return (factors.get(input_term_type) if factors_key == 'wet' else factors, is_wet is None)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _flooded_rice_factors(model_term_id: str, cycle: dict):
|
|
151
|
+
lookup_name = 'IPCC_2019_N2O_rice'
|
|
152
|
+
practices = filter_list_term_type(cycle.get('practices', []), TermTermType.WATERREGIME)
|
|
153
|
+
practice = next((p for p in practices if _get_waterRegime_lookup(model_term_id, p, lookup_name) is not None), None)
|
|
154
|
+
|
|
155
|
+
factors = {
|
|
156
|
+
'value': _get_waterRegime_lookup(model_term_id, practice, lookup_name),
|
|
157
|
+
'min': _get_waterRegime_lookup(model_term_id, practice, lookup_name + '-min'),
|
|
158
|
+
'max': _get_waterRegime_lookup(model_term_id, practice, lookup_name + '-max')
|
|
159
|
+
} if practice else N2O_FACTORS['flooded_rice']
|
|
160
|
+
|
|
161
|
+
return (factors, practice is None)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def get_N2O_factors(
|
|
165
|
+
model_term_id: str,
|
|
166
|
+
cycle: dict,
|
|
167
|
+
input_term_type: TermTermType,
|
|
168
|
+
ecoClimateZone: str = None,
|
|
169
|
+
flooded_rice: bool = False
|
|
170
|
+
):
|
|
171
|
+
return _flooded_rice_factors(model_term_id, cycle) if flooded_rice \
|
|
172
|
+
else _ecoClimate_factors(input_term_type, ecoClimateZone)
|
|
@@ -12,6 +12,7 @@ from hestia_earth.utils.model import find_term_match
|
|
|
12
12
|
from hestia_earth.utils.tools import flatten, list_sum, list_average
|
|
13
13
|
|
|
14
14
|
from hestia_earth.models.log import logRequirements, logShouldRun, debugValues
|
|
15
|
+
from hestia_earth.models.utils.cropResidue import PRODUCT_ID_TO_PRACTICES_ID
|
|
15
16
|
from hestia_earth.models.utils.product import _new_product
|
|
16
17
|
from hestia_earth.models.utils.completeness import _is_term_type_incomplete
|
|
17
18
|
from . import MODEL
|
|
@@ -38,20 +39,16 @@ RETURNS = {
|
|
|
38
39
|
}
|
|
39
40
|
TERM_ID = 'aboveGroundCropResidueLeftOnField,aboveGroundCropResidueBurnt,aboveGroundCropResidueIncorporated,aboveGroundCropResidueRemoved' # noqa: E501
|
|
40
41
|
TOTAL_TERM_ID = 'aboveGroundCropResidueTotal'
|
|
41
|
-
|
|
42
|
-
{'term': 'aboveGroundCropResidueRemoved', 'practices': ['residueRemoved']},
|
|
43
|
-
{'term': 'aboveGroundCropResidueIncorporated', 'practices': [
|
|
44
|
-
'residueIncorporated',
|
|
45
|
-
'residueIncorporatedLessThan30DaysBeforeCultivation',
|
|
46
|
-
'residueIncorporatedMoreThan30DaysBeforeCultivation'
|
|
47
|
-
]},
|
|
48
|
-
{'term': 'aboveGroundCropResidueBurnt', 'practices': ['residueBurnt']}
|
|
49
|
-
]
|
|
50
|
-
REMAINING_MODEL = 'aboveGroundCropResidueLeftOnField'
|
|
42
|
+
REMAINING_MODEL = PRODUCT_ID_TO_PRACTICES_ID[-1]['product']
|
|
51
43
|
|
|
52
44
|
|
|
53
45
|
def _get_practices(term_id: str):
|
|
54
|
-
return flatten([
|
|
46
|
+
return flatten([
|
|
47
|
+
model.get('practices', []) for model in PRODUCT_ID_TO_PRACTICES_ID if all([
|
|
48
|
+
model.get('product') == term_id,
|
|
49
|
+
model.get('product') != REMAINING_MODEL
|
|
50
|
+
])
|
|
51
|
+
])
|
|
55
52
|
|
|
56
53
|
|
|
57
54
|
def _get_practice_value(term_ids: list, cycle: dict) -> float:
|
|
@@ -63,12 +60,12 @@ def _get_practice_value(term_ids: list, cycle: dict) -> float:
|
|
|
63
60
|
|
|
64
61
|
|
|
65
62
|
def _product(term_id: str, value: float):
|
|
66
|
-
product = _new_product(term_id, value, MODEL)
|
|
63
|
+
product = _new_product(term_id, round(value, 2), MODEL)
|
|
67
64
|
return product
|
|
68
65
|
|
|
69
66
|
|
|
70
67
|
def _should_run_model(model, cycle: dict, total_value: float):
|
|
71
|
-
term_id = model.get('
|
|
68
|
+
term_id = model.get('product')
|
|
72
69
|
practice_value = _get_practice_value(model.get('practices'), cycle)
|
|
73
70
|
has_product = find_term_match(cycle.get('products', []), term_id, None) is not None
|
|
74
71
|
|
|
@@ -102,15 +99,16 @@ def _run(cycle: dict, total_values: list):
|
|
|
102
99
|
total_value = list_average(total_values)
|
|
103
100
|
# first, calculate the remaining value available after applying all user-uploaded data
|
|
104
101
|
remaining_value = reduce(
|
|
105
|
-
lambda prev, model: prev - _model_value(model.get('
|
|
106
|
-
|
|
102
|
+
lambda prev, model: prev - _model_value(model.get('product'), products),
|
|
103
|
+
PRODUCT_ID_TO_PRACTICES_ID,
|
|
107
104
|
total_value
|
|
108
105
|
)
|
|
109
106
|
|
|
110
107
|
values = []
|
|
111
108
|
# then run every model in order up to the remaining value
|
|
112
|
-
for model in
|
|
113
|
-
|
|
109
|
+
models = [model for model in PRODUCT_ID_TO_PRACTICES_ID if model.get('product') != REMAINING_MODEL]
|
|
110
|
+
for model in models:
|
|
111
|
+
term_id = model.get('product')
|
|
114
112
|
value = _run_model(model, cycle, total_value)
|
|
115
113
|
debugValues(cycle, model=MODEL, term=term_id,
|
|
116
114
|
total_value=total_value,
|
|
@@ -8,7 +8,7 @@ from hestia_earth.schema import TermTermType
|
|
|
8
8
|
from hestia_earth.utils.model import filter_list_term_type
|
|
9
9
|
from hestia_earth.utils.tools import list_sum
|
|
10
10
|
|
|
11
|
-
from hestia_earth.models.log import logRequirements, logShouldRun
|
|
11
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_blank_nodes_id
|
|
12
12
|
from hestia_earth.models.utils import is_from_model
|
|
13
13
|
from hestia_earth.models.utils.blank_node import get_total_value
|
|
14
14
|
from .utils import _practice
|
|
@@ -66,7 +66,7 @@ def _should_run(cycle: dict):
|
|
|
66
66
|
logRequirements(cycle, model=MODEL_LOG,
|
|
67
67
|
total_value=total_value,
|
|
68
68
|
recalculated_total_value=recalculated_total_value,
|
|
69
|
-
|
|
69
|
+
recalculated_practice_ids=log_blank_nodes_id(recalculated_practices))
|
|
70
70
|
|
|
71
71
|
should_run = all([total_value > 0, total_value != 100, recalculated_total_value > 0])
|
|
72
72
|
logShouldRun(cycle, MODEL_LOG, None, should_run)
|
|
@@ -3,10 +3,12 @@ from hestia_earth.schema import TermTermType
|
|
|
3
3
|
from hestia_earth.utils.model import find_primary_product, find_term_match
|
|
4
4
|
from hestia_earth.utils.tools import list_sum
|
|
5
5
|
|
|
6
|
-
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
|
|
6
|
+
from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table, log_blank_nodes_id
|
|
7
|
+
from hestia_earth.models.utils import is_from_model
|
|
7
8
|
from hestia_earth.models.utils.completeness import _is_term_type_incomplete
|
|
8
9
|
from hestia_earth.models.utils.practice import _new_practice
|
|
9
10
|
from hestia_earth.models.utils.term import get_crop_residue_management_terms
|
|
11
|
+
from hestia_earth.models.utils.cropResidue import crop_residue_product_ids
|
|
10
12
|
from . import MODEL
|
|
11
13
|
|
|
12
14
|
|
|
@@ -23,6 +25,7 @@ def _model_value(term_id: str, practices: list):
|
|
|
23
25
|
def _should_run(term_id: str, cycle: dict, require_country: bool = False):
|
|
24
26
|
primary_product = find_primary_product(cycle)
|
|
25
27
|
has_primary_product = primary_product is not None
|
|
28
|
+
|
|
26
29
|
crop_residue_incomplete = _is_term_type_incomplete(cycle, TermTermType.CROPRESIDUE)
|
|
27
30
|
practices = cycle.get('practices', [])
|
|
28
31
|
residue_terms = get_crop_residue_management_terms()
|
|
@@ -32,6 +35,16 @@ def _should_run(term_id: str, cycle: dict, require_country: bool = False):
|
|
|
32
35
|
])
|
|
33
36
|
has_remaining_value = remaining_value > 0
|
|
34
37
|
|
|
38
|
+
# make sure no above ground residue product has been added by the user, or values will be off
|
|
39
|
+
provided_cropResidue_products = [
|
|
40
|
+
p for p in cycle.get('products', []) if all([
|
|
41
|
+
p.get('term', {}).get('@id') in crop_residue_product_ids(),
|
|
42
|
+
p.get('value', []),
|
|
43
|
+
not is_from_model(p)
|
|
44
|
+
])
|
|
45
|
+
]
|
|
46
|
+
has_provided_cropResidue_products = len(provided_cropResidue_products) > 0
|
|
47
|
+
|
|
35
48
|
country_id = cycle.get('site', {}).get('country', {}).get('@id')
|
|
36
49
|
|
|
37
50
|
logRequirements(cycle, model=MODEL, term=term_id,
|
|
@@ -39,11 +52,14 @@ def _should_run(term_id: str, cycle: dict, require_country: bool = False):
|
|
|
39
52
|
term_type_cropResidue_incomplete=crop_residue_incomplete,
|
|
40
53
|
has_remaining_value=has_remaining_value,
|
|
41
54
|
crop_residue_values=residue_values,
|
|
42
|
-
country_id=country_id
|
|
55
|
+
country_id=country_id,
|
|
56
|
+
has_provided_cropResidue_products=has_provided_cropResidue_products,
|
|
57
|
+
provided_cropResidue_product_ids=log_blank_nodes_id(provided_cropResidue_products))
|
|
43
58
|
|
|
44
59
|
should_run = all([
|
|
45
60
|
has_primary_product, crop_residue_incomplete, has_remaining_value,
|
|
46
|
-
not require_country or country_id
|
|
61
|
+
not require_country or country_id,
|
|
62
|
+
not has_provided_cropResidue_products
|
|
47
63
|
])
|
|
48
64
|
logShouldRun(cycle, MODEL, term_id, should_run)
|
|
49
65
|
return should_run, remaining_value, primary_product, country_id
|
|
@@ -83,8 +83,9 @@ def _group_emissions(impact: dict):
|
|
|
83
83
|
def _group_by(prev: dict, emission: dict):
|
|
84
84
|
term_id = emission.get('term', {}).get('@id')
|
|
85
85
|
grouping = _emission_group(term_id)
|
|
86
|
+
value = emission.get('value') or 0
|
|
86
87
|
if grouping:
|
|
87
|
-
prev[grouping] = prev.get(grouping, 0) +
|
|
88
|
+
prev[grouping] = prev.get(grouping, 0) + value
|
|
88
89
|
return prev
|
|
89
90
|
|
|
90
91
|
emissions = impact.get('emissionsResourceUse', [])
|
|
@@ -101,7 +102,8 @@ def _run_input(cycle: dict):
|
|
|
101
102
|
emissions = _group_emissions(impact)
|
|
102
103
|
|
|
103
104
|
logRequirements(cycle, model=model, term=term_id,
|
|
104
|
-
impact_assessment_id=input.get('impactAssessment', {}).get('@id')
|
|
105
|
+
impact_assessment_id=input.get('impactAssessment', {}).get('@id'),
|
|
106
|
+
input_value=input_value)
|
|
105
107
|
logShouldRun(cycle, model, term_id, True, methodTier=TIER)
|
|
106
108
|
|
|
107
109
|
return [
|
hestia_earth/models/log.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
3
|
import logging
|
|
4
|
-
from typing import Union
|
|
4
|
+
from typing import Union, List
|
|
5
5
|
|
|
6
6
|
LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO')
|
|
7
7
|
|
|
@@ -57,7 +57,7 @@ def logRequirements(log_node: dict, **kwargs):
|
|
|
57
57
|
logger.info(_log_node_suffix(log_node) + 'requirements=true, ' + _join_args(**kwargs))
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def logShouldRun(log_node: dict, model: str, term: str, should_run: bool, **kwargs):
|
|
60
|
+
def logShouldRun(log_node: dict, model: str, term: Union[str, None], should_run: bool, **kwargs):
|
|
61
61
|
extra = (', ' + _join_args(**kwargs)) if len(kwargs.keys()) > 0 else ''
|
|
62
62
|
logger.info(_log_node_suffix(log_node) + 'should_run=%s, model=%s, term=%s' + extra, should_run, model, term)
|
|
63
63
|
|
|
@@ -89,4 +89,16 @@ def log_as_table(values: Union[list, dict]):
|
|
|
89
89
|
(
|
|
90
90
|
'_'.join([f"{k}:{v}" for k, v in value.items()]) if isinstance(value, dict) else str(value)
|
|
91
91
|
) for value in values
|
|
92
|
-
])
|
|
92
|
+
]) or 'None'
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def log_blank_nodes_id(blank_nodes: List[dict]):
|
|
96
|
+
"""
|
|
97
|
+
Log a list of blank node ids to display as a table.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
values : list
|
|
102
|
+
List of blank nodes, like Product, Input, Measurement, etc.
|
|
103
|
+
"""
|
|
104
|
+
return ';'.join([p.get('term', {}).get('@id') for p in blank_nodes if p.get('term', {}).get('@id')]) or 'None'
|