hestia-earth-models 0.59.7__py3-none-any.whl → 0.60.1__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/cache_sites.py +40 -16
- hestia_earth/models/ipcc2019/animal/__init__.py +0 -0
- hestia_earth/models/ipcc2019/animal/pastureGrass.py +298 -0
- hestia_earth/models/ipcc2019/{co2ToAirSoilCarbonStockChangeManagementChange.py → co2ToAirSoilOrganicCarbonStockChangeManagementChange.py} +2 -2
- hestia_earth/models/ipcc2019/pastureGrass.py +73 -447
- hestia_earth/models/ipcc2019/pastureGrass_utils.py +415 -0
- hestia_earth/models/mocking/search-results.json +215 -207
- hestia_earth/models/site/pre_checks/cache_geospatialDatabase.py +16 -4
- hestia_earth/models/utils/completeness.py +17 -14
- hestia_earth/models/utils/feedipedia.py +23 -23
- hestia_earth/models/utils/property.py +3 -1
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.59.7.dist-info → hestia_earth_models-0.60.1.dist-info}/LICENSE +1 -1
- {hestia_earth_models-0.59.7.dist-info → hestia_earth_models-0.60.1.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.59.7.dist-info → hestia_earth_models-0.60.1.dist-info}/RECORD +39 -34
- tests/models/cycle/animal/input/test_properties.py +3 -1
- tests/models/cycle/animal/test_properties.py +4 -2
- tests/models/cycle/input/test_properties.py +3 -1
- tests/models/cycle/product/test_properties.py +2 -1
- tests/models/cycle/test_coldCarcassWeightPerHead.py +1 -0
- tests/models/cycle/test_coldDressedCarcassWeightPerHead.py +1 -0
- tests/models/cycle/test_energyContentLowerHeatingValue.py +1 -0
- tests/models/cycle/test_feedConversionRatio.py +10 -0
- tests/models/cycle/test_readyToCookWeightPerHead.py +1 -0
- tests/models/ipcc2006/test_n2OToAirCropResidueDecompositionDirect.py +4 -1
- tests/models/ipcc2019/animal/__init__.py +0 -0
- tests/models/ipcc2019/animal/test_pastureGrass.py +45 -0
- tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +32 -8
- tests/models/ipcc2019/{test_co2ToAirSoilCarbonStockChangeManagementChange.py → test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py} +1 -1
- tests/models/ipcc2019/test_n2OToAirCropResidueDecompositionDirect.py +6 -1
- tests/models/ipcc2019/test_n2OToAirInorganicFertiliserDirect.py +6 -1
- tests/models/ipcc2019/test_n2OToAirOrganicFertiliserDirect.py +6 -1
- tests/models/ipcc2019/test_pastureGrass.py +32 -8
- tests/models/pooreNemecek2018/test_excretaKgN.py +5 -0
- tests/models/pooreNemecek2018/test_excretaKgVs.py +5 -0
- tests/models/pooreNemecek2018/test_no3ToGroundwaterSoilFlux.py +1 -0
- tests/models/test_cache_sites.py +10 -7
- {hestia_earth_models-0.59.7.dist-info → hestia_earth_models-0.60.1.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.59.7.dist-info → hestia_earth_models-0.60.1.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from functools import reduce
|
|
2
2
|
from enum import Enum
|
|
3
|
+
from pydash.objects import merge
|
|
3
4
|
from hestia_earth.utils.api import download_hestia
|
|
4
5
|
from hestia_earth.utils.tools import flatten
|
|
5
6
|
|
|
@@ -64,12 +65,13 @@ def _run_values(sites: list, param_type: ParamType, rasters: list = [], vectors:
|
|
|
64
65
|
**_cache_results(raster_results, rasters, index),
|
|
65
66
|
**_cache_results(vector_results, vectors, index)
|
|
66
67
|
} | ({CACHE_AREA_SIZE: area_size} if area_size is not None else {})
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
CACHE_KEY
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
cached_data = merge(cached_value(site, CACHE_GEOSPATIAL_KEY, {}), cached_data)
|
|
69
|
+
site_cache = merge(
|
|
70
|
+
site.get(CACHE_KEY, {}),
|
|
71
|
+
{CACHE_GEOSPATIAL_KEY: cached_data},
|
|
72
|
+
({CACHE_YEARS_KEY: cached_value(site, CACHE_YEARS_KEY, []) + years} if years else {})
|
|
73
|
+
)
|
|
74
|
+
return merge(site, {CACHE_KEY: site_cache})
|
|
73
75
|
|
|
74
76
|
return reduce(lambda prev, curr: prev + [_process_site(curr)], sites, [])
|
|
75
77
|
|
|
@@ -82,7 +84,7 @@ def _preload_regions_area_size(sites: dict):
|
|
|
82
84
|
return {term_id: download_hestia(term_id).get('area') for term_id in region_ids}
|
|
83
85
|
|
|
84
86
|
|
|
85
|
-
def _group_sites(sites: dict):
|
|
87
|
+
def _group_sites(sites: dict, check_has_cache: bool = True):
|
|
86
88
|
# preload area size for all regions
|
|
87
89
|
regions_area_size = _preload_regions_area_size(sites)
|
|
88
90
|
|
|
@@ -90,7 +92,7 @@ def _group_sites(sites: dict):
|
|
|
90
92
|
return regions_area_size.get(_site_gadm_id(site)) if _should_preload_region_area_size(site) else None
|
|
91
93
|
|
|
92
94
|
sites = [
|
|
93
|
-
(n, ) + (_should_run(n, get_region_area_size(n))) for n in sites
|
|
95
|
+
(n, ) + (_should_run(n, area_size=get_region_area_size(n), check_has_cache=check_has_cache)) for n in sites
|
|
94
96
|
]
|
|
95
97
|
# restrict sites based on should_cache result
|
|
96
98
|
sites = [(site, area_size) for site, should_cache, area_size in sites if should_cache]
|
|
@@ -112,6 +114,24 @@ def _group_sites(sites: dict):
|
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
|
|
117
|
+
def _run(sites: list, years: list, include_region: bool, years_only: bool = False):
|
|
118
|
+
rasters, vectors = list_collections(years, include_region, years_only)
|
|
119
|
+
filtered_data = _group_sites(sites, not years_only)
|
|
120
|
+
return flatten([
|
|
121
|
+
_run_values(filtered_data.get(param_type), param_type, rasters, vectors, years)
|
|
122
|
+
for param_type in [e for e in ParamType] if len(filtered_data.get(param_type)) > 0
|
|
123
|
+
])
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _group_years(years: list, years_range: int):
|
|
127
|
+
batches = sorted(list(set(list(range(years[0], years[-1] + 1, years_range)) + [years[0], years[-1]])))
|
|
128
|
+
grouped_batches = [batches[i:i+2] for i in range(0, len(batches))]
|
|
129
|
+
return [
|
|
130
|
+
# make sure we don't overlap
|
|
131
|
+
[v[0] + (0 if v[0] == years[0] else 1), v[1]] for v in grouped_batches if len(v) == 2
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
|
|
115
135
|
def run(sites: list, years: list = None, include_region: bool = False):
|
|
116
136
|
"""
|
|
117
137
|
Run all queries at once for the list of provided Sites.
|
|
@@ -127,11 +147,15 @@ def run(sites: list, years: list = None, include_region: bool = False):
|
|
|
127
147
|
Prefecth region IDs.
|
|
128
148
|
This will cache region-level data and will make the request slower. Only use if needed.
|
|
129
149
|
"""
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
150
|
+
try:
|
|
151
|
+
return _run(sites, years, include_region)
|
|
152
|
+
except Exception as e:
|
|
153
|
+
# when querying with multiple years, we can reach a compute memory limit, so run the years separately
|
|
154
|
+
if str(e) == 'User memory limit exceeded.' and years:
|
|
155
|
+
sites = _run(sites, [], include_region)
|
|
156
|
+
# query for subranges
|
|
157
|
+
for sub_years in _group_years(years, years_range=5):
|
|
158
|
+
sites = _run(sites, sub_years, include_region, years_only=True)
|
|
159
|
+
return sites
|
|
160
|
+
|
|
161
|
+
return []
|
|
File without changes
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Full Grass Consumption
|
|
3
|
+
|
|
4
|
+
This model estimates the energetic requirements of ruminants and can be used to estimate the amount of grass they graze.
|
|
5
|
+
Source:
|
|
6
|
+
[IPCC 2019, Vol.4, Chapter 10](https://www.ipcc-nggip.iges.or.jp/public/2019rf/pdf/4_Volume4/19R_V4_Ch10_Livestock.pdf).
|
|
7
|
+
"""
|
|
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, debugValues
|
|
13
|
+
from hestia_earth.models.utils.input import _new_input
|
|
14
|
+
from hestia_earth.models.utils.term import get_wool_terms, get_lookup_value
|
|
15
|
+
from hestia_earth.models.utils.completeness import _is_term_type_complete, _is_term_type_incomplete
|
|
16
|
+
from hestia_earth.models.utils.property import get_node_property
|
|
17
|
+
from .. import MODEL
|
|
18
|
+
from ..pastureGrass_utils import (
|
|
19
|
+
practice_input_id,
|
|
20
|
+
should_run_practice,
|
|
21
|
+
calculate_meanDE,
|
|
22
|
+
calculate_meanECHHV,
|
|
23
|
+
calculate_REM,
|
|
24
|
+
calculate_REG,
|
|
25
|
+
calculate_NEfeed,
|
|
26
|
+
product_wool_energy,
|
|
27
|
+
get_animals,
|
|
28
|
+
get_animal_values
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
REQUIREMENTS = {
|
|
32
|
+
"Cycle": {
|
|
33
|
+
"completeness.animalFeed": "True",
|
|
34
|
+
"completeness.animalPopulation": "True",
|
|
35
|
+
"completeness.freshForage": "False",
|
|
36
|
+
"site": {
|
|
37
|
+
"@type": "Site",
|
|
38
|
+
"siteType": "permanent pasture"
|
|
39
|
+
},
|
|
40
|
+
"practices": [{
|
|
41
|
+
"@type": "Practice",
|
|
42
|
+
"value": "",
|
|
43
|
+
"term.@id": "pastureGrass",
|
|
44
|
+
"key": {
|
|
45
|
+
"@type": "Term",
|
|
46
|
+
"term.termType": "landCover"
|
|
47
|
+
}
|
|
48
|
+
}],
|
|
49
|
+
"animals": [{
|
|
50
|
+
"@type": "Animal",
|
|
51
|
+
"value": "> 0",
|
|
52
|
+
"term.termType": "liveAnimal",
|
|
53
|
+
"referencePeriod": "average",
|
|
54
|
+
"properties": [{
|
|
55
|
+
"@type": "Property",
|
|
56
|
+
"value": "",
|
|
57
|
+
"term.@id": [
|
|
58
|
+
"liveweightPerHead",
|
|
59
|
+
"weightAtMaturity"
|
|
60
|
+
]
|
|
61
|
+
}],
|
|
62
|
+
"optional": {
|
|
63
|
+
"properties": [{
|
|
64
|
+
"@type": "Property",
|
|
65
|
+
"value": "",
|
|
66
|
+
"term.@id": [
|
|
67
|
+
"hoursWorkedPerDay",
|
|
68
|
+
"pregnancyRateTotal",
|
|
69
|
+
"animalsPerBirth"
|
|
70
|
+
]
|
|
71
|
+
}],
|
|
72
|
+
"inputs": [{
|
|
73
|
+
"@type": "Input",
|
|
74
|
+
"term.units": "kg",
|
|
75
|
+
"value": "> 0",
|
|
76
|
+
"optional": {
|
|
77
|
+
"properties": [{
|
|
78
|
+
"@type": "Property",
|
|
79
|
+
"value": "",
|
|
80
|
+
"term.@id": ["neutralDetergentFibreContent", "energyContentHigherHeatingValue"]
|
|
81
|
+
}]
|
|
82
|
+
}
|
|
83
|
+
}],
|
|
84
|
+
"practices": [{
|
|
85
|
+
"@type": "Practice",
|
|
86
|
+
"value": "",
|
|
87
|
+
"term.termType": "animalManagement",
|
|
88
|
+
"properties": [{
|
|
89
|
+
"@type": "Property",
|
|
90
|
+
"value": "",
|
|
91
|
+
"term.@id": "fatContent"
|
|
92
|
+
}]
|
|
93
|
+
}]
|
|
94
|
+
}
|
|
95
|
+
}],
|
|
96
|
+
"none": {
|
|
97
|
+
"inputs": [{
|
|
98
|
+
"@type": "Input",
|
|
99
|
+
"term.units": "kg",
|
|
100
|
+
"value": "> 0",
|
|
101
|
+
"isAnimalFeed": "True"
|
|
102
|
+
}]
|
|
103
|
+
},
|
|
104
|
+
"optional": {
|
|
105
|
+
"products": [{
|
|
106
|
+
"@type": "Product",
|
|
107
|
+
"value": "",
|
|
108
|
+
"term.@id": "animalProduct"
|
|
109
|
+
}]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
LOOKUPS = {
|
|
114
|
+
"animalManagement": [
|
|
115
|
+
"mjKgEvMilkIpcc2019"
|
|
116
|
+
],
|
|
117
|
+
"animalProduct": ["mjKgEvWoolNetEnergyWoolIpcc2019", "allowedLiveAnimalTermIds"],
|
|
118
|
+
"liveAnimal": [
|
|
119
|
+
"ipcc2019AnimalTypeGrouping",
|
|
120
|
+
"mjDayKgCfiNetEnergyMaintenanceIpcc2019",
|
|
121
|
+
"ratioCPregnancyNetEnergyPregnancyIpcc2019",
|
|
122
|
+
"ratioCNetEnergyGrowthCattleBuffaloIpcc2019",
|
|
123
|
+
"mjKgABNetEnergyGrowthSheepGoatsIpcc2019",
|
|
124
|
+
"isWoolProducingAnimal"
|
|
125
|
+
],
|
|
126
|
+
"system-liveAnimal-activityCoefficient-ipcc2019": "using animal term @id",
|
|
127
|
+
"crop-property": ["energyDigestibilityRuminants", "energyContentHigherHeatingValue"],
|
|
128
|
+
"crop": "grazedPastureGrassInputId",
|
|
129
|
+
"forage-property": ["energyDigestibilityRuminants", "energyContentHigherHeatingValue"],
|
|
130
|
+
"landCover": "grazedPastureGrassInputId"
|
|
131
|
+
}
|
|
132
|
+
RETURNS = {
|
|
133
|
+
"Animal": [{
|
|
134
|
+
"Input": [{
|
|
135
|
+
"@type": "Input",
|
|
136
|
+
"term.termType": ["crop", "forage"],
|
|
137
|
+
"value": ""
|
|
138
|
+
}]
|
|
139
|
+
}]
|
|
140
|
+
}
|
|
141
|
+
MODEL_KEY = 'animal/pastureGrass'
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _input(term_id: str, value: float):
|
|
145
|
+
node = _new_input(term_id, MODEL)
|
|
146
|
+
node['value'] = [value]
|
|
147
|
+
return node
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _sum_liveWeightPerHead(animals: list):
|
|
151
|
+
return list_sum([
|
|
152
|
+
animal.get('value', 0) * get_node_property(animal, 'liveweightPerHead', False).get('value', 0)
|
|
153
|
+
for animal in animals
|
|
154
|
+
])
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _isNEwool_animal(animal: dict):
|
|
158
|
+
value = get_lookup_value(animal.get('term', {}), 'isWoolProducingAnimal', model=MODEL, model_key=MODEL_KEY)
|
|
159
|
+
return not (not value)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _is_NEwool_product(product: dict, animal: dict):
|
|
163
|
+
animal_term_ids = get_lookup_value(product, 'allowedLiveAnimalTermIds', model=MODEL, model_key=MODEL_KEY).split(';')
|
|
164
|
+
return animal.get('term', {}).get('@id') in animal_term_ids
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def calculate_NEwool(cycle: dict, animal: dict, products: list, total_weight: float) -> float:
|
|
168
|
+
term_id = animal.get('term', {}).get('@id')
|
|
169
|
+
|
|
170
|
+
wool_products = [p for p in products if _is_NEwool_product(p.get('term', {}), animal)]
|
|
171
|
+
total_energy = list_sum([
|
|
172
|
+
list_sum(product.get('value', [])) * product_wool_energy(product) for product in wool_products
|
|
173
|
+
])
|
|
174
|
+
animal_weight = _sum_liveWeightPerHead([animal])
|
|
175
|
+
|
|
176
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
177
|
+
total_energy=total_energy,
|
|
178
|
+
animal_liveWeightPerHead=animal_weight,
|
|
179
|
+
total_liveWeightPerHead=total_weight)
|
|
180
|
+
|
|
181
|
+
return total_energy * animal_weight/total_weight
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _calculate_GE(
|
|
185
|
+
cycle: dict, animal: dict, REM: float, REG: float, NEwool: float, system: dict
|
|
186
|
+
) -> float:
|
|
187
|
+
term_id = animal.get('term', {}).get('@id')
|
|
188
|
+
|
|
189
|
+
NEm, NEa, NEl, NEwork, NEp, NEg = get_animal_values(cycle, animal, system)
|
|
190
|
+
|
|
191
|
+
NEm_feed, NEg_feed = calculate_NEfeed(animal)
|
|
192
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
193
|
+
NEm_feed=NEm_feed,
|
|
194
|
+
NEg_feed=NEg_feed)
|
|
195
|
+
|
|
196
|
+
return (NEm + NEa + NEl + NEwork + NEp - NEm_feed)/REM + (NEg + NEwool - NEg_feed)/REG
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _run_practice(cycle: dict, GE: float, meanECHHV: float):
|
|
200
|
+
def run(practice: dict):
|
|
201
|
+
key = practice.get('key', {})
|
|
202
|
+
key_id = key.get('@id')
|
|
203
|
+
input_term_id = practice_input_id(practice)
|
|
204
|
+
value = (GE / meanECHHV) * (list_sum(practice.get('value', [0])) / 100)
|
|
205
|
+
|
|
206
|
+
logRequirements(cycle, model=MODEL, term=input_term_id, model_key=MODEL_KEY,
|
|
207
|
+
GE=GE,
|
|
208
|
+
meanECHHV=meanECHHV,
|
|
209
|
+
key_id=key_id)
|
|
210
|
+
|
|
211
|
+
logShouldRun(cycle, MODEL, input_term_id, True, model_key=MODEL_KEY)
|
|
212
|
+
|
|
213
|
+
return _input(input_term_id, value)
|
|
214
|
+
|
|
215
|
+
return run
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _run_animal(cycle: dict, meanDE: float, meanECHHV: float, system: dict, practices: list):
|
|
219
|
+
REM = calculate_REM(meanDE)
|
|
220
|
+
REG = calculate_REG(meanDE)
|
|
221
|
+
|
|
222
|
+
wool_term_ids = get_wool_terms()
|
|
223
|
+
# list of animal product
|
|
224
|
+
wool_products = [p for p in cycle.get('products', []) if p.get('term', {}).get('@id') in wool_term_ids]
|
|
225
|
+
animals = list(filter(_isNEwool_animal, cycle.get('animals', [])))
|
|
226
|
+
total_liveWeightPerHead = _sum_liveWeightPerHead(animals)
|
|
227
|
+
|
|
228
|
+
def run(animal: dict):
|
|
229
|
+
term_id = animal.get('term', {}).get('@id')
|
|
230
|
+
|
|
231
|
+
NEwool = calculate_NEwool(cycle, animal, wool_products, total_liveWeightPerHead) if (
|
|
232
|
+
total_liveWeightPerHead > 0
|
|
233
|
+
) else 0
|
|
234
|
+
GE = (_calculate_GE(cycle, animal, REM, REG, NEwool, system) / (meanDE/100)) if all([REM, REG]) else 0
|
|
235
|
+
|
|
236
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
237
|
+
REM=REM,
|
|
238
|
+
REG=REG,
|
|
239
|
+
NEwool=NEwool,
|
|
240
|
+
GE=GE,
|
|
241
|
+
meanDE=meanDE)
|
|
242
|
+
|
|
243
|
+
inputs = list(map(_run_practice(cycle, GE, meanECHHV), practices))
|
|
244
|
+
return animal | {
|
|
245
|
+
'inputs': animal.get('inputs', []) + inputs
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return run
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _run(cycle: dict, meanDE: float, meanECHHV: float, system: dict, practices: list):
|
|
252
|
+
animals = get_animals(cycle)
|
|
253
|
+
return list(map(_run_animal(cycle, meanDE, meanECHHV, system, practices), animals))
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _should_run(cycle: dict, practices: dict):
|
|
257
|
+
systems = filter_list_term_type(cycle.get('practices', []), TermTermType.SYSTEM)
|
|
258
|
+
animalFeed_complete = _is_term_type_complete(cycle, 'animalFeed')
|
|
259
|
+
animalPopulation_complete = _is_term_type_complete(cycle, 'animalPopulation')
|
|
260
|
+
freshForage_incomplete = _is_term_type_incomplete(cycle, 'freshForage')
|
|
261
|
+
all_animals_have_value = all([a.get('value', 0) > 0 for a in cycle.get('animals', [])])
|
|
262
|
+
|
|
263
|
+
no_cycle_inputs_feed = all([not input.get('isAnimalFeed', False) for input in cycle.get('inputs', [])])
|
|
264
|
+
|
|
265
|
+
meanDE = calculate_meanDE(practices)
|
|
266
|
+
meanECHHV = calculate_meanECHHV(practices)
|
|
267
|
+
|
|
268
|
+
should_run = all([
|
|
269
|
+
animalFeed_complete,
|
|
270
|
+
animalPopulation_complete,
|
|
271
|
+
freshForage_incomplete,
|
|
272
|
+
no_cycle_inputs_feed,
|
|
273
|
+
all_animals_have_value,
|
|
274
|
+
len(systems) > 0,
|
|
275
|
+
len(practices) > 0,
|
|
276
|
+
meanDE > 0,
|
|
277
|
+
meanECHHV > 0
|
|
278
|
+
])
|
|
279
|
+
|
|
280
|
+
for term_id in [MODEL_KEY] + [practice_input_id(p) for p in practices]:
|
|
281
|
+
logRequirements(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
282
|
+
term_type_animalFeed_complete=animalFeed_complete,
|
|
283
|
+
term_type_animalPopulation_complete=animalPopulation_complete,
|
|
284
|
+
term_type_freshForage_incomplete=freshForage_incomplete,
|
|
285
|
+
no_cycle_inputs_feed=no_cycle_inputs_feed,
|
|
286
|
+
all_animals_have_value=all_animals_have_value,
|
|
287
|
+
meanDE=meanDE,
|
|
288
|
+
meanECHHV=meanECHHV)
|
|
289
|
+
|
|
290
|
+
logShouldRun(cycle, MODEL, term_id, should_run, model_key=MODEL_KEY)
|
|
291
|
+
|
|
292
|
+
return should_run, meanDE, meanECHHV, systems[0] if systems else None
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def run(cycle: dict):
|
|
296
|
+
practices = list(filter(should_run_practice(cycle), cycle.get('practices', [])))
|
|
297
|
+
should_run, meanDE, meanECHHV, system = _should_run(cycle, practices)
|
|
298
|
+
return _run(cycle, meanDE, meanECHHV, system, practices) if should_run else []
|
|
@@ -50,7 +50,7 @@ RETURNS = {
|
|
|
50
50
|
"depth": "30"
|
|
51
51
|
}]
|
|
52
52
|
}
|
|
53
|
-
TERM_ID = '
|
|
53
|
+
TERM_ID = 'co2ToAirSoilOrganicCarbonStockChangeManagementChange'
|
|
54
54
|
|
|
55
55
|
DEPTH_UPPER = 0
|
|
56
56
|
DEPTH_LOWER = 30
|
|
@@ -101,7 +101,7 @@ MEASUREMENT_METHOD_RANKING = [
|
|
|
101
101
|
]
|
|
102
102
|
"""
|
|
103
103
|
A ranking of `MeasurementMethodClassification`s from weakest to strongest used to determine the `EmissionMethodTier` of
|
|
104
|
-
the `
|
|
104
|
+
the `co2ToAirSoilOrganicCarbonStockChangeManagementChange` output.
|
|
105
105
|
|
|
106
106
|
The `EmissionMethodTier` should be based on the weakest `MeasurementMethodClassification` between the current SOC and
|
|
107
107
|
previous SOC.
|