hestia-earth-models 0.64.10__py3-none-any.whl → 0.64.12__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 (71) hide show
  1. hestia_earth/models/cml2001Baseline/eutrophicationPotentialExcludingFate.py +2 -2
  2. hestia_earth/models/cml2001Baseline/terrestrialAcidificationPotentialIncludingFateAverageEurope.py +2 -2
  3. hestia_earth/models/cml2001NonBaseline/eutrophicationPotentialIncludingFateAverageEurope.py +2 -2
  4. hestia_earth/models/cml2001NonBaseline/terrestrialAcidificationPotentialExcludingFate.py +2 -2
  5. hestia_earth/models/cycle/completeness/cropResidue.py +15 -10
  6. hestia_earth/models/cycle/completeness/freshForage.py +60 -0
  7. hestia_earth/models/cycle/concentrateFeed.py +31 -19
  8. hestia_earth/models/edip2003/ozoneDepletionPotential.py +2 -2
  9. hestia_earth/models/fantkeEtAl2016/damageToHumanHealthParticulateMatterFormation.py +7 -17
  10. hestia_earth/models/faostat2018/utils.py +72 -12
  11. hestia_earth/models/hestia/__init__.py +13 -0
  12. hestia_earth/models/hestia/landCover.py +725 -0
  13. hestia_earth/models/ipcc2013ExcludingFeedbacks/gwp100.py +2 -2
  14. hestia_earth/models/ipcc2013IncludingFeedbacks/gwp100.py +2 -2
  15. hestia_earth/models/ipcc2019/animal/fatContent.py +1 -1
  16. hestia_earth/models/ipcc2019/animal/milkYieldPerAnimal.py +91 -0
  17. hestia_earth/models/ipcc2019/animal/trueProteinContent.py +1 -1
  18. hestia_earth/models/ipcc2019/animal/utils.py +17 -12
  19. hestia_earth/models/ipcc2019/co2ToAirAboveGroundBiomassStockChange.py +8 -4
  20. hestia_earth/models/ipcc2019/co2ToAirBelowGroundBiomassStockChange.py +7 -3
  21. hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +45 -3
  22. hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChange.py +7 -3
  23. hestia_earth/models/ipcc2021/gwp100.py +2 -2
  24. hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsClimateChange.py +2 -2
  25. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthClimateChange.py +2 -2
  26. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthStratosphericOzoneDepletion.py +2 -2
  27. hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsClimateChange.py +2 -2
  28. hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsClimateChange.py +2 -2
  29. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthClimateChange.py +2 -2
  30. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthStratosphericOzoneDepletion.py +2 -2
  31. hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsClimateChange.py +2 -2
  32. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthClimateChange.py +2 -2
  33. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthStratosphericOzoneDepletion.py +2 -2
  34. hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsClimateChange.py +2 -2
  35. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthClimateChange.py +2 -2
  36. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthStratosphericOzoneDepletion.py +2 -2
  37. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsClimateChange.py +2 -2
  38. hestia_earth/models/mocking/search-results.json +335 -335
  39. hestia_earth/models/recipe2016Egalitarian/ecosystemDamageOzoneFormation.py +2 -2
  40. hestia_earth/models/recipe2016Egalitarian/freshwaterEutrophicationPotential.py +2 -2
  41. hestia_earth/models/recipe2016Egalitarian/humanDamageOzoneFormation.py +2 -2
  42. hestia_earth/models/recipe2016Egalitarian/marineEutrophicationPotential.py +2 -2
  43. hestia_earth/models/recipe2016Egalitarian/ozoneDepletionPotential.py +2 -2
  44. hestia_earth/models/recipe2016Egalitarian/terrestrialAcidificationPotential.py +2 -2
  45. hestia_earth/models/recipe2016Hierarchist/ecosystemDamageOzoneFormation.py +2 -2
  46. hestia_earth/models/recipe2016Hierarchist/freshwaterEutrophicationPotential.py +2 -2
  47. hestia_earth/models/recipe2016Hierarchist/humanDamageOzoneFormation.py +2 -2
  48. hestia_earth/models/recipe2016Hierarchist/marineEutrophicationPotential.py +2 -2
  49. hestia_earth/models/recipe2016Hierarchist/ozoneDepletionPotential.py +2 -2
  50. hestia_earth/models/recipe2016Hierarchist/terrestrialAcidificationPotential.py +2 -2
  51. hestia_earth/models/recipe2016Individualist/ecosystemDamageOzoneFormation.py +2 -2
  52. hestia_earth/models/recipe2016Individualist/freshwaterEutrophicationPotential.py +2 -2
  53. hestia_earth/models/recipe2016Individualist/humanDamageOzoneFormation.py +2 -2
  54. hestia_earth/models/recipe2016Individualist/marineEutrophicationPotential.py +2 -2
  55. hestia_earth/models/recipe2016Individualist/ozoneDepletionPotential.py +2 -2
  56. hestia_earth/models/recipe2016Individualist/terrestrialAcidificationPotential.py +2 -2
  57. hestia_earth/models/utils/impact_assessment.py +18 -8
  58. hestia_earth/models/utils/lookup.py +2 -1
  59. hestia_earth/models/version.py +1 -1
  60. {hestia_earth_models-0.64.10.dist-info → hestia_earth_models-0.64.12.dist-info}/METADATA +2 -2
  61. {hestia_earth_models-0.64.10.dist-info → hestia_earth_models-0.64.12.dist-info}/RECORD +71 -62
  62. tests/models/cycle/completeness/test_freshForage.py +21 -0
  63. tests/models/faostat2018/test_faostat_utils.py +84 -0
  64. tests/models/hestia/__init__.py +0 -0
  65. tests/models/hestia/test_landCover.py +209 -0
  66. tests/models/ipcc2019/animal/test_milkYieldPerAnimal.py +21 -0
  67. tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChange.py +48 -1
  68. tests/models/utils/test_impact_assessment.py +3 -3
  69. {hestia_earth_models-0.64.10.dist-info → hestia_earth_models-0.64.12.dist-info}/LICENSE +0 -0
  70. {hestia_earth_models-0.64.10.dist-info → hestia_earth_models-0.64.12.dist-info}/WHEEL +0 -0
  71. {hestia_earth_models-0.64.10.dist-info → hestia_earth_models-0.64.12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,209 @@
1
+ import csv
2
+ import json
3
+ import numpy as np
4
+ import pytest
5
+ from unittest.mock import patch
6
+
7
+ from tests.utils import fixtures_path
8
+ from hestia_earth.models.faostat2018.utils import MODEL as FAOSTAT_MODEL
9
+ from hestia_earth.models.hestia.landCover import (
10
+ MODEL, MODEL_KEY, get_changes, _estimate_maximum_forest_change,
11
+ run, site_area_sum_to_100, _get_sums_of_crop_expansion
12
+ )
13
+
14
+ CLASS_PATH = f"hestia_earth.models.{MODEL}.{MODEL_KEY}"
15
+ fixtures_folder = f"{fixtures_path}/{MODEL}/{MODEL_KEY}"
16
+
17
+ FAOSTAT_CLASS_PATH = f"hestia_earth.models.{FAOSTAT_MODEL}.utils"
18
+ faostat_fixtures_folder = f"{fixtures_path}/{FAOSTAT_MODEL}/utils"
19
+
20
+ BRAZIL_SITE = {
21
+ "@type": "Site",
22
+ "id": "Brazil-example",
23
+ "country": {
24
+ "name": "Brazil",
25
+ "type": "Term"
26
+ },
27
+ "siteType": "cropland",
28
+ "management": [
29
+ {
30
+ "term": {
31
+ "@id": "maizePlant",
32
+ "name": "Maize plant",
33
+ "type": "Term",
34
+ "termType": "landCover"
35
+ },
36
+ "value": 100,
37
+ "startDate": "2010-01-01",
38
+ "endDate": "2010-12-31",
39
+ "type": "Management"
40
+ }
41
+ ]
42
+ }
43
+
44
+
45
+ def recfromcsv_mod(filename, **kwargs):
46
+ def rewrite_csv_as_tab(csv_name):
47
+ with open(csv_name, newline='') as fp:
48
+ for row in csv.reader(fp, delimiter=","):
49
+ yield "\t".join(row)
50
+ return np.recfromcsv(
51
+ rewrite_csv_as_tab(filename), delimiter="\t", encoding=None, **kwargs)
52
+
53
+
54
+ def _download_fixture(filepath: str):
55
+ return recfromcsv_mod(filename=filepath)
56
+
57
+
58
+ @patch(f"{FAOSTAT_CLASS_PATH}.download_lookup")
59
+ def test_get_changes(mock_lookup):
60
+ mock_lookup.return_value = _download_fixture(f"{faostat_fixtures_folder}/gadm-afg.csv")
61
+ result = get_changes(
62
+ country_id="GADM-AFG",
63
+ end_year=2010
64
+ )
65
+ assert (
66
+ result == {
67
+ "Arable land": -117.0,
68
+ "Cropland": -123.0,
69
+ "Forest land": 0,
70
+ "Other land": 123.0,
71
+ "Land area": 0,
72
+ "Permanent crops": -6.0,
73
+ "Permanent meadows and pastures": 0,
74
+ "Total agricultural change": -123.0
75
+ }
76
+ )
77
+
78
+
79
+ @pytest.mark.parametrize(
80
+ "description,inputs,expected_output",
81
+ [
82
+ (
83
+ "Annual cropland gain from forest",
84
+ {
85
+ "forest_change": -1000,
86
+ "total_cropland_change": 1000,
87
+ "pasture_change": 0,
88
+ "total_agricultural_change": 1000
89
+ },
90
+ -1000
91
+ ),
92
+ (
93
+ "Pasture gain from forest",
94
+ {
95
+ "forest_change": -1000,
96
+ "total_cropland_change": 0,
97
+ "pasture_change": 1000,
98
+ "total_agricultural_change": 1000
99
+ },
100
+ -1000
101
+ ),
102
+ (
103
+ "Brazil",
104
+ {
105
+ "forest_change": -77317,
106
+ "total_cropland_change": 5201,
107
+ "pasture_change": -8267,
108
+ "total_agricultural_change": -3066
109
+ },
110
+ -5201
111
+ ),
112
+ (
113
+ "Argentina",
114
+ {
115
+ "forest_change": -4990,
116
+ "total_cropland_change": 11408,
117
+ "pasture_change": -12705,
118
+ "total_agricultural_change": -1297
119
+ },
120
+ -4990
121
+ ),
122
+ (
123
+ "Madagascar",
124
+ {
125
+ "forest_change": -1131,
126
+ "total_cropland_change": 275,
127
+ "pasture_change": 4295,
128
+ "total_agricultural_change": 4570
129
+ },
130
+ -1131
131
+ ),
132
+ (
133
+ "Afforestation",
134
+ {
135
+ "forest_change": 100,
136
+ "total_cropland_change": -1000,
137
+ "pasture_change": -50,
138
+ "total_agricultural_change": -1000
139
+ },
140
+ 0
141
+ ),
142
+ (
143
+ "Pasture gain more than forest loss",
144
+ {
145
+ "forest_change": -49,
146
+ "total_cropland_change": -1000,
147
+ "pasture_change": 50,
148
+ "total_agricultural_change": -950
149
+ },
150
+ -49
151
+ )
152
+ ]
153
+ )
154
+ def test_estimate_maximum_forest_change(description, inputs, expected_output):
155
+ assert _estimate_maximum_forest_change(**inputs) == expected_output, description
156
+
157
+
158
+ @pytest.mark.parametrize(
159
+ "description,inputs,expected_result",
160
+ [
161
+ ("All zeros, OK", {"a": 0, "b": 0, "c": 0.0, "d": 0.0}, True),
162
+ ("Exactly 1, OK", {"a": 0.1, "b": 0.5, "c": 0.4, "d": 0.0}, True),
163
+ ("Almost 1, OK", {"a": 0.1, "b": 0.5, "c": 0.4, "d": 0.01}, True),
164
+ ("Less than 1, Fail", {"a": 0.1, "b": 0, "c": 0.0, "d": 0.65}, False),
165
+ ("More than 1, Fail", {"a": 0.15, "b": 0.7, "c": 0.0, "d": 0.65}, False),
166
+ ]
167
+ )
168
+ def test_check_sum_of_percentages(description, inputs, expected_result):
169
+ assert site_area_sum_to_100(dict_of_percentages=inputs) == expected_result
170
+
171
+
172
+ def test_get_sums_of_crop_expansion():
173
+ result = _get_sums_of_crop_expansion(
174
+ country_id="GADM-AFG",
175
+ year=2010,
176
+ include_negatives=True
177
+ )
178
+ assert result == (753973.3, 18354.0)
179
+
180
+ result = _get_sums_of_crop_expansion(
181
+ country_id="GADM-AFG",
182
+ year=2010,
183
+ include_negatives=False
184
+ )
185
+ assert result == (940270.0, 28139.0)
186
+
187
+
188
+ @pytest.mark.parametrize(
189
+ "subfolder",
190
+ [
191
+ "albania_example",
192
+ "argentina_example",
193
+ "armenia_example",
194
+ "brazil_example",
195
+ "zimbabwe_example",
196
+ "brazil_empty_example",
197
+ "gbr_example"
198
+ ]
199
+ )
200
+ def test_run(subfolder):
201
+ folder = f"{fixtures_folder}/{subfolder}"
202
+ with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
203
+ site = json.load(f)
204
+
205
+ with open(f"{folder}/result.jsonld", encoding='utf-8') as f:
206
+ expected = json.load(f)
207
+
208
+ result = run(site)
209
+ assert result == expected
@@ -0,0 +1,21 @@
1
+ from unittest.mock import patch
2
+ import json
3
+ from tests.utils import fixtures_path, fake_new_practice
4
+
5
+ from hestia_earth.models.ipcc2019 import MODEL
6
+ from hestia_earth.models.ipcc2019.animal.milkYieldPerAnimal import MODEL_KEY, run
7
+
8
+ class_path = f"hestia_earth.models.{MODEL}.animal.{MODEL_KEY}"
9
+ fixtures_folder = f"{fixtures_path}/{MODEL}/animal/{MODEL_KEY}"
10
+
11
+
12
+ @patch(f"{class_path}._new_practice", side_effect=fake_new_practice)
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
@@ -10,8 +10,34 @@ from tests.utils import fake_new_emission, fixtures_path, order_list
10
10
 
11
11
  class_path = f"hestia_earth.models.{MODEL}.co2ToAirSoilOrganicCarbonStockChange"
12
12
  utils_path = f"hestia_earth.models.{MODEL}.co2ToAirCarbonStockChange_utils"
13
+ soc_utils_path = f"hestia_earth.models.{MODEL}.organicCarbonPerHa_utils"
14
+ term_folder = "hestia_earth.models.utils.term"
13
15
  fixtures_folder = f"{fixtures_path}/{MODEL}/co2ToAirSoilOrganicCarbonStockChange"
14
16
 
17
+
18
+ IRRIGATED_TERM_IDS = [
19
+ "rainfedDeepWater",
20
+ "rainfedDeepWaterWaterDepth100Cm",
21
+ "rainfedDeepWaterWaterDepth50100Cm",
22
+ "irrigatedTypeUnspecified",
23
+ "irrigatedCenterPivotIrrigation",
24
+ "irrigatedContinuouslyFlooded",
25
+ "irrigatedDripIrrigation",
26
+ "irrigatedFurrowIrrigation",
27
+ "irrigatedLateralMoveIrrigation",
28
+ "irrigatedLocalizedIrrigation",
29
+ "irrigatedManualIrrigation",
30
+ "irrigatedSurfaceIrrigationMultipleDrainagePeriods",
31
+ "irrigatedSurfaceIrrigationSingleDrainagePeriod",
32
+ "irrigatedSprinklerIrrigation",
33
+ "irrigatedSubIrrigation",
34
+ "irrigatedSurfaceIrrigationDrainageRegimeUnspecified"
35
+ ]
36
+
37
+ UPLAND_RICE_LAND_COVER_TERM_IDS = [
38
+ "ricePlantUpland"
39
+ ]
40
+
15
41
  RUN_SCENARIOS = [
16
42
  ("no-overlapping-cycles", 3),
17
43
  ("overlapping-cycles", 4),
@@ -47,7 +73,20 @@ RUN_IDS = [f"{param[0]}, cycle{param[2]}" for param in RUN_PARAMS]
47
73
  @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
48
74
  @patch(f"{utils_path}.related_cycles")
49
75
  @patch(f"{utils_path}._get_site")
50
- def test_run(_get_site_mock, related_cycles_mock, _new_emission_mock, subfolder, num_cycles, cycle_index):
76
+ @patch(f"{soc_utils_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
77
+ @patch(f"{soc_utils_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
78
+ @patch(f"{term_folder}.search")
79
+ def test_run(
80
+ search_mock,
81
+ get_irrigated_terms_mock,
82
+ get_upland_rice_land_cover_terms_mock,
83
+ _get_site_mock,
84
+ related_cycles_mock,
85
+ _new_emission_mock,
86
+ subfolder,
87
+ num_cycles,
88
+ cycle_index
89
+ ):
51
90
  """
52
91
  Test `run` function for each cycle in each scenario.
53
92
  """
@@ -63,6 +102,14 @@ def test_run(_get_site_mock, related_cycles_mock, _new_emission_mock, subfolder,
63
102
  related_cycles_mock.return_value = cycles
64
103
 
65
104
  result = run(cycle)
105
+
106
+ # Ensure that API calls to retrieve term IDs are properly cached.
107
+ get_irrigated_terms_mock.call_count <= 1
108
+ get_upland_rice_land_cover_terms_mock.call_count <= 1
109
+
110
+ # Ensure that the property and term utils are properly mocked.
111
+ search_mock.assert_not_called()
112
+
66
113
  assert order_list(result) == order_list(expected)
67
114
 
68
115
 
@@ -1,7 +1,7 @@
1
- from hestia_earth.models.utils.impact_assessment import impact_lookup_value, get_region_id
1
+ from hestia_earth.models.utils.impact_assessment import impact_emission_lookup_value, get_region_id
2
2
 
3
3
 
4
- def test_impact_lookup_value():
4
+ def test_impact_emission_lookup_value():
5
5
  impact = {
6
6
  'emissionsResourceUse': [
7
7
  {
@@ -14,7 +14,7 @@ def test_impact_lookup_value():
14
14
  ]
15
15
  }
16
16
  # multiplies the emissionsResourceUse values with a coefficient
17
- assert impact_lookup_value('', '', impact, 'co2EqGwp100ExcludingClimate-CarbonFeedbacksIpcc2013') == 2800
17
+ assert impact_emission_lookup_value('', '', impact, 'co2EqGwp100ExcludingClimate-CarbonFeedbacksIpcc2013') == 2800
18
18
 
19
19
 
20
20
  def test_get_region_id():