hestia-earth-models 0.59.1__py3-none-any.whl → 0.59.2__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 (33) hide show
  1. hestia_earth/models/cycle/irrigatedTypeUnspecified.py +6 -7
  2. hestia_earth/models/impact_assessment/irrigated.py +4 -1
  3. hestia_earth/models/ipcc2006/n2OToAirCropResidueDecompositionIndirect.py +3 -3
  4. hestia_earth/models/ipcc2006/n2OToAirExcretaIndirect.py +3 -3
  5. hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py +5 -4
  6. hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserIndirect.py +5 -4
  7. hestia_earth/models/ipcc2006/utils.py +0 -16
  8. hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionDirect.py +8 -7
  9. hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionIndirect.py +100 -0
  10. hestia_earth/models/ipcc2019/n2OToAirExcretaIndirect.py +100 -0
  11. hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py +54 -61
  12. hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py +58 -66
  13. hestia_earth/models/ipcc2019/nh3ToAirOrganicFertiliser.py +104 -0
  14. hestia_earth/models/ipcc2019/noxToAirOrganicFertiliser.py +104 -0
  15. hestia_earth/models/ipcc2019/organicCarbonPerHa.py +56 -18
  16. hestia_earth/models/ipcc2019/utils.py +28 -16
  17. hestia_earth/models/site/soilMeasurement.py +197 -0
  18. hestia_earth/models/utils/cycle.py +7 -6
  19. hestia_earth/models/utils/emission.py +15 -0
  20. hestia_earth/models/version.py +1 -1
  21. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.2.dist-info}/METADATA +1 -1
  22. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.2.dist-info}/RECORD +33 -23
  23. tests/models/ipcc2019/test_n2OToAirCropResidueDecompositionIndirect.py +71 -0
  24. tests/models/ipcc2019/test_n2OToAirExcretaIndirect.py +71 -0
  25. tests/models/ipcc2019/test_n2OToAirInorganicFertiliserIndirect.py +36 -13
  26. tests/models/ipcc2019/test_n2OToAirOrganicFertiliserIndirect.py +36 -13
  27. tests/models/ipcc2019/test_nh3ToAirOrganicFertiliser.py +35 -0
  28. tests/models/ipcc2019/test_noxToAirOrganicFertiliser.py +35 -0
  29. tests/models/ipcc2019/test_organicCarbonPerHa.py +45 -4
  30. tests/models/site/test_soilMeasurement.py +159 -0
  31. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.2.dist-info}/LICENSE +0 -0
  32. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.2.dist-info}/WHEEL +0 -0
  33. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,197 @@
1
+ """
2
+ Soil Measurement
3
+
4
+ This model harmonises matching soil measurements into depth ranges of 0-30 and 0-50 and gap fills missing measurements.
5
+ """
6
+ from collections import defaultdict
7
+ from copy import deepcopy
8
+ from hestia_earth.schema import MeasurementMethodClassification
9
+ from hestia_earth.utils.tools import non_empty_list, flatten
10
+
11
+ from hestia_earth.models.log import logRequirements, logShouldRun, logErrorRun
12
+ from hestia_earth.models.utils.measurement import _new_measurement
13
+ from hestia_earth.models.utils.term import get_lookup_value
14
+ from . import MODEL
15
+
16
+ REQUIREMENTS = {
17
+ "Site": {
18
+ "measurements": [
19
+ {"@type": "Measurement", "depthUpper": "", "depthLower": ""}
20
+ ]
21
+ }
22
+ }
23
+
24
+ RETURNS = {
25
+ "Measurement": [{
26
+ "value": "",
27
+ "depthUpper": 0,
28
+ "depthLower": [30, 50],
29
+ "dates": "",
30
+ "methodClassification": "modelled using other measurements"
31
+ }]
32
+ }
33
+
34
+ LOOKUPS = {
35
+ "measurement": ["recommendAddingDepth", "depthSensitive"]
36
+ }
37
+
38
+ MODEL_KEY = 'soilMeasurement'
39
+ STANDARD_DEPTHS = {(0, 30), (0, 50)}
40
+
41
+
42
+ def _measurement(value: float, date: str, term_id: str, standard_fields: dict):
43
+ data = _new_measurement(term=term_id)
44
+ data["value"] = [value]
45
+ data["depthUpper"] = standard_fields["depthUpper"]
46
+ data["depthLower"] = standard_fields["depthLower"]
47
+ data["methodClassification"] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
48
+ if date and date[0]:
49
+ data["dates"] = [date]
50
+ return data
51
+
52
+
53
+ def _get_overlap(in_lower: int, in_upper: int, out_lower: int, out_upper: int):
54
+ """Returns the amount of overlap between upper-lower and range_upper-range_lower."""
55
+ if in_lower >= in_upper or out_lower >= out_upper or in_lower >= out_upper or in_upper <= out_lower:
56
+ return 0
57
+
58
+ overlap_range = [max(in_lower, out_lower), min(in_upper, out_upper)]
59
+ return max(overlap_range) - min(overlap_range)
60
+
61
+
62
+ def _harmonise_measurements(measurements_list: list, standard_depth_lower: int, standard_depth_upper: int) -> float:
63
+ """Gather measurements and calculate modelled value."""
64
+ total_weight_values = 0
65
+ total_weights = 0
66
+ for measurement_dict in measurements_list:
67
+ value = measurement_dict.get("value", [])[0]
68
+ depth_lower = measurement_dict.get("depthLower", 0)
69
+ depth_upper = measurement_dict.get("depthUpper", 0)
70
+ # Note that the upper/lower here is reversed as lower in the ground (greater depth),
71
+ # means higher numbers.
72
+ weight = _get_overlap(
73
+ in_lower=depth_upper,
74
+ in_upper=depth_lower,
75
+ out_lower=standard_depth_upper,
76
+ out_upper=standard_depth_lower
77
+ )
78
+ total_weights += weight
79
+ total_weight_values += value * weight
80
+ modelled_value = total_weight_values / total_weights if total_weights else 0
81
+ return modelled_value
82
+
83
+
84
+ def _expand_multiple_measurements(measurements):
85
+ """Split/expand measurements with arrays of values and dates into distinct measurements."""
86
+ expanded_measurements = []
87
+ for measurement in measurements:
88
+ if "dates" in measurement and len(measurement.get("value", [])) != len(measurement.get("dates", [])):
89
+ logErrorRun(
90
+ model=MODEL,
91
+ term=measurement.get("term", {}),
92
+ error="Inconsistent field lengths between values and dates fields in measurement."
93
+ )
94
+ elif len(measurement.get("value", [])) < 2:
95
+ expanded_measurements.append(measurement)
96
+ else:
97
+ for v, d in zip(measurement.get("value", []), measurement.get("dates", [])):
98
+ new_measurement = deepcopy(measurement)
99
+ new_measurement.update({"value": [v], "dates": [d]})
100
+ expanded_measurements.append(new_measurement)
101
+
102
+ return expanded_measurements
103
+
104
+
105
+ def _group_measurements_by_date_method_term(measurements):
106
+ group_by_result = defaultdict(list)
107
+ for measurement_dict in measurements:
108
+ dates = measurement_dict.get("dates", [])
109
+ method = measurement_dict.get("method", {}).get("@id", "")
110
+ term_id = measurement_dict.get("term", {}).get("@id", "")
111
+ if not dates:
112
+ dates = [measurement_dict.get('endDate', "")]
113
+ group_by_result[(dates[0], method, term_id)].append(measurement_dict)
114
+ return group_by_result
115
+
116
+
117
+ def _run_harmonisation(measurements: list, needed_depths: list):
118
+ results = []
119
+ grouped_measurements = _group_measurements_by_date_method_term(
120
+ _expand_multiple_measurements(measurements)
121
+ )
122
+
123
+ for (date, method, term_id), measurements_list in grouped_measurements.items():
124
+ # For a target depth
125
+ for depth_upper, depth_lower in needed_depths:
126
+ modelled_value = _harmonise_measurements(
127
+ measurements_list=measurements_list,
128
+ standard_depth_upper=depth_upper,
129
+ standard_depth_lower=depth_lower
130
+ )
131
+ if modelled_value:
132
+ results.append(
133
+ _measurement(
134
+ value=modelled_value,
135
+ date=date,
136
+ standard_fields={
137
+ "depthUpper": depth_upper,
138
+ "depthLower": depth_lower
139
+ },
140
+ term_id=term_id
141
+ )
142
+ )
143
+
144
+ return results
145
+
146
+
147
+ def _run_gap_fill_depths(measurements_missing_depths: list) -> list:
148
+ return [dict(m, **{"depthUpper": 0, "depthLower": 30}) for m in measurements_missing_depths]
149
+
150
+
151
+ def _get_needed_depths(site: dict) -> list:
152
+ needed_depths = list(STANDARD_DEPTHS)
153
+ for measurement in site.get("measurements", []):
154
+ if (measurement.get("depthUpper"), measurement.get("depthLower")) in needed_depths:
155
+ needed_depths.remove((int(measurement["depthUpper"]), int(measurement["depthLower"])))
156
+
157
+ return needed_depths
158
+
159
+
160
+ def _should_run(site: dict, model_key: str):
161
+ # we only work with measurements with depths
162
+ measurements = [
163
+ m for m in site.get("measurements", [])
164
+ if get_lookup_value(m.get("term", {}), LOOKUPS["measurement"][0], model=MODEL, model_key=model_key)
165
+ ]
166
+
167
+ measurements_with_depths = [m for m in measurements if all([
168
+ "depthUpper" in m.keys(),
169
+ "depthLower" in m.keys(),
170
+ (int(m.get("depthUpper", 0)), int(m.get("depthLower", 0))) not in STANDARD_DEPTHS
171
+ ])]
172
+ has_measurements_with_depths = len(measurements_with_depths) > 0
173
+
174
+ measurements_missing_depth_recommended = [m for m in measurements if all([
175
+ "depthUpper" not in m.keys(),
176
+ "depthLower" not in m.keys(),
177
+ not get_lookup_value(m.get("term", {}), LOOKUPS["measurement"][1], model=MODEL, model_key=model_key)
178
+ ])]
179
+
180
+ logRequirements(site, model=MODEL, model_key=model_key,
181
+ has_measurements_with_depths=has_measurements_with_depths,
182
+ has_missing_depths=bool(measurements_missing_depth_recommended))
183
+
184
+ should_run = has_measurements_with_depths or bool(measurements_missing_depth_recommended)
185
+ for measurement in measurements_with_depths + measurements_missing_depth_recommended:
186
+ term_id = measurement.get("term", {}).get("@id", {})
187
+ logShouldRun(site, MODEL, term_id, should_run)
188
+ return should_run, measurements_with_depths, measurements_missing_depth_recommended
189
+
190
+
191
+ def run(site: dict):
192
+ should_run, measurements_with_depths, measurements_missing_depth = _should_run(site=site, model_key=MODEL_KEY)
193
+ needed_depths = _get_needed_depths(site)
194
+ return non_empty_list(flatten(
195
+ _run_harmonisation(measurements=measurements_with_depths, needed_depths=needed_depths)
196
+ + _run_gap_fill_depths(measurements_missing_depths=measurements_missing_depth)
197
+ )) if should_run else []
@@ -1,6 +1,6 @@
1
1
  from hestia_earth.schema import CycleFunctionalUnit, SiteSiteType, TermTermType
2
2
  from hestia_earth.utils.model import filter_list_term_type, find_term_match, find_primary_product
3
- from hestia_earth.utils.tools import flatten, list_sum, safe_parse_float, safe_parse_date
3
+ from hestia_earth.utils.tools import list_sum, safe_parse_float, safe_parse_date
4
4
 
5
5
  from ..log import logRequirements, debugValues
6
6
  from .lookup import factor_value
@@ -368,7 +368,7 @@ def is_organic(cycle: dict):
368
368
  return any([get_lookup_value(p.get('term', {}), 'isOrganic') == 'organic' for p in practices])
369
369
 
370
370
 
371
- def is_irrigated(cycle: dict):
371
+ def is_irrigated(cycle: dict, **log_ars):
372
372
  """
373
373
  Check if the `Cycle` is irrigated, i.e. if it contains an irrigated `Practice` with a value above `0`.
374
374
 
@@ -376,16 +376,17 @@ def is_irrigated(cycle: dict):
376
376
  ----------
377
377
  cycle : dict
378
378
  The `Cycle`.
379
+ log_ars : dict[str, Any]
380
+ Extra loggging, e.g. model, term.
379
381
 
380
382
  Returns
381
383
  -------
382
384
  bool
383
385
  `True` if the `Cycle` is irrigated, `False` otherwise.
384
386
  """
385
- irrigated_practices = [
386
- p for p in cycle.get('practices', []) if p.get('term', {}).get('@id', '').startswith('irrigated')
387
- ]
388
- return list_sum(flatten([p.get('value', []) for p in irrigated_practices])) > 0
387
+ practices = filter_list_term_type(cycle.get('practices', []), TermTermType.WATERREGIME)
388
+ irrigated_practices = [p for p in practices if get_lookup_value(p.get('term', {}), 'irrigated', **log_ars)]
389
+ return any([list_sum(p.get('value', []), 0) > 0 for p in irrigated_practices])
389
390
 
390
391
 
391
392
  def cycle_end_year(cycle: dict):
@@ -4,6 +4,8 @@ from hestia_earth.utils.model import linked_node
4
4
  from hestia_earth.utils.lookup import get_table_value, download_lookup, column_name
5
5
 
6
6
  from . import _term_id, _include_methodModel
7
+ from .blank_node import find_terms_value
8
+ from .constant import Units, get_atomic_conversion
7
9
 
8
10
 
9
11
  def _new_emission(term, model=None):
@@ -17,3 +19,16 @@ def is_in_system_boundary(term_id: str):
17
19
  value = get_table_value(lookup, 'termid', term_id, column_name('inHestiaDefaultSystemBoundary'))
18
20
  # handle numpy boolean
19
21
  return not (not value)
22
+
23
+
24
+ def get_nh3_no3_nox_to_n(cycle: dict, nh3_term_id: str, no3_term_id: str, nox_term_id: str, allow_none: bool = False):
25
+ default_value = 0 if allow_none else None
26
+
27
+ nh3 = find_terms_value(cycle.get('emissions', []), nh3_term_id, default=default_value)
28
+ nh3 = None if nh3 is None else nh3 / get_atomic_conversion(Units.KG_NH3, Units.TO_N)
29
+ no3 = find_terms_value(cycle.get('emissions', []), no3_term_id, default=default_value)
30
+ no3 = None if no3 is None else no3 / get_atomic_conversion(Units.KG_NO3, Units.TO_N)
31
+ nox = find_terms_value(cycle.get('emissions', []), nox_term_id, default=default_value)
32
+ nox = None if nox is None else nox / get_atomic_conversion(Units.KG_NOX, Units.TO_N)
33
+
34
+ return (nh3, no3, nox)
@@ -1 +1 @@
1
- VERSION = '0.59.1'
1
+ VERSION = '0.59.2'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hestia-earth-models
3
- Version: 0.59.1
3
+ Version: 0.59.2
4
4
  Summary: Hestia's set of modules for filling gaps in the activity data using external datasets (e.g. populating soil properties with a geospatial dataset using provided coordinates) and internal lookups (e.g. populating machinery use from fuel use). Includes rules for when gaps should be filled versus not (e.g. never gap fill yield, gap fill crop residue if yield provided etc.).
5
5
  Home-page: https://gitlab.com/hestia-earth/hestia-engine-models
6
6
  Author: Hestia Team
@@ -3,7 +3,7 @@ hestia_earth/models/__init__.py,sha256=qEFeq3yuf3lQKVseALmL8aPM8fpCS54B_5pry00M3
3
3
  hestia_earth/models/cache_sites.py,sha256=kp_3D09P-JdAn9vt7eU-KKTwd6BAXWKQL_0UQCDsH2s,4798
4
4
  hestia_earth/models/log.py,sha256=b63I3qyTtQs17xxbq8RI0Fv2lvZ1oDZ9k0njhxqiFFk,3459
5
5
  hestia_earth/models/requirements.py,sha256=znNZJAhwX2iYiKcAQXPftY7z_1MsNa0QxCXkXyHm_U0,17363
6
- hestia_earth/models/version.py,sha256=LsmLTJIb3gRkCkowNKNONE3gjzMidoU3T3ZdHLRP_xc,19
6
+ hestia_earth/models/version.py,sha256=58Yl5t5ON-GW8LlDihjO_US-BZGFRvSNjAnjUrGJ5wQ,19
7
7
  hestia_earth/models/agribalyse2016/__init__.py,sha256=WvK0qCQbnYtg9oZxrACd1wGormZyXibPtpCnIQeDqbw,415
8
8
  hestia_earth/models/agribalyse2016/fuelElectricity.py,sha256=mrh8seYSYdTgcMDCETLiknuPeJehg071YoG4UiyW0yU,4404
9
9
  hestia_earth/models/agribalyse2016/machineryInfrastructureDepreciatedAmountPerCycle.py,sha256=_Rbngu0DzHKa62JwBl58ZC_ui1zLF2que_nB7ukhOQc,3392
@@ -44,7 +44,7 @@ hestia_earth/models/cycle/excretaKgMass.py,sha256=iA8Kfl3WvyxbQpx1QOGPQZ9O_Pc5rj
44
44
  hestia_earth/models/cycle/excretaKgN.py,sha256=mgJTneQIYJ9Su-rTK5ppb_k3YhICFNWsfPZtGR98RI0,2968
45
45
  hestia_earth/models/cycle/excretaKgVs.py,sha256=ed-DcQoQXZgWF8UZDs2N-G6EBIOPmpXu3BD6jdmh0V0,2973
46
46
  hestia_earth/models/cycle/inorganicFertiliser.py,sha256=3pJRcbZ0OQSNkFq_YC4McpiwLvWJpnL29AhhmCxr7RI,6938
47
- hestia_earth/models/cycle/irrigatedTypeUnspecified.py,sha256=OgKEuGmLLieS_aZ-2eA6r78UcXo1jcA0JJRZUllMHJg,2303
47
+ hestia_earth/models/cycle/irrigatedTypeUnspecified.py,sha256=KlIa5eDvT47Twz6Q1kpw0rMlRjCK25CExaW58DEvc9w,2125
48
48
  hestia_earth/models/cycle/liveAnimal.py,sha256=orJz6ZN3bbGNzU9s5xsTk3u8K4ntPSv1_PyG0Nwslh8,3934
49
49
  hestia_earth/models/cycle/milkYield.py,sha256=RGaD5RtinMTsu6p49YUgr5z1NAVgCNFNPmwWa_Wrk3Q,5718
50
50
  hestia_earth/models/cycle/pastureGrass.py,sha256=7PrmDMJPtsbKGa8WIOh_4NXNtbH3Pxb23pmjawQuY9o,1226
@@ -176,7 +176,7 @@ hestia_earth/models/impact_assessment/__init__.py,sha256=gTR_PhWps593fPhm-V826VL
176
176
  hestia_earth/models/impact_assessment/emissions.py,sha256=zRQd17joMqij8mjRcrY9LssHgwzsYC5bkoy7iGdjj-Q,3429
177
177
  hestia_earth/models/impact_assessment/freshwaterWithdrawalsDuringCycle.py,sha256=wvNwABEh4blgm95G9y_yorMNEjyYsq4MZiFggkPRuIE,3932
178
178
  hestia_earth/models/impact_assessment/freshwaterWithdrawalsInputsProduction.py,sha256=DSLX_aEWaUFcFZRD46bG5lIQ4TtAtIqH-sMkVCJH2Dg,990
179
- hestia_earth/models/impact_assessment/irrigated.py,sha256=bXUQdF3SrL9Lqh6QztL5Gcbar0AfTiN5FHVco0JvMpA,704
179
+ hestia_earth/models/impact_assessment/irrigated.py,sha256=qopAYbD91uu1Q2hJ3aB5Xl3br2Nzh7LoMTRCFOXmOv0,783
180
180
  hestia_earth/models/impact_assessment/landOccupationInputsProduction.py,sha256=SggB_4tpiKNeb6TIQWBm-X9VwG4pzLoyHdK8JroRIsE,576
181
181
  hestia_earth/models/impact_assessment/landTransformationFromCropland100YearAverageInputsProduction.py,sha256=jxeJS8r1qYIoyeEE-MGKbldEDL3x9CG8aIb4JdcUnj4,1036
182
182
  hestia_earth/models/impact_assessment/landTransformationFromCropland20YearAverageInputsProduction.py,sha256=vluuIcr1jYhs11oz7nANk2qUuUVPy5uNkvpfMv_M4LE,1034
@@ -202,15 +202,15 @@ hestia_earth/models/ipcc2006/aboveGroundCropResidueRemoved.py,sha256=6FDgMH5eiO1
202
202
  hestia_earth/models/ipcc2006/aboveGroundCropResidueTotal.py,sha256=vD_kpvOJmjTOjDEnlqSYBSZxjuPGvzpmCr0JIC84GKE,3431
203
203
  hestia_earth/models/ipcc2006/belowGroundCropResidue.py,sha256=KzeRphJb1IWB_EPVcxa9tbCoNmEe80D9lKxgQOqfKoU,4138
204
204
  hestia_earth/models/ipcc2006/co2ToAirOrganicSoilCultivation.py,sha256=8AzFuqRprk6o-uyyI3XYsTGl2dP_ALgYJXWCseYEBQ8,3029
205
- hestia_earth/models/ipcc2006/n2OToAirCropResidueDecompositionIndirect.py,sha256=WDpxmnlFsEWOPYI4uc-AIIZQNohwwKOrOIqTkRMlKZo,2333
205
+ hestia_earth/models/ipcc2006/n2OToAirCropResidueDecompositionIndirect.py,sha256=kf4WjdMzs6d8h433LFuUH9LJKJ_aMHTqEHDToGY5-Xk,2315
206
206
  hestia_earth/models/ipcc2006/n2OToAirExcretaDirect.py,sha256=VvQTIh58JyhrdPk5FdJQBkjBDr5-Cv7CnGkNEcco3P4,1986
207
- hestia_earth/models/ipcc2006/n2OToAirExcretaIndirect.py,sha256=WFWC3Hvw1-XXs_tHhZ-lwKtchanITOvEyHU4WgFSBV0,2261
207
+ hestia_earth/models/ipcc2006/n2OToAirExcretaIndirect.py,sha256=me1MLX2WI5A_VZ11774CRxwRC6seOaxgMg_GGYCckIk,2243
208
208
  hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserDirect.py,sha256=hhFioTDxWZ2g_SjDt0k5tq6P8AJrq48i65qUpAfW_sU,2144
209
- hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py,sha256=FjwtDdp-TTp_KKR0w00LTVtRUptiIkJOMXWD2-EL9sY,2847
209
+ hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py,sha256=MNFyXPCLX_RqfRQkO0UzVIYVevpEBO3R2uh3sIoIycM,2863
210
210
  hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserDirect.py,sha256=MZUmA3ajGkpi4wr020OU6m4WJdujjKkRhUVsbPgUVb8,2094
211
- hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserIndirect.py,sha256=qbHuht24JRtPBtRthzNSxCCaS5EzTOwCm1VIcgcUZSo,2785
211
+ hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserIndirect.py,sha256=pgNG18EwgTA7kmVw9QFtucMn8ScVeEKJAsSPxcExbI8,2801
212
212
  hestia_earth/models/ipcc2006/n2OToAirOrganicSoilCultivationDirect.py,sha256=0J6ntZxYyLg3pUQeSQelDe36fb0nQtbMLjIBtwzHUyc,3038
213
- hestia_earth/models/ipcc2006/utils.py,sha256=mcfXf2gJKVShvER0LkEpTGp3tShXz25ZKNlYojlEGc4,1419
213
+ hestia_earth/models/ipcc2006/utils.py,sha256=7-0rfkjgm8tH0dx5nfi-9sFP07L9Dli_2UCZf6eL2qU,541
214
214
  hestia_earth/models/ipcc2013ExcludingFeedbacks/__init__.py,sha256=v4Qe-X4w3tqIHGJBNnEAK81x4ZuQMwYxQYXRncugmcU,427
215
215
  hestia_earth/models/ipcc2013ExcludingFeedbacks/gwp100.py,sha256=8VRg-Vvzc86_CQmBH-iHNhaSnAFHew2swAMecT0aXW4,979
216
216
  hestia_earth/models/ipcc2013IncludingFeedbacks/__init__.py,sha256=VJ16KIGQQHybzZiTvu3mpZy_3j0xcd06RHHCfPrCMgU,427
@@ -227,20 +227,24 @@ hestia_earth/models/ipcc2019/co2ToAirSoilCarbonStockChangeManagementChange.py,sh
227
227
  hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py,sha256=ICE3r8GMoHj6WfMUxQdqdejRpOLa3cxDMyF3GvSTW0U,3700
228
228
  hestia_earth/models/ipcc2019/croppingDuration.py,sha256=_jlFrTNDOARH2_g8s4dzuaCoLHSX2BHzSQd3uuQN32Y,3173
229
229
  hestia_earth/models/ipcc2019/ligninContent.py,sha256=wp5EbCthCDAKyvPBfZULS9-uKEY58TQQ8ey1pf-juv8,7267
230
- hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionDirect.py,sha256=c4DOH5Evmxgm4x6MmUMzi4x77D8otT-sdlD-spQVIOs,4069
230
+ hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionDirect.py,sha256=Fand7NbT27unwgFTxi_9NxT024s63vQ7U6-tk9yp3d8,3990
231
+ hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionIndirect.py,sha256=_Oj6Jw8F4rce7FmhWkzeqyB7W3ZQWpOiA10p6xrfSwc,3777
231
232
  hestia_earth/models/ipcc2019/n2OToAirExcretaDirect.py,sha256=9rpp5NvFZOGRSnkfLhBoMqArdzKSd4fH-fgQEnbTT4I,1722
233
+ hestia_earth/models/ipcc2019/n2OToAirExcretaIndirect.py,sha256=4TfJg5OhTnj_ulW-IH8Jz1hMRB0zKMQdh0vBZKL6nqg,3650
232
234
  hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserDirect.py,sha256=NfS6EiEVSf-hpWHqO3r-1PKPuHPVb6ijTNLTbOlRCp0,4062
233
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py,sha256=9tCk0ZIUitj6XXfz8wvnGL6SR6L3aRhXL0FFpaXxQkE,4216
235
+ hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py,sha256=iNjwTyktLqD0HpwfwAEnAHbQUDNQmT7ekONF_lJobzE,3715
234
236
  hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserDirect.py,sha256=pMyl6UtUVgPWfczgA_cdm1RUdMGi4Ln16qWrw1eesv4,4138
235
- hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py,sha256=g6vWbuooOU9Xg4V0Oqo8730UeeiwOwNPCVJMz9NoeTw,4110
237
+ hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py,sha256=9YbaR8h7P-4rLHgcwtDLnQ_hT7cKzyELjCVJ9lWV2jI,3701
238
+ hestia_earth/models/ipcc2019/nh3ToAirOrganicFertiliser.py,sha256=fsuc4pojyOfNrfnwLpVlfUWScm6SznJ5s_rbxhB6zJg,3717
236
239
  hestia_earth/models/ipcc2019/nitrogenContent.py,sha256=6fGG7diDp9zAidVH75gXz9c8uxURx0Q2COo8KrkT3I4,7191
237
240
  hestia_earth/models/ipcc2019/no3ToGroundwaterCropResidueDecomposition.py,sha256=8NOjbqJuQ-wnLz3bYmwaygSzKBdaF3N7hoELGNnO4YQ,3115
238
241
  hestia_earth/models/ipcc2019/no3ToGroundwaterExcreta.py,sha256=mJUXLGtg9EOZq9LH0KFOKvzER1ypCUucs0ZMaNYMShc,2991
239
242
  hestia_earth/models/ipcc2019/no3ToGroundwaterInorganicFertiliser.py,sha256=wTvMBthqmiKMn4nLbL4VD6_8_gGI2WGR3OYz3KK8sXs,3105
240
243
  hestia_earth/models/ipcc2019/no3ToGroundwaterOrganicFertiliser.py,sha256=zOhp6NhYUuUNU_LMMwhZBP78YC2XRWRlGnajBUX2AN8,3095
241
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py,sha256=7FXRYTrgFFdU1Fjo4HegfipiWPbY5ChcBi3qRfc7aXE,141142
244
+ hestia_earth/models/ipcc2019/noxToAirOrganicFertiliser.py,sha256=VK3F0GUBG5CYJj0tLercVryj1ezj58PxaFi_zqijHvE,3717
245
+ hestia_earth/models/ipcc2019/organicCarbonPerHa.py,sha256=ADn2kv6uzfJb71ti8ydI3aGiGQMj0HsIZDjgxdU2Aic,142289
242
246
  hestia_earth/models/ipcc2019/pastureGrass.py,sha256=CpDEtdnbKd_8eaDLcflJ-dGik3t879HIoEIzuaHNmC0,23168
243
- hestia_earth/models/ipcc2019/utils.py,sha256=1DfHJxVktu7vZMqj-yVjGb_59sHi7lu91GDnB5-qR4o,6504
247
+ hestia_earth/models/ipcc2019/utils.py,sha256=MSDMu15D9DnilFUgi4_6jYXC0FaKso3OODauGTMB6hs,6229
244
248
  hestia_earth/models/ipcc2021/__init__.py,sha256=VTgGFKhwMmk_nuI1RRq0in27fHYVPBonlXlPK00K8no,409
245
249
  hestia_earth/models/ipcc2021/gwp100.py,sha256=v-DYU-11XnWI1Ns1GEiKrJqL3JafxvhTsLmuBuFcxJU,1021
246
250
  hestia_earth/models/jarvisAndPain1994/__init__.py,sha256=ercUwy29sV7oPIESj8UjsGB5lqiBCss9OZcbjxeeG8E,418
@@ -447,6 +451,7 @@ hestia_earth/models/site/precipitationAnnual.py,sha256=to14BEFjUaYyCu5aIBQZtuaIr
447
451
  hestia_earth/models/site/precipitationMonthly.py,sha256=yGUbiUCu1Prp3qVHuZodGrcfrbYu170WTUGyaj-KEjY,1896
448
452
  hestia_earth/models/site/rainfallAnnual.py,sha256=Ix_B8Ny7IIRkJ_3lUvoHOjPgqCyR9I0U3_ADUUtMqsY,2003
449
453
  hestia_earth/models/site/rainfallMonthly.py,sha256=2Uo8F-YxnTK0_txlHmiAyVp1bGfWD4bneRKyg4tdQkI,1881
454
+ hestia_earth/models/site/soilMeasurement.py,sha256=pFh7-lpcBrvpOZ071XhadpuK_5AoywIFaekRfGosY5U,7839
450
455
  hestia_earth/models/site/temperatureAnnual.py,sha256=Q3b1RH2_hpA0JWwOYA5nKgMGcXHjV8-akXT9vB0cbwc,2012
451
456
  hestia_earth/models/site/temperatureMonthly.py,sha256=yXwpFCGT2tUqvVBNedaPyBmN_KlzZqo5yv2TWem1pBk,1890
452
457
  hestia_earth/models/site/totalNitrogenPerKgSoil.py,sha256=8ERrTZpN_yCRUyFg_EYaX4abE9jLcyX3lx3MO4Bi6CE,1938
@@ -501,9 +506,9 @@ hestia_earth/models/utils/crop.py,sha256=S8UycHpkgx_TznW3Q7pchEMlCQ623T_SqU6V5fB
501
506
  hestia_earth/models/utils/cropResidue.py,sha256=_0Q35CrliJeo31xGHsPWe8A2oHxijdIsOrf3gBEqhlA,612
502
507
  hestia_earth/models/utils/cropResidueManagement.py,sha256=nIDFjf39rDD10UHSVudfDyu-EiL261g8jyrgS-2aDKw,347
503
508
  hestia_earth/models/utils/currency.py,sha256=f_ArJANb--pZq4LL49SXQ1AMX_oKroqwBXKRRQqZwsM,578
504
- hestia_earth/models/utils/cycle.py,sha256=gDCGfAb_bZ9pdqZrIhUMNUJ_qT11GyY-w1zlayvoAsA,16511
509
+ hestia_earth/models/utils/cycle.py,sha256=F5dykDeHJfnSm6m7YCqQT3Ip3OZsAB-oipbKwbvslBE,16647
505
510
  hestia_earth/models/utils/ecoClimateZone.py,sha256=NHFt-A9EiWXC6tUNIxkgOWUZOjj4I4uwJIP9ddDZegw,1112
506
- hestia_earth/models/utils/emission.py,sha256=W0yCUnr_FQB5f6-SF6skoDC6MzC6zglwNrKWTPYCUdo,748
511
+ hestia_earth/models/utils/emission.py,sha256=AVp-ngrb4VHYT8BG1QA5EEb17edT3cLonsXV3cNm04U,1576
507
512
  hestia_earth/models/utils/excretaManagement.py,sha256=NuWPQjFZxMVt9sYgBjcqhGWCFk_OKb3sA9Ovcff3fRQ,428
508
513
  hestia_earth/models/utils/feedipedia.py,sha256=fqlpAwG_jbZAFPWJ-yUI7gwn0oq--1GLTlHLsCeBbPQ,3181
509
514
  hestia_earth/models/utils/fuel.py,sha256=r1MKMMxg-PYiVlRutP83RuvY2rsdCQ1iN6ekSGGQGpA,1379
@@ -744,17 +749,21 @@ tests/models/ipcc2019/test_co2ToAirUreaHydrolysis.py,sha256=MmtEME0xjsa3KojFk_fx
744
749
  tests/models/ipcc2019/test_croppingDuration.py,sha256=gLRXeR6Tqa7ciD9KTRfsIflSeIIWT2iOpZMdcxAQla4,1871
745
750
  tests/models/ipcc2019/test_ligninContent.py,sha256=eIKEN__ab-0R52EhlhPSBiHnmTl6xOf1XbI33O-W9A4,4146
746
751
  tests/models/ipcc2019/test_n2OToAirCropResidueDecompositionDirect.py,sha256=lVfSKpVszGK42pzo2FefXNZRmXbqOt25IBcnxvhC_X0,2418
752
+ tests/models/ipcc2019/test_n2OToAirCropResidueDecompositionIndirect.py,sha256=it2PVNYBNAvQWmWLDJ9Evjqtx7SJl-X0ZyQz3Fuvb3k,2119
747
753
  tests/models/ipcc2019/test_n2OToAirExcretaDirect.py,sha256=JYvBK4edcqfHrMPwgBFXF6km51ew9RISUcfQ_RNf2RY,1216
754
+ tests/models/ipcc2019/test_n2OToAirExcretaIndirect.py,sha256=z46L5JMB4-W0uCyyFlLKTEyDnt2gUHRkH7dEXK6ioHk,2098
748
755
  tests/models/ipcc2019/test_n2OToAirInorganicFertiliserDirect.py,sha256=ffk-aom1BqyEmqm-JESWX5MErrAVAgVuH1gjW32U5Pk,2407
749
- tests/models/ipcc2019/test_n2OToAirInorganicFertiliserIndirect.py,sha256=X61AE9Eb0Lqwy4AkfKKaHKU-p4C5JZIo326t8BT6ALs,1613
756
+ tests/models/ipcc2019/test_n2OToAirInorganicFertiliserIndirect.py,sha256=RnU8CkUCYBBO1bgJALnoVgjTHLL1L1sja2nsyeVA_cg,2113
750
757
  tests/models/ipcc2019/test_n2OToAirOrganicFertiliserDirect.py,sha256=XQpzdEFT7qSw6KKRYEZ6Cmzkc_xLyG98FHH1PSfOUo0,2403
751
- tests/models/ipcc2019/test_n2OToAirOrganicFertiliserIndirect.py,sha256=cPXdknWmXJig9i_AR19oX4g3GjTcEo8455DsD2w8M10,1609
758
+ tests/models/ipcc2019/test_n2OToAirOrganicFertiliserIndirect.py,sha256=hW84sTlhB8mKRSFJX_iQS4gYo74zCtY-9zr1VHLC5GU,2111
759
+ tests/models/ipcc2019/test_nh3ToAirOrganicFertiliser.py,sha256=Z4a20I2UnZdzm6FqHnlHRXXVCY993_SHT7nG-zAhx-c,1104
752
760
  tests/models/ipcc2019/test_nitrogenContent.py,sha256=rKl_05PCC0OSsAhG0cHJOqnt9LsCaFnRpJorkm1TShA,3704
753
761
  tests/models/ipcc2019/test_no3ToGroundwaterCropResidueDecomposition.py,sha256=4__3HDUDWt5KjQGcXEFXHBgP_jT0rxvIzpBLH_mP9WE,1729
754
762
  tests/models/ipcc2019/test_no3ToGroundwaterExcreta.py,sha256=Z-pCBQvlUf0ttmCERgezW-6e3KlX45YEVccOwthf5lU,1588
755
763
  tests/models/ipcc2019/test_no3ToGroundwaterInorganicFertiliser.py,sha256=e7REnQ9r9a8xroq5aPp0NIzmkad_6MyTuceRTYoKdkE,1613
756
764
  tests/models/ipcc2019/test_no3ToGroundwaterOrganicFertiliser.py,sha256=e1ZViD12qB3bLdH3TJw3GbBP8iqMen-UJbcFkytb3VQ,1609
757
- tests/models/ipcc2019/test_organicCarbonPerHa.py,sha256=UtiFAYJSqIz8_zb0H4qFRfh-6c-m422THoV3KfHHXpQ,20374
765
+ tests/models/ipcc2019/test_noxToAirOrganicFertiliser.py,sha256=LR5pjV5vRbgSSQAw8kYRp_ij4CHInzgaDS6EggQuBiw,1104
766
+ tests/models/ipcc2019/test_organicCarbonPerHa.py,sha256=lsg148KPupjF4ds8yUy1Cl2hcVXaGT9AIgkGycbHqXI,21643
758
767
  tests/models/ipcc2019/test_pastureGrass.py,sha256=pE4PWdR541v4xWDYihP7Dou8V1iqg5GwD5_rjGRzrds,2292
759
768
  tests/models/ipcc2021/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
760
769
  tests/models/ipcc2021/test_gwp100.py,sha256=JRklKMSg-OXopb9ZufGgl94deuMuJSsfNXRZDBtOZrE,1119
@@ -956,6 +965,7 @@ tests/models/site/test_precipitationAnnual.py,sha256=h0tXvykZw4Zaw225RHfvw-3DvAy
956
965
  tests/models/site/test_precipitationMonthly.py,sha256=iccr-_ZrseM_OT3AKZbTNQhRFSIe-R6wXTDS-2wIVew,995
957
966
  tests/models/site/test_rainfallAnnual.py,sha256=4YYna66qjJptPJ_URvdcQuRC3dri9SB0xmWP8DFwslM,986
958
967
  tests/models/site/test_rainfallMonthly.py,sha256=A3gIe2Yxt9CLtLcAJNCQ0-8aRB49VdfKBLBy-7eDgJw,985
968
+ tests/models/site/test_soilMeasurement.py,sha256=yXOG0EKyk57NvIqVDIohjZRubQ4aJoLw63Nwi6H54r8,4445
959
969
  tests/models/site/test_temperatureAnnual.py,sha256=nOJG9ZJ8NCMM8T47uxxBeloIYLFN6-xtvUBqJsqt8xk,992
960
970
  tests/models/site/test_temperatureMonthly.py,sha256=C2lv-lpYqH7VUGOlxNLE6d7k_dFS6NYe8BvMlrJorCw,991
961
971
  tests/models/site/test_totalNitrogenPerKgSoil.py,sha256=2ILrA0jQKGniiKwS5FF3ZLtudgUgjcMnzFtrHpJKPTc,1161
@@ -1017,8 +1027,8 @@ tests/models/utils/test_source.py,sha256=mv3vHZV5cjpoLA2I1109-YUkuzAiuhbRSnv_76_
1017
1027
  tests/models/utils/test_term.py,sha256=JJmzyHnhVGeQ7tG-T6DjE7CoIJPH0guH-y2kjGeZiJY,3756
1018
1028
  tests/models/webbEtAl2012AndSintermannEtAl2012/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1019
1029
  tests/models/webbEtAl2012AndSintermannEtAl2012/test_nh3ToAirOrganicFertiliser.py,sha256=qi2FNXS5Af2WDtm7nq_FsprH3BfCF0XxnE0XHmC4aIY,2244
1020
- hestia_earth_models-0.59.1.dist-info/LICENSE,sha256=EFSZhfUdZCTsCIYdHzTGewMKfRfp7X9t1s2aaKxm8O0,1154
1021
- hestia_earth_models-0.59.1.dist-info/METADATA,sha256=OmSflUlcdw-cSbja7uMHn26Do72YujIz0dol2DND0Ek,3134
1022
- hestia_earth_models-0.59.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
1023
- hestia_earth_models-0.59.1.dist-info/top_level.txt,sha256=1dqA9TqpOLTEgpqa-YBsmbCmmNU1y56AtfFGEceZ2A0,19
1024
- hestia_earth_models-0.59.1.dist-info/RECORD,,
1030
+ hestia_earth_models-0.59.2.dist-info/LICENSE,sha256=EFSZhfUdZCTsCIYdHzTGewMKfRfp7X9t1s2aaKxm8O0,1154
1031
+ hestia_earth_models-0.59.2.dist-info/METADATA,sha256=-qJ0J6ITtaF7C2fKg8Y38GtdFxZq0FMtcW4XO-H1pkA,3134
1032
+ hestia_earth_models-0.59.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
1033
+ hestia_earth_models-0.59.2.dist-info/top_level.txt,sha256=1dqA9TqpOLTEgpqa-YBsmbCmmNU1y56AtfFGEceZ2A0,19
1034
+ hestia_earth_models-0.59.2.dist-info/RECORD,,
@@ -0,0 +1,71 @@
1
+ from unittest.mock import patch
2
+ import json
3
+ from tests.utils import fixtures_path, fake_new_emission
4
+
5
+ from hestia_earth.models.ipcc2019.n2OToAirCropResidueDecompositionIndirect import (
6
+ MODEL, TERM_ID, run, _should_run, NH3_TERM_ID, NO3_TERM_ID, NOX_TERM_ID
7
+ )
8
+
9
+ class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
10
+ fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
11
+
12
+
13
+ def test_should_run():
14
+ # no emissions => no run
15
+ cycle = {'completeness': {'cropResidue': True}, 'emissions': []}
16
+ should_run, *args = _should_run(cycle)
17
+ assert not should_run
18
+
19
+ # with no3 emission => run
20
+ cycle['emissions'] = [
21
+ {
22
+ 'term': {'@id': NO3_TERM_ID},
23
+ 'value': [100]
24
+ },
25
+ {
26
+ 'term': {'@id': NH3_TERM_ID},
27
+ 'value': [100]
28
+ },
29
+ {
30
+ 'term': {'@id': NOX_TERM_ID},
31
+ 'value': [100]
32
+ }
33
+ ]
34
+ should_run, *args = _should_run(cycle)
35
+ assert should_run is True
36
+
37
+
38
+ @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
39
+ def test_run(*args):
40
+ with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
41
+ cycle = json.load(f)
42
+
43
+ with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
44
+ expected = json.load(f)
45
+
46
+ value = run(cycle)
47
+ assert value == expected
48
+
49
+
50
+ @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
51
+ def test_run_wet(*args):
52
+ with open(f"{fixtures_folder}/ecoClimateZone-wet/cycle.jsonld", encoding='utf-8') as f:
53
+ cycle = json.load(f)
54
+
55
+ with open(f"{fixtures_folder}/ecoClimateZone-wet/result.jsonld", encoding='utf-8') as f:
56
+ expected = json.load(f)
57
+
58
+ value = run(cycle)
59
+ assert value == expected
60
+
61
+
62
+ @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
63
+ def test_run_dry(*args):
64
+ with open(f"{fixtures_folder}/ecoClimateZone-dry/cycle.jsonld", encoding='utf-8') as f:
65
+ cycle = json.load(f)
66
+
67
+ with open(f"{fixtures_folder}/ecoClimateZone-dry/result.jsonld", encoding='utf-8') as f:
68
+ expected = json.load(f)
69
+
70
+ value = run(cycle)
71
+ assert value == expected
@@ -0,0 +1,71 @@
1
+ from unittest.mock import patch
2
+ import json
3
+ from tests.utils import fixtures_path, fake_new_emission
4
+
5
+ from hestia_earth.models.ipcc2019.n2OToAirExcretaIndirect import (
6
+ MODEL, TERM_ID, run, _should_run, NH3_TERM_ID, NO3_TERM_ID, NOX_TERM_ID
7
+ )
8
+
9
+ class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
10
+ fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
11
+
12
+
13
+ def test_should_run():
14
+ # no emissions => no run
15
+ cycle = {'completeness': {'excreta': True}, 'emissions': []}
16
+ should_run, *args = _should_run(cycle)
17
+ assert not should_run
18
+
19
+ # with no3 emission => run
20
+ cycle['emissions'] = [
21
+ {
22
+ 'term': {'@id': NO3_TERM_ID},
23
+ 'value': [100]
24
+ },
25
+ {
26
+ 'term': {'@id': NH3_TERM_ID},
27
+ 'value': [100]
28
+ },
29
+ {
30
+ 'term': {'@id': NOX_TERM_ID},
31
+ 'value': [100]
32
+ }
33
+ ]
34
+ should_run, *args = _should_run(cycle)
35
+ assert should_run is True
36
+
37
+
38
+ @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
39
+ def test_run(*args):
40
+ with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
41
+ cycle = json.load(f)
42
+
43
+ with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
44
+ expected = json.load(f)
45
+
46
+ value = run(cycle)
47
+ assert value == expected
48
+
49
+
50
+ @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
51
+ def test_run_wet(*args):
52
+ with open(f"{fixtures_folder}/ecoClimateZone-wet/cycle.jsonld", encoding='utf-8') as f:
53
+ cycle = json.load(f)
54
+
55
+ with open(f"{fixtures_folder}/ecoClimateZone-wet/result.jsonld", encoding='utf-8') as f:
56
+ expected = json.load(f)
57
+
58
+ value = run(cycle)
59
+ assert value == expected
60
+
61
+
62
+ @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
63
+ def test_run_dry(*args):
64
+ with open(f"{fixtures_folder}/ecoClimateZone-dry/cycle.jsonld", encoding='utf-8') as f:
65
+ cycle = json.load(f)
66
+
67
+ with open(f"{fixtures_folder}/ecoClimateZone-dry/result.jsonld", encoding='utf-8') as f:
68
+ expected = json.load(f)
69
+
70
+ value = run(cycle)
71
+ assert value == expected
@@ -2,26 +2,49 @@ from unittest.mock import patch
2
2
  import json
3
3
  from tests.utils import fixtures_path, fake_new_emission
4
4
 
5
- from hestia_earth.models.ipcc2019.n2OToAirInorganicFertiliserIndirect import MODEL, TERM_ID, run, _should_run
5
+ from hestia_earth.models.ipcc2019.n2OToAirInorganicFertiliserIndirect import (
6
+ MODEL, TERM_ID, run, _should_run, NH3_TERM_ID, NO3_TERM_ID, NOX_TERM_ID
7
+ )
6
8
 
7
9
  class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
8
10
  fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
9
11
 
10
12
 
11
- @patch(f"{class_path}.get_ecoClimateZone", return_value=2)
12
- @patch(f"{class_path}._is_term_type_complete", return_value=False)
13
- @patch(f"{class_path}.get_inorganic_fertiliser_N_total", return_value=0)
14
- def test_should_run(mock_N_total, mock_complete, *args):
15
- # no N => no run
16
- assert not _should_run({})
13
+ def test_should_run():
14
+ # no emissions => no run
15
+ cycle = {'completeness': {'fertiliser': True}, 'emissions': []}
16
+ should_run, *args = _should_run(cycle)
17
+ assert not should_run
17
18
 
18
- # with N => no run
19
- mock_N_total.return_value = 10
20
- assert not _should_run({})
19
+ # with no3 emission => run
20
+ cycle['emissions'] = [
21
+ {
22
+ 'term': {'@id': NO3_TERM_ID},
23
+ 'value': [100]
24
+ },
25
+ {
26
+ 'term': {'@id': NH3_TERM_ID},
27
+ 'value': [100]
28
+ },
29
+ {
30
+ 'term': {'@id': NOX_TERM_ID},
31
+ 'value': [100]
32
+ }
33
+ ]
34
+ should_run, *args = _should_run(cycle)
35
+ assert should_run is True
21
36
 
22
- # is complete => run
23
- mock_complete.return_value = True
24
- assert _should_run({}) is True
37
+
38
+ @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
39
+ def test_run(*args):
40
+ with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
41
+ cycle = json.load(f)
42
+
43
+ with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
44
+ expected = json.load(f)
45
+
46
+ value = run(cycle)
47
+ assert value == expected
25
48
 
26
49
 
27
50
  @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)