hestia-earth-models 0.59.6__py3-none-any.whl → 0.60.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/cache_sites.py +8 -8
- hestia_earth/models/cycle/siteDuration.py +1 -1
- hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +9 -6
- hestia_earth/models/faostat2018/product/price.py +14 -3
- hestia_earth/models/geospatialDatabase/utils.py +0 -1
- hestia_earth/models/ipcc2019/animal/__init__.py +0 -0
- hestia_earth/models/ipcc2019/animal/pastureGrass.py +298 -0
- hestia_earth/models/ipcc2019/co2ToAirLimeHydrolysis.py +1 -1
- hestia_earth/models/ipcc2019/{co2ToAirSoilCarbonStockChangeManagementChange.py → co2ToAirSoilOrganicCarbonStockChangeManagementChange.py} +2 -2
- hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +2 -7
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +7 -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 +14 -2
- hestia_earth/models/utils/completeness.py +17 -14
- hestia_earth/models/utils/feedipedia.py +23 -23
- hestia_earth/models/utils/property.py +4 -1
- hestia_earth/models/utils/site.py +7 -4
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.59.6.dist-info → hestia_earth_models-0.60.0.dist-info}/LICENSE +1 -1
- {hestia_earth_models-0.59.6.dist-info → hestia_earth_models-0.60.0.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.59.6.dist-info → hestia_earth_models-0.60.0.dist-info}/RECORD +49 -44
- 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/faostat2018/product/test_price.py +15 -3
- 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_organicCarbonPerHa.py +95 -40
- 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 +22 -7
- {hestia_earth_models-0.59.6.dist-info → hestia_earth_models-0.60.0.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.59.6.dist-info → hestia_earth_models-0.60.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
from hestia_earth.schema import TermTermType, AnimalReferencePeriod
|
|
2
|
+
from hestia_earth.utils.api import download_hestia
|
|
3
|
+
from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name, extract_grouped_data
|
|
4
|
+
from hestia_earth.utils.tools import list_sum, safe_parse_float
|
|
5
|
+
|
|
6
|
+
from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
|
|
7
|
+
from hestia_earth.models.utils.input import get_feed_inputs
|
|
8
|
+
from hestia_earth.models.utils.term import get_lookup_value
|
|
9
|
+
from hestia_earth.models.utils.property import get_node_property, get_node_property_value, node_property_lookup_value
|
|
10
|
+
from .utils import get_milkYield_practice
|
|
11
|
+
from . import MODEL
|
|
12
|
+
|
|
13
|
+
MODEL_KEY = 'pastureGrass'
|
|
14
|
+
KEY_TERM_TYPES = [
|
|
15
|
+
TermTermType.LANDCOVER.value
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def practice_input_id(practice: dict):
|
|
20
|
+
return get_lookup_value(practice.get('key', {}), 'grazedPastureGrassInputId', model=MODEL, model_key=MODEL_KEY)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _get_grouping(animal: dict) -> str:
|
|
24
|
+
term = animal.get('term', {})
|
|
25
|
+
return get_lookup_value(term, 'ipcc2019AnimalTypeGrouping', model=MODEL, model_key=MODEL_KEY)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _get_activityCoefficient(cycle: dict, animal: dict, system: dict) -> float:
|
|
29
|
+
term = animal.get('term', {})
|
|
30
|
+
term_id = term.get('@id')
|
|
31
|
+
system_id = system.get('term', {}).get('@id')
|
|
32
|
+
lookup = download_lookup('system-liveAnimal-activityCoefficient-ipcc2019.csv')
|
|
33
|
+
activityCoefficient = safe_parse_float(get_table_value(lookup, 'termid', system_id, column_name(term_id)), 0)
|
|
34
|
+
|
|
35
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
36
|
+
activityCoefficient=activityCoefficient)
|
|
37
|
+
|
|
38
|
+
return activityCoefficient
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _calculate_NEm(cycle: dict, animal: dict) -> float:
|
|
42
|
+
term = animal.get('term', {})
|
|
43
|
+
term_id = term.get('@id')
|
|
44
|
+
|
|
45
|
+
mjDayKgCfiNetEnergyMaintenance = safe_parse_float(
|
|
46
|
+
get_lookup_value(term, 'mjDayKgCfiNetEnergyMaintenanceIpcc2019', model=MODEL, model_key=MODEL_KEY), 0
|
|
47
|
+
)
|
|
48
|
+
liveweightPerHead = get_node_property(animal, 'liveweightPerHead', False).get('value', 0)
|
|
49
|
+
animal_value = animal.get('value', 0)
|
|
50
|
+
cycleDuration = cycle.get('cycleDuration', 365)
|
|
51
|
+
NEm = mjDayKgCfiNetEnergyMaintenance * pow(liveweightPerHead, 0.75) * animal_value * cycleDuration
|
|
52
|
+
|
|
53
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
54
|
+
mjDayKgCfiNetEnergyMaintenance=mjDayKgCfiNetEnergyMaintenance,
|
|
55
|
+
liveweightPerHead=liveweightPerHead,
|
|
56
|
+
NEm=NEm)
|
|
57
|
+
|
|
58
|
+
return NEm
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _calculate_NEa_cattleAndBuffalo(cycle: dict, animal: dict, system: dict, NEm: float) -> float:
|
|
62
|
+
term = animal.get('term', {})
|
|
63
|
+
term_id = term.get('@id')
|
|
64
|
+
|
|
65
|
+
activityCoefficient = _get_activityCoefficient(cycle, animal, system)
|
|
66
|
+
|
|
67
|
+
NEa = activityCoefficient * NEm
|
|
68
|
+
|
|
69
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
70
|
+
NEa=NEa)
|
|
71
|
+
|
|
72
|
+
return NEa
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _calculate_NEa_sheepAndGoat(cycle: dict, animal: dict, system: dict, _NEm: float) -> float:
|
|
76
|
+
term = animal.get('term', {})
|
|
77
|
+
term_id = term.get('@id')
|
|
78
|
+
|
|
79
|
+
activityCoefficient = _get_activityCoefficient(cycle, animal, system)
|
|
80
|
+
|
|
81
|
+
liveweightPerHead = get_node_property(animal, 'liveweightPerHead', False).get('value', 0)
|
|
82
|
+
animal_value = animal.get('value', 0)
|
|
83
|
+
cycleDuration = cycle.get('cycleDuration', 365)
|
|
84
|
+
NEa = activityCoefficient * liveweightPerHead * animal_value * cycleDuration
|
|
85
|
+
|
|
86
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
87
|
+
liveweightPerHead=liveweightPerHead,
|
|
88
|
+
NEa=NEa)
|
|
89
|
+
|
|
90
|
+
return NEa
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
_NEa_BY_GROUPING = {
|
|
94
|
+
'cattleAndBuffalo': _calculate_NEa_cattleAndBuffalo,
|
|
95
|
+
'sheepAndGoat': _calculate_NEa_sheepAndGoat
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _calculate_NEa(cycle: dict, animal: dict, system: dict, NEm: float) -> float:
|
|
100
|
+
grouping = _get_grouping(animal)
|
|
101
|
+
return _NEa_BY_GROUPING.get(grouping, lambda *args: None)(cycle, animal, system, NEm)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _calculate_NEl_cattleAndBuffalo(cycle: dict, animal: dict) -> float:
|
|
105
|
+
term = animal.get('term', {})
|
|
106
|
+
term_id = term.get('@id')
|
|
107
|
+
|
|
108
|
+
milkYieldPractice = get_milkYield_practice(animal)
|
|
109
|
+
milkYield = list_sum(milkYieldPractice.get('value', []))
|
|
110
|
+
fatContent = get_node_property(milkYieldPractice, 'fatContent').get('value', 0)
|
|
111
|
+
animal_value = animal.get('value', 0)
|
|
112
|
+
cycleDuration = cycle.get('cycleDuration', 365)
|
|
113
|
+
NEl = milkYield * (1.47 + (0.4 * fatContent)) * animal_value * cycleDuration
|
|
114
|
+
|
|
115
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
116
|
+
milkYield=milkYield,
|
|
117
|
+
fatContent=fatContent,
|
|
118
|
+
NEl=NEl)
|
|
119
|
+
|
|
120
|
+
return NEl
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _calculate_NEl_sheepAndGoat(cycle: dict, animal: dict) -> float:
|
|
124
|
+
term = animal.get('term', {})
|
|
125
|
+
term_id = term.get('@id')
|
|
126
|
+
|
|
127
|
+
milkYieldPractice = get_milkYield_practice(animal)
|
|
128
|
+
milkYield = list_sum(milkYieldPractice.get('value', []))
|
|
129
|
+
EV_milk = safe_parse_float(
|
|
130
|
+
get_lookup_value(milkYieldPractice.get('term', {}), 'mjKgEvMilkIpcc2019', model=MODEL, model_key=MODEL_KEY),
|
|
131
|
+
0
|
|
132
|
+
)
|
|
133
|
+
default_fatContent = safe_parse_float(
|
|
134
|
+
get_lookup_value(milkYieldPractice.get('term', {}),
|
|
135
|
+
'defaultFatContentEvMilkIpcc2019', model=MODEL, model_key=MODEL_KEY),
|
|
136
|
+
7
|
|
137
|
+
)
|
|
138
|
+
fatContent = get_node_property(milkYieldPractice, 'fatContent').get('value', 0)
|
|
139
|
+
animal_value = animal.get('value', 0)
|
|
140
|
+
cycleDuration = cycle.get('cycleDuration', 365)
|
|
141
|
+
NEl = milkYield * (EV_milk * fatContent/default_fatContent) * animal_value * cycleDuration
|
|
142
|
+
|
|
143
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
144
|
+
milkYield=milkYield,
|
|
145
|
+
EV_milk=EV_milk,
|
|
146
|
+
NEl=NEl)
|
|
147
|
+
|
|
148
|
+
return NEl
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
_NEl_BY_GROUPING = {
|
|
152
|
+
'cattleAndBuffalo': _calculate_NEl_cattleAndBuffalo,
|
|
153
|
+
'sheepAndGoat': _calculate_NEl_sheepAndGoat
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _calculate_NEl(cycle: dict, animal: dict) -> float:
|
|
158
|
+
grouping = _get_grouping(animal)
|
|
159
|
+
return _NEl_BY_GROUPING.get(grouping, lambda *args: None)(cycle, animal)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _calculate_NEwork(cycle: dict, animal: dict, NEm: float) -> float:
|
|
163
|
+
term = animal.get('term', {})
|
|
164
|
+
term_id = term.get('@id')
|
|
165
|
+
|
|
166
|
+
hoursWorkedPerDay = get_node_property(animal, 'hoursWorkedPerDay').get('value', 0)
|
|
167
|
+
NEwork = 0.1 * NEm * hoursWorkedPerDay
|
|
168
|
+
|
|
169
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
170
|
+
hoursWorkedPerDay=hoursWorkedPerDay,
|
|
171
|
+
NEwork=NEwork)
|
|
172
|
+
|
|
173
|
+
return NEwork
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _get_pregnancy_ratio_per_birth(animal: dict, value: str) -> float:
|
|
177
|
+
animalsPerBirth = get_node_property(animal, 'animalsPerBirth').get('value', 3)
|
|
178
|
+
single = safe_parse_float(extract_grouped_data(value, 'singleBirth'), 0)
|
|
179
|
+
double = safe_parse_float(extract_grouped_data(value, 'doubleBirth'), 0)
|
|
180
|
+
tripple = safe_parse_float(extract_grouped_data(value, 'tripleBirthOrMore'))
|
|
181
|
+
return (
|
|
182
|
+
single if animalsPerBirth <= 1 else
|
|
183
|
+
((animalsPerBirth-1)/2)*single * (1-((animalsPerBirth-1)/2)*double) if 1 < animalsPerBirth < 2 else
|
|
184
|
+
double if animalsPerBirth == 2 else
|
|
185
|
+
((animalsPerBirth-2)/3)*double * (1-((animalsPerBirth-2)/3)*tripple) if 2 < animalsPerBirth < 3 else
|
|
186
|
+
tripple
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _get_pregnancy_ratio(animal: dict) -> float:
|
|
191
|
+
term = animal.get('term', {})
|
|
192
|
+
value = get_lookup_value(term, 'ratioCPregnancyNetEnergyPregnancyIpcc2019', model=MODEL, model_key=MODEL_KEY)
|
|
193
|
+
return _get_pregnancy_ratio_per_birth(animal, value) if ';' in value else safe_parse_float(value, 0)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _calculate_NEp(cycle: dict, animal: dict, NEm: float) -> float:
|
|
197
|
+
term = animal.get('term', {})
|
|
198
|
+
term_id = term.get('@id')
|
|
199
|
+
|
|
200
|
+
ratioCPregnancyNetEnergyPregnancy = _get_pregnancy_ratio(animal)
|
|
201
|
+
pregnancyRateTotal = get_node_property(animal, 'pregnancyRateTotal').get('value', 0)
|
|
202
|
+
NEp = ratioCPregnancyNetEnergyPregnancy * pregnancyRateTotal/100 * NEm
|
|
203
|
+
|
|
204
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
205
|
+
ratioCPregnancyNetEnergyPregnancy=ratioCPregnancyNetEnergyPregnancy,
|
|
206
|
+
pregnancyRateTotal=pregnancyRateTotal,
|
|
207
|
+
NEp=NEp)
|
|
208
|
+
|
|
209
|
+
return NEp
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _calculate_NEg_cattleAndBuffalo(cycle: dict, animal: dict) -> float:
|
|
213
|
+
term = animal.get('term', {})
|
|
214
|
+
term_id = term.get('@id')
|
|
215
|
+
|
|
216
|
+
ratioCNetEnergyGrowthCattleBuffalo = safe_parse_float(
|
|
217
|
+
get_lookup_value(term, 'ratioCNetEnergyGrowthCattleBuffaloIpcc2019', model=MODEL, model_key=MODEL_KEY), 0
|
|
218
|
+
)
|
|
219
|
+
liveweightPerHead = get_node_property(animal, 'liveweightPerHead').get('value', 0)
|
|
220
|
+
weightAtMaturity = get_node_property(animal, 'weightAtMaturity').get('value', 0)
|
|
221
|
+
liveweightGain = get_node_property(animal, 'liveweightGain').get('value', 0)
|
|
222
|
+
animal_value = animal.get('value', 0)
|
|
223
|
+
cycleDuration = cycle.get('cycleDuration', 365)
|
|
224
|
+
NEg = 22.02 * \
|
|
225
|
+
pow(liveweightPerHead / (ratioCNetEnergyGrowthCattleBuffalo * weightAtMaturity), 0.75) * \
|
|
226
|
+
pow(liveweightGain, 1.097) * \
|
|
227
|
+
animal_value * cycleDuration if all([
|
|
228
|
+
ratioCNetEnergyGrowthCattleBuffalo * weightAtMaturity > 0
|
|
229
|
+
]) else 0
|
|
230
|
+
|
|
231
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
232
|
+
ratioCNetEnergyGrowthCattleBuffalo=ratioCNetEnergyGrowthCattleBuffalo,
|
|
233
|
+
liveweightPerHead=liveweightPerHead,
|
|
234
|
+
weightAtMaturity=weightAtMaturity,
|
|
235
|
+
liveweightGain=liveweightGain,
|
|
236
|
+
NEg=NEg)
|
|
237
|
+
|
|
238
|
+
return NEg
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _calculate_NEg_sheepAndGoat(cycle: dict, animal: dict) -> float:
|
|
242
|
+
term = animal.get('term', {})
|
|
243
|
+
term_id = term.get('@id')
|
|
244
|
+
|
|
245
|
+
MjKgABNetEnergyGrowthSheepGoats = get_lookup_value(
|
|
246
|
+
term, 'MjKgABNetEnergyGrowthSheepGoatsIpcc2019', model=MODEL, model_key=MODEL_KEY)
|
|
247
|
+
MjKg_a = safe_parse_float(extract_grouped_data(MjKgABNetEnergyGrowthSheepGoats, 'a'), 0)
|
|
248
|
+
MjKg_b = safe_parse_float(extract_grouped_data(MjKgABNetEnergyGrowthSheepGoats, 'b'), 0)
|
|
249
|
+
BWi = get_node_property(animal, 'weightAtWeaning').get('value', 0)
|
|
250
|
+
BWf = get_node_property(animal, 'weightAtOneYear').get('value', 0) or \
|
|
251
|
+
get_node_property(animal, 'weightAtSlaughter').get('value', 0)
|
|
252
|
+
animal_value = animal.get('value', 0)
|
|
253
|
+
cycleDuration = cycle.get('cycleDuration', 365)
|
|
254
|
+
NEg = (BWf - BWi) * (MjKg_a + 0.5 * MjKg_b * (BWi + BWf)) / 365 * animal_value * cycleDuration
|
|
255
|
+
|
|
256
|
+
debugValues(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
257
|
+
MjKg_a=MjKg_a,
|
|
258
|
+
MjKg_b=MjKg_b,
|
|
259
|
+
BWi=BWi,
|
|
260
|
+
BWf=BWf,
|
|
261
|
+
NEg=NEg)
|
|
262
|
+
|
|
263
|
+
return NEg
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
_NEg_BY_GROUPING = {
|
|
267
|
+
'cattleAndBuffalo': _calculate_NEg_cattleAndBuffalo,
|
|
268
|
+
'sheepAndGoat': _calculate_NEg_sheepAndGoat
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _calculate_NEg(cycle: dict, animal: dict) -> float:
|
|
273
|
+
grouping = _get_grouping(animal)
|
|
274
|
+
return _NEg_BY_GROUPING.get(grouping, lambda *args: None)(cycle, animal)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _pastureGrass_key_property_value(practice: dict, column: dict):
|
|
278
|
+
term_id = practice_input_id(practice)
|
|
279
|
+
term = download_hestia(term_id)
|
|
280
|
+
term_type = term.get('termType')
|
|
281
|
+
value = list_sum(practice.get('value', [0]))
|
|
282
|
+
lookup_value = node_property_lookup_value(MODEL, {'@id': term_id, 'termType': term_type}, column, default=0)
|
|
283
|
+
return (lookup_value, value)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def calculate_REM(energy: float = 0) -> float:
|
|
287
|
+
return 1.123 - (4.092/1000 * energy) + (1.126/100000 * pow(energy, 2)) - (25.4/energy) if energy > 0 else 0
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def calculate_REG(energy: float = 0) -> float:
|
|
291
|
+
return 1.164 - (5.16/1000 * energy) + (1.308/100000 * pow(energy, 2)) - (37.4/energy) if energy > 0 else 0
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _calculate_feed_meanDE(node: dict, input: dict) -> float:
|
|
295
|
+
term_id = input.get('term', {}).get('@id')
|
|
296
|
+
|
|
297
|
+
energyContent = get_node_property_value(MODEL, input, 'energyContentHigherHeatingValue')
|
|
298
|
+
energyDigestibility = get_node_property_value(MODEL, input, 'energyDigestibilityRuminants')
|
|
299
|
+
meanDE = energyContent * energyDigestibility if all([energyContent, energyDigestibility]) else 0
|
|
300
|
+
|
|
301
|
+
debugValues(node, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
302
|
+
energyContent=energyContent,
|
|
303
|
+
energyDigestibility=energyDigestibility,
|
|
304
|
+
meanDE=meanDE)
|
|
305
|
+
|
|
306
|
+
return meanDE
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _calculate_NEfeed_m(node: dict, input: dict, meanDE: float) -> float:
|
|
310
|
+
term_id = input.get('term', {}).get('@id')
|
|
311
|
+
|
|
312
|
+
energyDigestibility = get_node_property_value(MODEL, input, 'energyDigestibilityRuminants', default=0)
|
|
313
|
+
REm = calculate_REM(energyDigestibility * 100)
|
|
314
|
+
|
|
315
|
+
debugValues(node, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
316
|
+
REm=REm)
|
|
317
|
+
|
|
318
|
+
input_value = list_sum(input.get('value'))
|
|
319
|
+
return meanDE * REm * input_value
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _calculate_NEfeed_g(node: dict, input: dict, meanDE: float) -> float:
|
|
323
|
+
term_id = input.get('term', {}).get('@id')
|
|
324
|
+
|
|
325
|
+
energyDigestibility = get_node_property_value(MODEL, input, 'energyDigestibilityRuminants', default=0)
|
|
326
|
+
REg = calculate_REG(energyDigestibility * 100)
|
|
327
|
+
|
|
328
|
+
debugValues(node, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
329
|
+
REg=REg)
|
|
330
|
+
|
|
331
|
+
input_value = list_sum(input.get('value'))
|
|
332
|
+
return meanDE * REg * input_value
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def calculate_NEfeed(node: dict) -> tuple:
|
|
336
|
+
inputs = get_feed_inputs(node)
|
|
337
|
+
# calculate meanDE for each input first
|
|
338
|
+
inputs = [(input, _calculate_feed_meanDE(node, input)) for input in inputs]
|
|
339
|
+
NEfeed_m = sum([
|
|
340
|
+
_calculate_NEfeed_m(node, input, meanDE) for (input, meanDE) in inputs
|
|
341
|
+
]) if len(inputs) > 0 else 0
|
|
342
|
+
NEfeed_g = sum([
|
|
343
|
+
_calculate_NEfeed_g(node, input, meanDE) for (input, meanDE) in inputs
|
|
344
|
+
]) if len(inputs) > 0 else 0
|
|
345
|
+
|
|
346
|
+
return (NEfeed_m, NEfeed_g)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def get_animal_values(cycle: dict, animal: dict, system: dict):
|
|
350
|
+
term_id = animal.get('term', {}).get('@id')
|
|
351
|
+
|
|
352
|
+
NEm = _calculate_NEm(cycle, animal)
|
|
353
|
+
NEa = _calculate_NEa(cycle, animal, system, NEm)
|
|
354
|
+
NEl = _calculate_NEl(cycle, animal)
|
|
355
|
+
NEwork = _calculate_NEwork(cycle, animal, NEm)
|
|
356
|
+
NEp = _calculate_NEp(cycle, animal, NEm)
|
|
357
|
+
NEg = _calculate_NEg(cycle, animal)
|
|
358
|
+
|
|
359
|
+
logRequirements(cycle, model=MODEL, term=term_id, model_key=MODEL_KEY,
|
|
360
|
+
NEm=NEm,
|
|
361
|
+
NEa=NEa,
|
|
362
|
+
NEl=NEl,
|
|
363
|
+
NEwork=NEwork,
|
|
364
|
+
NEp=NEp,
|
|
365
|
+
NEg=NEg)
|
|
366
|
+
|
|
367
|
+
return (NEm, NEa, NEl, NEwork, NEp, NEg)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def calculate_meanECHHV(practices: list) -> float:
|
|
371
|
+
values = list(map(lambda p: _pastureGrass_key_property_value(p, 'energyContentHigherHeatingValue'), practices))
|
|
372
|
+
total_weight = sum([weight/100 for _value, weight in values])
|
|
373
|
+
return sum([
|
|
374
|
+
(value * weight/100 if all([value, weight]) else 0) for value, weight in values
|
|
375
|
+
]) / total_weight if total_weight > 0 else 0
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def calculate_meanDE(practices: list) -> float:
|
|
379
|
+
values = list(map(lambda p: _pastureGrass_key_property_value(p, 'energyDigestibilityRuminants'), practices))
|
|
380
|
+
total_weight = sum([weight/100 for _value, weight in values])
|
|
381
|
+
meanDE = sum([
|
|
382
|
+
(value * weight/100 if all([value, weight]) else 0) for value, weight in values
|
|
383
|
+
]) / total_weight if total_weight > 0 else 0
|
|
384
|
+
|
|
385
|
+
return meanDE
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def product_wool_energy(product: dict):
|
|
389
|
+
return safe_parse_float(get_lookup_value(product.get('term', {}), 'mjKgEvWoolNetEnergyWoolIpcc2019'), 24)
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def should_run_practice(cycle: dict):
|
|
393
|
+
def should_run(practice: dict):
|
|
394
|
+
term_id = practice.get('term', {}).get('@id')
|
|
395
|
+
key_term_type = practice.get('key', {}).get('termType')
|
|
396
|
+
value = practice.get('value', [])
|
|
397
|
+
|
|
398
|
+
logRequirements(cycle, model=MODEL, term=term_id,
|
|
399
|
+
practice_value=list_sum(value),
|
|
400
|
+
practice_key_term_type=key_term_type)
|
|
401
|
+
|
|
402
|
+
should_run = all([len(value) > 0, term_id == MODEL_KEY, key_term_type in KEY_TERM_TYPES])
|
|
403
|
+
logShouldRun(cycle, MODEL, term_id, should_run)
|
|
404
|
+
return should_run
|
|
405
|
+
|
|
406
|
+
return should_run
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def get_animals(cycle: dict):
|
|
410
|
+
return [
|
|
411
|
+
a for a in cycle.get('animals', []) if all([
|
|
412
|
+
a.get('value'),
|
|
413
|
+
a.get('referencePeriod') == AnimalReferencePeriod.AVERAGE.value
|
|
414
|
+
])
|
|
415
|
+
]
|