hestia-earth-models 0.62.3__py3-none-any.whl → 0.62.5__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 (38) hide show
  1. hestia_earth/models/emepEea2019/co2ToAirFuelCombustion.py +2 -10
  2. hestia_earth/models/emepEea2019/n2OToAirFuelCombustionDirect.py +2 -10
  3. hestia_earth/models/emepEea2019/nh3ToAirExcreta.py +2 -9
  4. hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +2 -9
  5. hestia_earth/models/emepEea2019/noxToAirFuelCombustion.py +2 -10
  6. hestia_earth/models/emepEea2019/pm10ToAirAnimalHousing.py +57 -0
  7. hestia_earth/models/emepEea2019/pm25ToAirAnimalHousing.py +57 -0
  8. hestia_earth/models/emepEea2019/so2ToAirFuelCombustion.py +2 -10
  9. hestia_earth/models/emepEea2019/tspToAirAnimalHousing.py +57 -0
  10. hestia_earth/models/emepEea2019/utils.py +60 -1
  11. hestia_earth/models/faostat2018/liveweightPerHead.py +1 -1
  12. hestia_earth/models/ipcc2019/animal/pastureGrass.py +2 -2
  13. hestia_earth/models/ipcc2019/pastureGrass.py +2 -2
  14. hestia_earth/models/ipcc2019/pastureGrass_utils.py +1 -10
  15. hestia_earth/models/log.py +1 -1
  16. hestia_earth/models/mocking/search-results.json +145 -1
  17. hestia_earth/models/site/management.py +63 -35
  18. hestia_earth/models/utils/cycle.py +10 -1
  19. hestia_earth/models/utils/site.py +7 -0
  20. hestia_earth/models/utils/term.py +21 -1
  21. hestia_earth/models/version.py +1 -1
  22. {hestia_earth_models-0.62.3.dist-info → hestia_earth_models-0.62.5.dist-info}/METADATA +1 -1
  23. {hestia_earth_models-0.62.3.dist-info → hestia_earth_models-0.62.5.dist-info}/RECORD +38 -32
  24. tests/models/emepEea2019/test_co2ToAirFuelCombustion.py +3 -2
  25. tests/models/emepEea2019/test_n2OToAirFuelCombustionDirect.py +3 -2
  26. tests/models/emepEea2019/test_nh3ToAirExcreta.py +2 -1
  27. tests/models/emepEea2019/test_nh3ToAirInorganicFertiliser.py +4 -3
  28. tests/models/emepEea2019/test_noxToAirFuelCombustion.py +3 -2
  29. tests/models/emepEea2019/test_pm10ToAirAnimalHousing.py +21 -0
  30. tests/models/emepEea2019/test_pm25ToAirAnimalHousing.py +21 -0
  31. tests/models/emepEea2019/test_so2ToAirFuelCombustion.py +3 -2
  32. tests/models/emepEea2019/test_tspToAirAnimalHousing.py +21 -0
  33. tests/models/emepEea2019/test_utils.py +198 -1
  34. tests/models/faostat2018/test_liveweightPerHead.py +9 -0
  35. tests/models/site/test_management.py +55 -7
  36. {hestia_earth_models-0.62.3.dist-info → hestia_earth_models-0.62.5.dist-info}/LICENSE +0 -0
  37. {hestia_earth_models-0.62.3.dist-info → hestia_earth_models-0.62.5.dist-info}/WHEEL +0 -0
  38. {hestia_earth_models-0.62.3.dist-info → hestia_earth_models-0.62.5.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@ from tests.utils import fixtures_path, fake_new_emission
5
5
  from hestia_earth.models.emepEea2019.so2ToAirFuelCombustion import MODEL, TERM_ID, run, _should_run
6
6
 
7
7
  class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
8
+ model_utils_path = f"hestia_earth.models.{MODEL}.utils"
8
9
  fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
9
10
 
10
11
 
@@ -21,7 +22,7 @@ def test_should_run(mock_get_fuel_values):
21
22
  assert should_run is True
22
23
 
23
24
 
24
- @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
25
+ @patch(f"{model_utils_path}._new_emission", side_effect=fake_new_emission)
25
26
  def test_run(*args):
26
27
  with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
27
28
  cycle = json.load(f)
@@ -33,7 +34,7 @@ def test_run(*args):
33
34
  assert value == expected
34
35
 
35
36
 
36
- @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
37
+ @patch(f"{model_utils_path}._new_emission", side_effect=fake_new_emission)
37
38
  def test_run_data_complete(*args):
38
39
  with open(f"{fixtures_folder}/no-input-data-complete/cycle.jsonld", encoding='utf-8') as f:
39
40
  cycle = json.load(f)
@@ -0,0 +1,21 @@
1
+ from unittest.mock import patch
2
+ import json
3
+
4
+ from tests.utils import fixtures_path, fake_new_emission
5
+ from hestia_earth.models.emepEea2019.tspToAirAnimalHousing import MODEL, TERM_ID, run
6
+
7
+ class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
8
+ model_utils_path = f"hestia_earth.models.{MODEL}.utils"
9
+ fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
10
+
11
+
12
+ @patch(f"{model_utils_path}._new_emission", side_effect=fake_new_emission)
13
+ def test_run(*args):
14
+ with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
15
+ cycle = json.load(f)
16
+
17
+ with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
18
+ expected = json.load(f)
19
+
20
+ value = run(cycle)
21
+ assert value == expected
@@ -1,6 +1,8 @@
1
1
  from unittest.mock import patch
2
2
 
3
- from hestia_earth.models.emepEea2019.utils import get_fuel_values
3
+ import pytest
4
+
5
+ from hestia_earth.models.emepEea2019.utils import get_fuel_values, should_run_animal, _duration_in_housing
4
6
 
5
7
  class_path = 'hestia_earth.models.emepEea2019.utils'
6
8
  TERMS = [
@@ -53,3 +55,198 @@ def test_get_fuel_values(*args):
53
55
  }
54
56
  result = get_fuel_values('co2ToAirFuelCombustion', cycle, 'co2ToAirFuelCombustionEmepEea2019')
55
57
  assert result == [317.0, 632.0, 475.5, 158.5]
58
+
59
+
60
+ @pytest.mark.parametrize(
61
+ "test_name,cycle,expected_duration",
62
+ [
63
+ (
64
+ "no sites => 0",
65
+ {"completeness": {"@type": "Completeness", "animalPopulation": False}},
66
+ 0
67
+ ),
68
+ (
69
+ "site and other sites have wrong type => 0",
70
+ {
71
+ "site": {"@type": "Site", "siteType": "permanent pasture"},
72
+ "siteDuration": 15,
73
+ "otherSites": [
74
+ {"@type": "Site", "siteType": "pond"},
75
+ {"@type": "Site", "siteType": "pond"},
76
+ {"@type": "Site", "siteType": "pond"},
77
+ ],
78
+ "otherSitesDuration": [20, 21, 22],
79
+ },
80
+ 0
81
+ ),
82
+ (
83
+ "only second other site is animal housing => 12",
84
+ {
85
+ "site": {"@type": "Site", "siteType": "pond"},
86
+ "siteDuration": 20,
87
+ "otherSites": [
88
+ {"@type": "Site", "siteType": "pond"},
89
+ {"@type": "Site", "siteType": "animal housing"},
90
+ {"@type": "Site", "siteType": "pond"},
91
+ ],
92
+ "otherSitesDuration": [11, 12, 13],
93
+ },
94
+ 12
95
+ ),
96
+ (
97
+ "only site is animal housing => 20",
98
+ {
99
+ "site": {"@type": "Site", "siteType": "animal housing"},
100
+ "otherSites": [
101
+ {"@type": "Site", "siteType": "forest"},
102
+ {"@type": "Site", "siteType": "forest"},
103
+ {"@type": "Site", "siteType": "forest"},
104
+ ],
105
+ "siteDuration": 20,
106
+ "otherSitesDuration": [12, 13, 14],
107
+ },
108
+ 20
109
+ ),
110
+ (
111
+ "site and otherSites are animal housing, sum all values => 59",
112
+ {
113
+ "site": {"@type": "Site", "siteType": "animal housing"},
114
+ "otherSites": [
115
+ {"@type": "Site", "siteType": "animal housing"},
116
+ {"@type": "Site", "siteType": "animal housing"},
117
+ {"@type": "Site", "siteType": "animal housing"},
118
+ ],
119
+ "siteDuration": 20,
120
+ "otherSitesDuration": [12, 13, 14],
121
+ },
122
+ 59
123
+ )
124
+
125
+ ]
126
+ )
127
+ def test_duration_in_housing(test_name, cycle, expected_duration):
128
+ assert _duration_in_housing(cycle) == expected_duration
129
+
130
+
131
+ @pytest.mark.parametrize(
132
+ "test_name,cycle,expected_should_run",
133
+ [
134
+ (
135
+ "not complete => no run",
136
+ {"completeness": {"@type": "Completeness", "animalPopulation": False}},
137
+ False
138
+ ),
139
+ (
140
+ "no site or other sites => no run",
141
+ {"completeness": {"@type": "Completeness", "animalPopulation": True}},
142
+ False
143
+ ),
144
+ (
145
+ "no site or other sites with 'animal housing' type => no run",
146
+ {
147
+ "completeness": {"@type": "Completeness", "animalPopulation": True},
148
+ "site": {"@type": "Site", "siteType": "permanent pasture"},
149
+ "otherSites": [{"@type": "Site", "siteType": "pond"}]
150
+ },
151
+ False
152
+ ),
153
+ (
154
+ "no site or other sites with 'animal housing' type and duration => no run",
155
+ {
156
+ "completeness": {"@type": "Completeness", "animalPopulation": True},
157
+ "site": {"@type": "Site", "siteType": "animal housing"},
158
+ "otherSites": [{"@type": "Site", "siteType": "pond"}],
159
+ "siteDuration": ""
160
+ },
161
+ False
162
+ ),
163
+ (
164
+ "no animal values => no run",
165
+ {
166
+ "completeness": {"@type": "Completeness", "animalPopulation": True},
167
+ "site": {"@type": "Site", "siteType": "animal housing"},
168
+ "otherSites": [{"@type": "Site", "siteType": "pond"}],
169
+ "siteDuration": 150,
170
+ "animals": [
171
+ {"value": ""}
172
+ ]
173
+ },
174
+ False
175
+ ),
176
+ (
177
+ "animal values reference period is not 'average' => no run",
178
+ {
179
+ "completeness": {"@type": "Completeness", "animalPopulation": True},
180
+ "site": {"@type": "Site", "siteType": "animal housing"},
181
+ "otherSites": [{"@type": "Site", "siteType": "pond"}],
182
+ "siteDuration": 150,
183
+ "animals": [
184
+ {
185
+ "@type": "Animal",
186
+ "value": 1
187
+ },
188
+ {
189
+ "@type": "Animal",
190
+ "value": 2,
191
+ "referencePeriod": ""
192
+ },
193
+ {
194
+ "@type": "Animal",
195
+ "value": 3,
196
+ "referencePeriod": "start of Cycle"
197
+ },
198
+ ]
199
+ },
200
+ False
201
+ ),
202
+ (
203
+ "missing otherSitesDuration => no run",
204
+ {
205
+ "completeness": {"@type": "Completeness", "animalPopulation": True},
206
+ "site": {"@type": "Site", "siteType": "animal housing"},
207
+ "otherSites": [{"@type": "Site", "siteType": "pond"}],
208
+ "siteDuration": 150,
209
+ "animals": [
210
+ {
211
+ "@type": "Animal",
212
+ "value": 2,
213
+ "referencePeriod": ""
214
+ },
215
+ {
216
+ "@type": "Animal",
217
+ "value": 3,
218
+ "referencePeriod": "average"
219
+ },
220
+ ]
221
+ },
222
+ False
223
+ ),
224
+ (
225
+ "all requirements met with otherSites => run",
226
+ {
227
+ "completeness": {"@type": "Completeness", "animalPopulation": True},
228
+ "site": {"@type": "Site", "siteType": "pond"},
229
+ "siteDuration": "",
230
+ "otherSites": [{"@type": "Site", "siteType": "animal housing"}],
231
+ "otherSitesDuration": [200],
232
+ "animals": [
233
+ {
234
+ "@type": "Animal",
235
+ "value": 2,
236
+ "referencePeriod": ""
237
+ },
238
+ {
239
+ "@type": "Animal",
240
+ "value": 3,
241
+ "referencePeriod": "average"
242
+ },
243
+ ]
244
+ },
245
+ True
246
+ ),
247
+
248
+ ]
249
+ )
250
+ def test_should_run_animal(test_name, cycle, expected_should_run):
251
+ should_run, *args = should_run_animal(cycle, 'model', 'term', 'tier')
252
+ assert should_run == expected_should_run, test_name
@@ -123,3 +123,12 @@ def test_run_liveAnimal_sheepLamb(mock_download_hestia, *args):
123
123
  }
124
124
  value = run(cycle)
125
125
  assert value == expected
126
+
127
+
128
+ @patch(f"{class_path}._new_property", side_effect=fake_new_property)
129
+ def test_run_liveAninal_missing_term_id(*args):
130
+ with open(f"{fixtures_folder}/liveAnimal/missing-fao-term-id/cycle.jsonld", encoding='utf-8') as f:
131
+ cycle = json.load(f)
132
+
133
+ value = run(cycle)
134
+ assert value == []
@@ -2,7 +2,7 @@ import json
2
2
  from unittest.mock import patch
3
3
 
4
4
  import pytest
5
- from hestia_earth.schema import TermTermType
5
+ from hestia_earth.schema import TermTermType, SiteSiteType
6
6
 
7
7
  from hestia_earth.models.site.management import MODEL, MODEL_KEY, run, _should_run
8
8
  from hestia_earth.models.utils.blank_node import condense_nodes
@@ -17,8 +17,17 @@ TERM_BY_ID = {
17
17
  'oatPlant': {'@type': 'Term', '@id': 'oatPlant', 'termType': TermTermType.LANDCOVER.value},
18
18
  'agatiTree': {'@type': 'Term', '@id': 'agatiTree', 'termType': TermTermType.LANDCOVER.value},
19
19
  'wildGarlicPlant': {'@type': 'Term', '@id': 'wildGarlicPlant', 'termType': TermTermType.LANDCOVER.value},
20
+ 'animalHousing': {
21
+ "@type": "Term",
22
+ "@id": "animalHousing",
23
+ "name": "Animal housing",
24
+ "termType": TermTermType.LANDCOVER.value,
25
+ "units": "% area"
26
+ }
20
27
  }
21
28
 
29
+ LAND_COVER_TERM_BY_SITE_TYPE = {SiteSiteType.ANIMAL_HOUSING.value: "animalHousing"}
30
+
22
31
 
23
32
  def lookup_side_effect(*args, **kwargs):
24
33
  # Values taken from real lookups.
@@ -233,7 +242,7 @@ def test_should_run(mock_related_cycles, *args):
233
242
  should_run, *args = _should_run({})
234
243
  assert should_run is True
235
244
 
236
- # with relevant product => run
245
+ # with relevant product, blank site_type => no run
237
246
  mock_related_cycles.return_value = [
238
247
  {
239
248
  "products": [
@@ -253,6 +262,28 @@ def test_should_run(mock_related_cycles, *args):
253
262
  }
254
263
  ]
255
264
  should_run, *args = _should_run({})
265
+ assert should_run is False
266
+
267
+ # with relevant product and site_type => run
268
+ mock_related_cycles.return_value = [
269
+ {
270
+ "products": [
271
+ {
272
+ "term": {
273
+ "termType": TermTermType.CROP.value,
274
+ "@id": "genericCropProduct"
275
+ },
276
+ "value": [51],
277
+ "startDate": "2001",
278
+ "endDate": "2002",
279
+ "properties": {"test": "properties"}
280
+ }
281
+ ],
282
+ "startDate": "2021",
283
+ "endDate": "2022"
284
+ }
285
+ ]
286
+ should_run, *args = _should_run({"siteType": "cropland"})
256
287
  assert should_run is True
257
288
  assert args[0] == [{
258
289
  'term': TERM_BY_ID['genericCropPlant'],
@@ -266,11 +297,12 @@ def test_should_run(mock_related_cycles, *args):
266
297
  @pytest.mark.parametrize(
267
298
  "test_name,fixture_path",
268
299
  [
300
+ ("Products and practices", f"{fixtures_folder}"),
269
301
  ("Example 1", f"{fixtures_folder}/inputs/example1"),
270
302
  ("Example 2", f"{fixtures_folder}/inputs/example2"),
271
303
  ("Example 3", f"{fixtures_folder}/inputs/example3"),
272
304
  ("Example 4", f"{fixtures_folder}/inputs/example4"),
273
- ("Condense Nodes", f"{fixtures_folder}/inputs/condense_nodes")
305
+ ("Condense Nodes", f"{fixtures_folder}/inputs/condense_nodes"),
274
306
  # Expected:
275
307
  # - appleTree (81) x 3 condenses 2020-03-01 to 2021-02-15
276
308
  # - animalManureUsed (true) x 2 condenses 2001-04-01 to 2001-12-31
@@ -282,18 +314,34 @@ def test_should_run(mock_related_cycles, *args):
282
314
  # - sassafrasTree (86) x 2 condenses 2001-01-01 to 2004-12-31
283
315
  # - bananaPlant (87) does not condense [non-consecutive years]
284
316
  # - durianTree (89) does not condense [dates overwritten See 808]
317
+ ("Site Type", f"{fixtures_folder}/inputs/site_type")
285
318
  ]
286
319
  )
287
- @patch(f"{CLASS_PATH}.download_hestia", side_effect=lambda id, *args: TERM_BY_ID[id])
320
+ @patch(
321
+ f"{CLASS_PATH}.get_landCover_term_id_from_site_type",
322
+ side_effect=lambda site_type: LAND_COVER_TERM_BY_SITE_TYPE[site_type]
323
+ )
324
+ @patch(f"{CLASS_PATH}.download_hestia", side_effect=lambda term_id, *args: TERM_BY_ID[term_id])
288
325
  @patch(f"{CLASS_PATH}.related_cycles")
289
326
  @patch(f"{CLASS_PATH}._get_lookup_with_debug", side_effect=lookup_side_effect)
290
- def test_run(mock_get_lookup_with_debug, mock_related_cycles, mock_download, test_name, fixture_path):
327
+ def test_run(
328
+ mock_get_lookup_with_debug,
329
+ mock_related_cycles,
330
+ mock_download,
331
+ mock_land_cover_lookup,
332
+ test_name,
333
+ fixture_path
334
+ ):
291
335
  with open(f"{fixture_path}/cycles.jsonld", encoding='utf-8') as f:
292
336
  cycles = json.load(f)
293
337
  mock_related_cycles.return_value = cycles
294
338
 
295
- with open(f"{fixtures_folder}/site.jsonld", encoding='utf-8') as f:
296
- site = json.load(f)
339
+ try:
340
+ with open(f"{fixture_path}/site.jsonld", encoding='utf-8') as f:
341
+ site = json.load(f)
342
+ except FileNotFoundError:
343
+ with open(f"{fixtures_folder}/site.jsonld", encoding='utf-8') as f:
344
+ site = json.load(f)
297
345
 
298
346
  with open(f"{fixture_path}/result.jsonld", encoding='utf-8') as f:
299
347
  expected = json.load(f)