hestia-earth-models 0.64.7__py3-none-any.whl → 0.64.9__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.

Files changed (58) hide show
  1. hestia_earth/models/cycle/animal/milkYield.py +10 -22
  2. hestia_earth/models/cycle/siteArea.py +2 -1
  3. hestia_earth/models/cycle/unknownPreSeasonWaterRegime.py +0 -1
  4. hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandOccupation.py +73 -82
  5. hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandTransformation.py +168 -0
  6. hestia_earth/models/environmentalFootprintV3/soilQualityIndexTotalLandUseEffects.py +77 -0
  7. hestia_earth/models/environmentalFootprintV3/utils.py +1 -1
  8. hestia_earth/models/faostat2018/landTransformationFromCropland100YearAverage.py +3 -2
  9. hestia_earth/models/faostat2018/landTransformationFromCropland20YearAverage.py +3 -2
  10. hestia_earth/models/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +69 -37
  11. hestia_earth/models/hyde32/utils.py +4 -0
  12. hestia_earth/models/ipcc2019/animal/fatContent.py +38 -0
  13. hestia_earth/models/ipcc2019/animal/liveweightGain.py +3 -54
  14. hestia_earth/models/ipcc2019/animal/liveweightPerHead.py +3 -54
  15. hestia_earth/models/ipcc2019/animal/pastureGrass.py +3 -1
  16. hestia_earth/models/ipcc2019/animal/pregnancyRateTotal.py +38 -0
  17. hestia_earth/models/ipcc2019/animal/trueProteinContent.py +38 -0
  18. hestia_earth/models/ipcc2019/animal/utils.py +87 -3
  19. hestia_earth/models/ipcc2019/animal/weightAtMaturity.py +4 -10
  20. hestia_earth/models/ipcc2019/co2ToAirAboveGroundBiomassStockChangeLandUseChange.py +191 -0
  21. hestia_earth/models/ipcc2019/co2ToAirBelowGroundBiomassStockChangeLandUseChange.py +204 -0
  22. hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +255 -35
  23. hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +63 -149
  24. hestia_earth/models/ipcc2019/pastureGrass.py +3 -1
  25. hestia_earth/models/mocking/search-results.json +2026 -26
  26. hestia_earth/models/pooreNemecek2018/landOccupationDuringCycle.py +1 -1
  27. hestia_earth/models/poschEtAl2008/terrestrialAcidificationPotentialAccumulatedExceedance.py +4 -1
  28. hestia_earth/models/poschEtAl2008/terrestrialEutrophicationPotentialAccumulatedExceedance.py +4 -1
  29. hestia_earth/models/site/management.py +3 -5
  30. hestia_earth/models/utils/__init__.py +5 -4
  31. hestia_earth/models/utils/impact_assessment.py +13 -4
  32. hestia_earth/models/utils/input.py +5 -2
  33. hestia_earth/models/utils/site.py +4 -2
  34. hestia_earth/models/version.py +1 -1
  35. {hestia_earth_models-0.64.7.dist-info → hestia_earth_models-0.64.9.dist-info}/METADATA +2 -2
  36. {hestia_earth_models-0.64.7.dist-info → hestia_earth_models-0.64.9.dist-info}/RECORD +58 -44
  37. tests/models/cycle/animal/test_milkYield.py +1 -14
  38. tests/models/environmentalFootprintV3/test_soilQualityIndexLandOccupation.py +97 -66
  39. tests/models/environmentalFootprintV3/test_soilQualityIndexLandTransformation.py +176 -0
  40. tests/models/environmentalFootprintV3/test_soilQualityIndexTotalLandUseEffects.py +55 -0
  41. tests/models/frischknechtEtAl2000/test_ionisingRadiationKbqU235Eq.py +67 -44
  42. tests/models/ipcc2019/animal/test_fatContent.py +22 -0
  43. tests/models/ipcc2019/animal/test_liveweightGain.py +4 -2
  44. tests/models/ipcc2019/animal/test_liveweightPerHead.py +4 -2
  45. tests/models/ipcc2019/animal/test_pregnancyRateTotal.py +22 -0
  46. tests/models/ipcc2019/animal/test_trueProteinContent.py +22 -0
  47. tests/models/ipcc2019/animal/test_weightAtMaturity.py +2 -1
  48. tests/models/ipcc2019/test_co2ToAirAboveGroundBiomassStockChangeLandUseChange.py +83 -0
  49. tests/models/ipcc2019/test_co2ToAirBelowGroundBiomassStockChangeLandUseChange.py +83 -0
  50. tests/models/ipcc2019/test_co2ToAirCarbonStockChange_utils.py +6 -6
  51. tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +5 -4
  52. tests/models/poschEtAl2008/test_terrestrialAcidificationPotentialAccumulatedExceedance.py +30 -17
  53. tests/models/poschEtAl2008/test_terrestrialEutrophicationPotentialAccumulatedExceedance.py +28 -14
  54. tests/models/site/test_management.py +4 -1
  55. tests/models/utils/test_input.py +65 -1
  56. {hestia_earth_models-0.64.7.dist-info → hestia_earth_models-0.64.9.dist-info}/LICENSE +0 -0
  57. {hestia_earth_models-0.64.7.dist-info → hestia_earth_models-0.64.9.dist-info}/WHEEL +0 -0
  58. {hestia_earth_models-0.64.7.dist-info → hestia_earth_models-0.64.9.dist-info}/top_level.txt +0 -0
@@ -1,23 +1,10 @@
1
- from functools import reduce
2
- from numpy import random
3
-
4
- from hestia_earth.schema import (
5
- CycleFunctionalUnit, EmissionMethodTier, EmissionStatsDefinition, MeasurementMethodClassification, SiteSiteType
6
- )
1
+ from hestia_earth.schema import CycleFunctionalUnit, EmissionMethodTier, SiteSiteType
7
2
 
8
3
  from hestia_earth.models.log import logRequirements, logShouldRun
9
- from hestia_earth.models.utils.array_builders import gen_seed
10
- from hestia_earth.models.utils.blank_node import (
11
- _get_datestr_format, cumulative_nodes_term_match, DatestrFormat, node_term_match
12
- )
13
- from hestia_earth.models.utils.descriptive_stats import calc_descriptive_stats
4
+ from hestia_earth.models.utils.blank_node import cumulative_nodes_term_match
14
5
  from hestia_earth.models.utils.emission import _new_emission
15
- from hestia_earth.models.utils.site import related_cycles
16
6
 
17
- from .co2ToAirCarbonStockChange_utils import (
18
- _InventoryKey, add_carbon_stock_change_emissions, compile_inventory, rescale_carbon_stock_change_emission
19
- )
20
- from .utils import check_consecutive
7
+ from .co2ToAirCarbonStockChange_utils import create_run_function, create_should_run_function
21
8
  from . import MODEL
22
9
 
23
10
  REQUIREMENTS = {
@@ -44,6 +31,11 @@ REQUIREMENTS = {
44
31
  RETURNS = {
45
32
  "Emission": [{
46
33
  "value": "",
34
+ "sd": "",
35
+ "min": "",
36
+ "max": "",
37
+ "statsDefinition": "simulated",
38
+ "observations": "",
47
39
  "methodTier": "",
48
40
  "depth": "30"
49
41
  }]
@@ -52,28 +44,8 @@ TERM_ID = 'co2ToAirSoilOrganicCarbonStockChangeManagementChange'
52
44
 
53
45
  _DEPTH_UPPER = 0
54
46
  _DEPTH_LOWER = 30
55
- _ITERATIONS = 10000
56
-
57
- _ORGANIC_CARBON_PER_HA_TERM_ID = 'organicCarbonPerHa'
58
-
59
- _VALID_DATE_FORMATS = {
60
- DatestrFormat.YEAR,
61
- DatestrFormat.YEAR_MONTH,
62
- DatestrFormat.YEAR_MONTH_DAY,
63
- DatestrFormat.YEAR_MONTH_DAY_HOUR_MINUTE_SECOND
64
- }
65
47
 
66
- _VALID_MEASUREMENT_METHOD_CLASSIFICATIONS = [
67
- MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT,
68
- MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS,
69
- MeasurementMethodClassification.TIER_3_MODEL,
70
- MeasurementMethodClassification.TIER_2_MODEL,
71
- MeasurementMethodClassification.TIER_1_MODEL
72
- ]
73
- """
74
- The list of `MeasurementMethodClassification`s that can be used to calculate SOC stock change emissions, ranked in
75
- order from strongest to weakest.
76
- """
48
+ _CARBON_STOCK_TERM_ID = 'organicCarbonPerHa'
77
49
 
78
50
  _SITE_TYPE_SYSTEMS_MAPPING = {
79
51
  SiteSiteType.GLASS_OR_HIGH_ACCESSIBLE_COVER.value: [
@@ -128,98 +100,37 @@ def _emission(
128
100
  return emission
129
101
 
130
102
 
131
- def _should_run(cycle: dict) -> tuple[bool, str, dict]:
103
+ def run(cycle: dict) -> list[dict]:
132
104
  """
133
- Determine if calculations should run for a given [Cycle](https://www.hestia.earth/schema/Cycle) based on SOC stock
134
- and emissions data.
105
+ Run the `ipcc2019.co2ToAirSoilOrganicCarbonStockChangeManagementChange`.
135
106
 
136
107
  Parameters
137
108
  ----------
138
109
  cycle : dict
139
- The cycle dictionary for which the calculations will be evaluated.
110
+ A HESTIA (Cycle node)[https://www.hestia.earth/schema/Cycle].
140
111
 
141
112
  Returns
142
113
  -------
143
- tuple[bool, str, dict]
144
- `(should_run, cycle_id, inventory)`
114
+ list[dict]
115
+ A list of [Emission nodes](https://www.hestia.earth/schema/Emission) containing model results.
145
116
  """
146
- cycle_id = cycle.get("@id")
147
- site = _get_site(cycle)
148
- soc_measurements = [node for node in site.get("measurements", []) if _validate_soc_measurement(node)]
149
- cycles = related_cycles(site)
150
-
151
- seed = gen_seed(site) # All cycles linked to the same site should be consistent
152
- rng = random.default_rng(seed)
153
-
154
- site_type = site.get("siteType")
155
- has_soil = site_type not in _SITE_TYPE_SYSTEMS_MAPPING or all(
156
- cumulative_nodes_term_match(
157
- cycle.get("practices", []),
158
- target_term_ids=_SITE_TYPE_SYSTEMS_MAPPING[site_type],
159
- cumulative_threshold=0
160
- ) for cycle in cycles
161
- )
162
-
163
- has_soc_measurements = len(soc_measurements) > 0
164
- has_cycles = len(cycles) > 0
165
- has_functional_unit_1_ha = all(cycle.get('functionalUnit') == CycleFunctionalUnit._1_HA.value for cycle in cycles)
166
-
167
- should_compile_inventory = all([
168
- has_soil,
169
- has_cycles,
170
- has_functional_unit_1_ha,
171
- has_soc_measurements,
172
- ])
173
-
174
- inventory, logs = (
175
- compile_inventory(
176
- cycle_id,
177
- cycles,
178
- soc_measurements,
179
- iterations=_ITERATIONS,
180
- seed=rng
181
- ) if should_compile_inventory else ({}, {})
117
+ should_run_exec = create_should_run_function(
118
+ _CARBON_STOCK_TERM_ID,
119
+ _should_compile_inventory_func,
120
+ should_run_measurement_func=_should_run_measurement_func
182
121
  )
183
122
 
184
- has_valid_inventory = len(inventory) > 0
185
- has_consecutive_years = check_consecutive(inventory.keys())
123
+ run_exec = create_run_function(_emission)
186
124
 
187
- logRequirements(
188
- cycle, model=MODEL, term=TERM_ID,
189
- site_type=site_type,
190
- seed=seed,
191
- has_soil=has_soil,
192
- has_soc_measurements=has_soc_measurements,
193
- has_cycles=has_cycles,
194
- has_functional_unit_1_ha=has_functional_unit_1_ha,
195
- has_valid_inventory=has_valid_inventory,
196
- has_consecutive_years=has_consecutive_years,
197
- **logs
198
- )
199
-
200
- should_run = all([has_valid_inventory, has_consecutive_years])
125
+ should_run, cycle_id, inventory, logs = should_run_exec(cycle)
201
126
 
127
+ logRequirements(cycle, model=MODEL, term=TERM_ID, **logs)
202
128
  logShouldRun(cycle, MODEL, TERM_ID, should_run)
203
129
 
204
- return should_run, cycle_id, inventory
205
-
206
-
207
- def _get_site(cycle: dict) -> dict:
208
- """
209
- Get the [Site](https://www.hestia.earth/schema/Site) data from a [Cycle](https://www.hestia.earth/schema/Cycle).
210
-
211
- Parameters
212
- ----------
213
- cycle : dict
214
-
215
- Returns
216
- -------
217
- str
218
- """
219
- return cycle.get("site", {})
130
+ return run_exec(cycle_id, inventory) if should_run else []
220
131
 
221
132
 
222
- def _validate_soc_measurement(node: dict) -> bool:
133
+ def _should_run_measurement_func(node: dict) -> bool:
223
134
  """
224
135
  Validate a [Measurement](https://www.hestia.earth/schema/Measurement) to determine whether it is a valid
225
136
  `organicCarbonPerHa` node.
@@ -234,57 +145,60 @@ def _validate_soc_measurement(node: dict) -> bool:
234
145
  bool
235
146
  `True` if the node passes all validation criteria, `False` otherwise.
236
147
  """
237
- value = node.get("value", [])
238
- sd = node.get("sd", [])
239
- dates = node.get("dates", [])
240
148
  return all([
241
- node_term_match(node, _ORGANIC_CARBON_PER_HA_TERM_ID),
242
- node.get("depthUpper") == _DEPTH_UPPER,
243
149
  node.get("depthLower") == _DEPTH_LOWER,
244
- node.get("methodClassification") in (m.value for m in _VALID_MEASUREMENT_METHOD_CLASSIFICATIONS),
245
- len(value) > 0,
246
- len(value) == len(dates),
247
- len(sd) == 0 or len(sd) == len(value),
248
- all(_get_datestr_format(datestr) in _VALID_DATE_FORMATS for datestr in dates)
150
+ node.get("depthUpper") == _DEPTH_UPPER
249
151
  ])
250
152
 
251
153
 
252
- def _run(cycle_id: str, inventory: dict) -> list[dict]:
154
+ def _should_compile_inventory_func(
155
+ site: dict, cycles: list[dict], carbon_stock_measurements: list[dict]
156
+ ) -> tuple[bool, dict]:
253
157
  """
254
- Calculate emissions for a specific cycle using grouped SOC stock change and share of emissions data.
255
-
256
- The emission method tier based on the minimum measurement method tier among the SOC stock change data in the
257
- grouped data.
158
+ Determine whether a site is suitable and has enough data to compile a carbon stock inventory.
258
159
 
259
160
  Parameters
260
161
  ----------
261
- cycle_id : str
262
- The "@id" field of the [Cycle node](https://www.hestia.earth/schema/Cycle).
263
- grouped_data : dict
264
- A dictionary containing grouped SOC stock change and share of emissions data.
162
+ site : dict
163
+ A HESTIA (Site node)[https://www.hestia.earth/schema/Site]
164
+ cycles : list[dict]
165
+ A list of HESTIA (Cycle nodes)[https://www.hestia.earth/schema/Cycle] that are related to the site.
166
+ carbon_stock_measurements : list[dict]
167
+ A list of HESTIA carbon stock (Measurement nodes)[https://www.hestia.earth/schema/Measurement] that are related
168
+ to the site.
265
169
 
266
170
  Returns
267
171
  -------
268
- list[dict]
269
- A list containing emission data calculated for the specified cycle.
172
+ tuple[bool, dict]
173
+ `(should_run, logs)`.
270
174
  """
271
- rescaled_emissions = [
272
- rescale_carbon_stock_change_emission(
273
- group[_InventoryKey.CO2_EMISSION], group[_InventoryKey.SHARE_OF_EMISSION][cycle_id]
274
- ) for group in inventory.values()
275
- ]
276
- total_emission = reduce(add_carbon_stock_change_emissions, rescaled_emissions)
277
-
278
- descriptive_stats = calc_descriptive_stats(
279
- total_emission.value,
280
- EmissionStatsDefinition.SIMULATED,
281
- decimals=6
175
+ site_type = site.get("siteType")
176
+ has_soil = site_type not in _SITE_TYPE_SYSTEMS_MAPPING or all(
177
+ cumulative_nodes_term_match(
178
+ cycle.get("practices", []),
179
+ target_term_ids=_SITE_TYPE_SYSTEMS_MAPPING[site_type],
180
+ cumulative_threshold=0
181
+ ) for cycle in cycles
282
182
  )
283
183
 
284
- method_tier = total_emission.method
285
- return [_emission(method_tier=method_tier, **descriptive_stats)]
184
+ has_stock_measurements = len(carbon_stock_measurements) > 0
185
+ has_cycles = len(cycles) > 0
186
+ has_functional_unit_1_ha = all(cycle.get('functionalUnit') == CycleFunctionalUnit._1_HA.value for cycle in cycles)
187
+
188
+ should_run = all([
189
+ has_soil,
190
+ has_stock_measurements,
191
+ has_cycles,
192
+ has_functional_unit_1_ha
193
+ ])
286
194
 
195
+ logs = {
196
+ "site_type": site_type,
197
+ "has_soil": has_soil,
198
+ "carbon_stock_term": _CARBON_STOCK_TERM_ID,
199
+ "has_stock_measurements": has_stock_measurements,
200
+ "has_cycles": has_cycles,
201
+ "has_functional_unit_1_ha": has_functional_unit_1_ha,
202
+ }
287
203
 
288
- def run(cycle: dict) -> list[dict]:
289
- should_run, *args = _should_run(cycle)
290
- return _run(*args) if should_run else []
204
+ return should_run, logs
@@ -141,10 +141,12 @@ LOOKUPS = {
141
141
  "isWoolProducingAnimal"
142
142
  ],
143
143
  "system-liveAnimal-activityCoefficient-ipcc2019": "using animal term @id",
144
+ "landCover": "grazedPastureGrassInputId",
144
145
  "crop-property": ["energyDigestibilityRuminants", "energyContentHigherHeatingValue"],
145
146
  "crop": "grazedPastureGrassInputId",
146
147
  "forage-property": ["energyDigestibilityRuminants", "energyContentHigherHeatingValue"],
147
- "landCover": "grazedPastureGrassInputId"
148
+ "feedFoodAdditive": "hasEnergyContent",
149
+ "feedFoodAdditive-property": ["energyDigestibilityRuminants", "energyContentHigherHeatingValue"]
148
150
  }
149
151
  RETURNS = {
150
152
  "Input": [{