hestia-earth-models 0.64.9__py3-none-any.whl → 0.64.10__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 (80) hide show
  1. hestia_earth/models/cml2001Baseline/abioticResourceDepletionFossilFuels.py +175 -0
  2. hestia_earth/models/cml2001Baseline/abioticResourceDepletionMineralsAndMetals.py +136 -0
  3. hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandTransformation.py +2 -2
  4. hestia_earth/models/ipcc2019/aboveGroundBiomass.py +31 -243
  5. hestia_earth/models/ipcc2019/belowGroundBiomass.py +529 -0
  6. hestia_earth/models/ipcc2019/biomass_utils.py +406 -0
  7. hestia_earth/models/ipcc2019/{co2ToAirAboveGroundBiomassStockChangeLandUseChange.py → co2ToAirAboveGroundBiomassStockChange.py} +19 -7
  8. hestia_earth/models/ipcc2019/{co2ToAirBelowGroundBiomassStockChangeLandUseChange.py → co2ToAirBelowGroundBiomassStockChange.py} +19 -7
  9. hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +402 -73
  10. hestia_earth/models/ipcc2019/{co2ToAirSoilOrganicCarbonStockChangeManagementChange.py → co2ToAirSoilOrganicCarbonStockChange.py} +20 -8
  11. hestia_earth/models/ipcc2019/organicCarbonPerHa.py +3 -1
  12. hestia_earth/models/ipcc2019/pastureGrass_utils.py +6 -7
  13. hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
  14. hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsWaterStress.py +2 -2
  15. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthParticulateMatterFormation.py +2 -2
  16. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
  17. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthWaterStress.py +2 -2
  18. hestia_earth/models/lcImpactAllEffects100Years/damageToMarineEcosystemsMarineEutrophication.py +2 -2
  19. hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
  20. hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
  21. hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
  22. hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsWaterStress.py +2 -2
  23. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthParticulateMatterFormation.py +2 -2
  24. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
  25. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
  26. hestia_earth/models/lcImpactAllEffectsInfinite/damageToMarineEcosystemsMarineEutrophication.py +2 -2
  27. hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
  28. hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
  29. hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
  30. hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsWaterStress.py +2 -2
  31. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthParticulateMatterFormation.py +2 -2
  32. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
  33. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthWaterStress.py +2 -2
  34. hestia_earth/models/lcImpactCertainEffects100Years/damageToMarineEcosystemsMarineEutrophication.py +2 -2
  35. hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
  36. hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
  37. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
  38. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsWaterStress.py +2 -2
  39. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthParticulateMatterFormation.py +2 -2
  40. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
  41. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
  42. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToMarineEcosystemsMarineEutrophication.py +2 -2
  43. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
  44. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
  45. hestia_earth/models/mocking/build_mock_search.py +44 -0
  46. hestia_earth/models/mocking/mock_search.py +8 -49
  47. hestia_earth/models/mocking/search-results.json +3075 -578
  48. hestia_earth/models/poschEtAl2008/terrestrialAcidificationPotentialAccumulatedExceedance.py +3 -3
  49. hestia_earth/models/poschEtAl2008/terrestrialEutrophicationPotentialAccumulatedExceedance.py +3 -3
  50. hestia_earth/models/preload_requests.py +1 -1
  51. hestia_earth/models/schmidt2007/utils.py +13 -4
  52. hestia_earth/models/utils/blank_node.py +73 -3
  53. hestia_earth/models/utils/constant.py +8 -1
  54. hestia_earth/models/utils/cycle.py +10 -13
  55. hestia_earth/models/utils/fuel.py +1 -1
  56. hestia_earth/models/utils/impact_assessment.py +31 -16
  57. hestia_earth/models/utils/lookup.py +36 -7
  58. hestia_earth/models/utils/pesticideAI.py +1 -1
  59. hestia_earth/models/utils/property.py +11 -4
  60. hestia_earth/models/utils/term.py +15 -8
  61. hestia_earth/models/version.py +1 -1
  62. {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/METADATA +2 -2
  63. {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/RECORD +78 -71
  64. {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/WHEEL +1 -1
  65. tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +196 -0
  66. tests/models/cml2001Baseline/test_abioticResourceDepletionMineralsAndMetals.py +124 -0
  67. tests/models/edip2003/test_ozoneDepletionPotential.py +1 -13
  68. tests/models/environmentalFootprintV3/test_soilQualityIndexLandTransformation.py +1 -2
  69. tests/models/impact_assessment/test_emissions.py +1 -0
  70. tests/models/ipcc2019/test_aboveGroundBiomass.py +27 -63
  71. tests/models/ipcc2019/test_belowGroundBiomass.py +146 -0
  72. tests/models/ipcc2019/test_biomass_utils.py +115 -0
  73. tests/models/ipcc2019/{test_co2ToAirAboveGroundBiomassStockChangeLandUseChange.py → test_co2ToAirAboveGroundBiomassStockChange.py} +5 -5
  74. tests/models/ipcc2019/{test_co2ToAirBelowGroundBiomassStockChangeLandUseChange.py → test_co2ToAirBelowGroundBiomassStockChange.py} +5 -5
  75. tests/models/ipcc2019/{test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py → test_co2ToAirSoilOrganicCarbonStockChange.py} +5 -5
  76. tests/models/ipcc2021/test_gwp100.py +2 -2
  77. hestia_earth/models/ipcc2019/aboveGroundBiomass_utils.py +0 -180
  78. tests/models/ipcc2019/test_aboveGroundBiomass_utils.py +0 -92
  79. {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/LICENSE +0 -0
  80. {hestia_earth_models-0.64.9.dist-info → hestia_earth_models-0.64.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,124 @@
1
+ import json
2
+ from unittest.mock import patch
3
+
4
+ from pytest import mark
5
+
6
+ from hestia_earth.models.cml2001Baseline.abioticResourceDepletionMineralsAndMetals import MODEL, TERM_ID, run, \
7
+ _should_run
8
+ from tests.utils import fixtures_path, fake_new_indicator
9
+
10
+ class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
11
+ fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
12
+
13
+
14
+ def fake_rounded_indicator(value: float):
15
+ indicator = fake_new_indicator(TERM_ID, MODEL)
16
+ indicator['value'] = round(value, 7)
17
+ return indicator
18
+
19
+
20
+ iodine_input = {"@id": "iodineMaterial", "termType": "material", "units": "kg"}
21
+ boron_input = {"@id": "boron", "termType": "soilAmendment", "units": "kg B"}
22
+ tellurium_input = {"@id": "CAS-13494-80-9", "termType": "otherInorganicChemical", "units": "kg"}
23
+ input_no_cf_material = {"@id": "cork", "termType": "material", "units": "kg"}
24
+
25
+ wrong_indicator = {'value': [1],
26
+ 'term': {'@id': 'landTransformationFromCropland20YearAverageDuringCycle', 'termType': 'resourceUse'},
27
+ 'inputs': [iodine_input]}
28
+
29
+ indicator_no_inputs = {'value': 3,
30
+ 'term': {'@id': 'resourceUseMineralsAndMetalsInputsProduction', 'termType': 'resourceUse'},
31
+ 'inputs': []}
32
+ indicator_2_inputs = {
33
+ 'value': 3, 'term': {'@id': 'resourceUseMineralsAndMetalsInputsProduction', 'termType': 'resourceUse'},
34
+ 'inputs': [boron_input, iodine_input]
35
+ }
36
+
37
+ indicator_no_unit = {
38
+ 'value': 3, 'term': {'@id': 'resourceUseMineralsAndMetalsInputsProduction', 'termType': 'resourceUse'},
39
+ 'inputs': [{"@id": "iodineMaterial", "termType": "material", }],
40
+ }
41
+
42
+ indicator_wrong_unit = {
43
+ 'value': 3, 'term': {'@id': 'resourceUseMineralsAndMetalsInputsProduction', 'termType': 'resourceUse'},
44
+ 'inputs': [{"@id": "iodineMaterial", "termType": "material", "units": "Mj"}],
45
+ }
46
+
47
+ indicator_no_cf_material = {
48
+ 'value': 3, 'term': {'@id': 'resourceUseMineralsAndMetalsInputsProduction', 'termType': 'resourceUse'},
49
+ 'inputs': [input_no_cf_material]
50
+ }
51
+
52
+ indicator_iodine = {
53
+ 'value': [1],
54
+ 'term': {'@id': 'resourceUseMineralsAndMetalsInputsProduction', 'termType': 'resourceUse'},
55
+ 'inputs': [iodine_input]
56
+ }
57
+
58
+ indicator_boron = {
59
+ 'value': 2,
60
+ 'term': {'@id': 'resourceUseMineralsAndMetalsInputsProduction', 'termType': 'resourceUse'},
61
+ 'inputs': [boron_input]
62
+ }
63
+
64
+ indicator_tellurium = {
65
+ 'value': 2,
66
+ 'term': {'@id': 'resourceUseMineralsAndMetalsInputsProduction', 'termType': 'resourceUse'},
67
+ 'inputs': [tellurium_input]
68
+ }
69
+
70
+
71
+ @mark.parametrize(
72
+ "resources, expected, num_inputs",
73
+ [
74
+ ([], True, 0),
75
+ ([wrong_indicator], True, 0),
76
+ ([indicator_no_inputs], False, 0),
77
+ ([indicator_2_inputs], False, 0),
78
+ ([indicator_no_unit], False, 0),
79
+ ([indicator_wrong_unit], False, 0),
80
+ ([indicator_no_cf_material], True, 0),
81
+ ([indicator_iodine], True, 1),
82
+ ([indicator_boron], True, 1),
83
+ ([indicator_tellurium], True, 1),
84
+ ([indicator_iodine, indicator_no_cf_material], True, 1),
85
+ ],
86
+ ids=["No indicators", "wrong indicator", "indicator no inputs", "indicator 2 inputs", "missing unit", "wrong unit",
87
+ "material with no cf", "good input material", "good input soilAmendment", "good input otherInorganicChemical",
88
+ "one good input"]
89
+ )
90
+ def test_should_run(resources, expected, num_inputs):
91
+ with open(f"{fixtures_folder}/impactassessment.jsonld", encoding='utf-8') as f:
92
+ impactassessment = json.load(f)
93
+
94
+ impactassessment['emissionsResourceUse'] = resources
95
+
96
+ should_run, grouped_inputs = _should_run(impactassessment)
97
+ assert should_run is expected
98
+ assert len(grouped_inputs) == num_inputs
99
+
100
+
101
+ @patch(f"{class_path}._indicator", side_effect=fake_rounded_indicator)
102
+ def test_run(*args):
103
+ with open(f"{fixtures_folder}/impactassessment.jsonld", encoding='utf-8') as f:
104
+ impactassessment = json.load(f)
105
+
106
+ with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
107
+ expected = json.load(f)
108
+
109
+ value = run(impactassessment)
110
+ assert value == expected
111
+
112
+
113
+ @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
114
+ def test_run_no_emissions(*args):
115
+ """
116
+ Impact assessment with no emissions should return a indicator of 0
117
+ """
118
+ with open(f"{fixtures_folder}/impactassessment.jsonld", encoding='utf-8') as f:
119
+ impactassessment = json.load(f)
120
+
121
+ del impactassessment['emissionsResourceUse']
122
+
123
+ value = run(impactassessment)
124
+ assert value['value'] == 0
@@ -1,7 +1,6 @@
1
1
  from unittest.mock import patch
2
2
  import json
3
3
 
4
- from hestia_earth.models.utils.lookup import factor_value
5
4
  from tests.utils import fixtures_path, fake_new_indicator
6
5
 
7
6
  from hestia_earth.models.edip2003.ozoneDepletionPotential import MODEL, TERM_ID, run
@@ -32,15 +31,4 @@ def test_run_empty_input(*args):
32
31
  impactassessment = json.load(f)
33
32
 
34
33
  result = run(impactassessment)
35
- assert result['value'] is None
36
-
37
-
38
- def test_known_ozone_depletion_lookup_value(*args):
39
- lookup_result = factor_value(
40
- 'edip2003', 'ozoneDepletionPotential', 'emission.csv', 'ozoneDepletionPotential')(
41
- data={
42
- '@type': 'Emission',
43
- 'term': {'@type': 'Term', '@id': '112TrichlorotrifluoroethaneToAirInputsProduction'},
44
- 'value': [1],
45
- })
46
- assert lookup_result == 0.81
34
+ assert result['value'] == 0
@@ -100,8 +100,7 @@ good_during_cycle_indicator_from_forest_to_forest = {
100
100
  "Multiple good indicators => run, 2 dict",
101
101
  ]
102
102
  )
103
- @patch(f"{class_path}.download_all_land_cover_terms",
104
- return_value=[{'@id': 'cropland'}, {'@id': 'seaOrOcean'}, {'@id': 'forest'}])
103
+ @patch(f"{class_path}.get_land_cover_terms", return_value=['cropland', 'seaOrOcean', 'forest'])
105
104
  def test_should_run(mock_download, resources, expected, num_inputs):
106
105
  with open(f"{fixtures_folder}/multipleTransformations/impact-assessment.jsonld", encoding='utf-8') as f:
107
106
  impact = json.load(f)
@@ -28,4 +28,5 @@ def test_run(*args):
28
28
  expected = json.load(f)
29
29
 
30
30
  value = run(impact)
31
+ print(json.dumps(value))
31
32
  assert value == expected
@@ -4,15 +4,13 @@ from os.path import isfile
4
4
  from pytest import mark
5
5
  from unittest.mock import MagicMock, patch
6
6
 
7
- from hestia_earth.models.ipcc2019.aboveGroundBiomass import (
8
- _is_lcc_event, _rescale_category_cover, _should_run, MODEL, run, TERM_ID
9
- )
10
- from hestia_earth.models.ipcc2019.aboveGroundBiomass_utils import BiomassCategory, sample_constant
7
+ from hestia_earth.models.ipcc2019.aboveGroundBiomass import _build_col_name, _should_run, MODEL, run, TERM_ID
8
+ from hestia_earth.models.ipcc2019.biomass_utils import BiomassCategory, sample_constant
11
9
 
12
10
  from tests.utils import fake_new_measurement, fixtures_path
13
11
 
14
12
  class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
15
- utils_path = f"hestia_earth.models.{MODEL}.{TERM_ID}_utils"
13
+ utils_path = f"hestia_earth.models.{MODEL}.biomass_utils"
16
14
  term_path = "hestia_earth.models.utils.term"
17
15
  property_path = "hestia_earth.models.utils.property"
18
16
 
@@ -40,6 +38,7 @@ PARAMS_SHOULD_RUN = [
40
38
  ("forest-to-cropland-lcc-q2", True),
41
39
  ("forest-to-cropland-lcc-q3", True),
42
40
  ("forest-to-cropland-lcc-q4", True),
41
+ ("forest-to-gohac", False),
43
42
  ("forest-to-orchard", True),
44
43
  ("forest-to-orchard-with-backup-factors", True),
45
44
  ("forest-to-orchard-with-in-category-lcc", True),
@@ -119,64 +118,29 @@ def test_run_with_stats(
119
118
 
120
119
 
121
120
  # input, expected
122
- PARAMS_RESCALE_CATEGORY_COVER = [
123
- (
124
- {BiomassCategory.ANNUAL_CROPS: 90},
125
- {BiomassCategory.ANNUAL_CROPS: 90, BiomassCategory.OTHER: 10}
126
- ),
127
- (
128
- {BiomassCategory.OTHER: 90},
129
- {BiomassCategory.OTHER: 100}
130
- ),
131
- (
132
- {BiomassCategory.ANNUAL_CROPS: 60, BiomassCategory.VINE: 60},
133
- {BiomassCategory.ANNUAL_CROPS: 50, BiomassCategory.VINE: 50}
134
- ),
135
- (
136
- {BiomassCategory.NATURAL_FOREST: 100},
137
- {BiomassCategory.NATURAL_FOREST: 100}
138
- )
121
+ PARAMS_BUILD_COLUMN_NAME = [
122
+ (BiomassCategory.ANNUAL_CROPS, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_ANNUAL_CROPS"),
123
+ (BiomassCategory.COCONUT, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_COCONUT"),
124
+ (BiomassCategory.FOREST, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_FOREST"),
125
+ (BiomassCategory.GRASSLAND, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_GRASSLAND"),
126
+ (BiomassCategory.JATROPHA, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_JATROPHA"),
127
+ (BiomassCategory.JOJOBA, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_JOJOBA"),
128
+ (BiomassCategory.NATURAL_FOREST, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_NATURAL_FOREST"),
129
+ (BiomassCategory.OIL_PALM, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OIL_PALM"),
130
+ (BiomassCategory.OLIVE, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OLIVE"),
131
+ (BiomassCategory.ORCHARD, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_ORCHARD"),
132
+ (BiomassCategory.OTHER, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
133
+ (BiomassCategory.PLANTATION_FOREST, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_PLANTATION_FOREST"),
134
+ (BiomassCategory.RUBBER, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_RUBBER"),
135
+ (BiomassCategory.SHORT_ROTATION_COPPICE, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_SHORT_ROTATION_COPPICE"),
136
+ (BiomassCategory.TEA, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_TEA"),
137
+ (BiomassCategory.VINE, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_VINE"),
138
+ (BiomassCategory.WOODY_PERENNIAL, "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_WOODY_PERENNIAL"),
139
+ ("Miscellaneous value", "AG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER")
139
140
  ]
140
- IDS_RESCALE_CATEGORY_COVER = ["fill", "fill w/ other", "squash", "do nothing"]
141
-
142
-
143
- @mark.parametrize("input, expected", PARAMS_RESCALE_CATEGORY_COVER, ids=IDS_RESCALE_CATEGORY_COVER)
144
- def test_rescale_category_cover(input: dict, expected: dict):
145
- assert _rescale_category_cover(input) == expected
146
-
147
-
148
- # a, b, expected
149
- PARAMS_IS_LCC_EVENT = [
150
- (
151
- {
152
- "appleTree": 33.333,
153
- "pearTree": 33.333,
154
- BiomassCategory.ANNUAL_CROPS: 33.334,
155
- },
156
- {
157
- "appleTree": 33.33333,
158
- "pearTree": 33.33333,
159
- BiomassCategory.ANNUAL_CROPS: 33.33334,
160
- },
161
- True
162
- ),
163
- (
164
- {
165
- "appleTree": 33.3333,
166
- "pearTree": 33.3333,
167
- BiomassCategory.ANNUAL_CROPS: 33.3334,
168
- },
169
- {
170
- "appleTree": 33.33333,
171
- "pearTree": 33.33333,
172
- BiomassCategory.ANNUAL_CROPS: 33.33334,
173
- },
174
- False
175
- )
176
- ]
177
- IDS_IS_LCC_EVENT = ["True", "False"]
141
+ IDS_BUILD_COLUMN_NAME = [p[0] for p in PARAMS_BUILD_COLUMN_NAME]
178
142
 
179
143
 
180
- @mark.parametrize("a, b, expected", PARAMS_IS_LCC_EVENT, ids=IDS_IS_LCC_EVENT)
181
- def test_is_lcc_event(a: dict, b: dict, expected: bool):
182
- assert _is_lcc_event(a, b) is expected
144
+ @mark.parametrize("input, expected", PARAMS_BUILD_COLUMN_NAME, ids=IDS_BUILD_COLUMN_NAME)
145
+ def test_build_col_name(input: BiomassCategory, expected: str):
146
+ assert _build_col_name(input) == expected
@@ -0,0 +1,146 @@
1
+ import json
2
+ from numpy.typing import NDArray
3
+ from os.path import isfile
4
+ from pytest import mark
5
+ from unittest.mock import MagicMock, patch
6
+
7
+ from hestia_earth.models.ipcc2019.belowGroundBiomass import _build_col_name, _should_run, MODEL, run, TERM_ID
8
+ from hestia_earth.models.ipcc2019.biomass_utils import BiomassCategory, sample_constant
9
+
10
+ from tests.utils import fake_new_measurement, fixtures_path
11
+
12
+ class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
13
+ utils_path = f"hestia_earth.models.{MODEL}.biomass_utils"
14
+ term_path = "hestia_earth.models.utils.term"
15
+ property_path = "hestia_earth.models.utils.property"
16
+
17
+ fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
18
+
19
+ _ITERATIONS = 1000
20
+
21
+
22
+ def _load_fixture(path: str, default=None):
23
+ if isfile(path):
24
+ with open(path, encoding="utf-8") as f:
25
+ return json.load(f)
26
+ return default
27
+
28
+
29
+ def _fake_calc_descriptive_stats(arr: NDArray, *_args, **_kwargs):
30
+ return {"value": [round(row[0], 6) for row in arr]}
31
+
32
+
33
+ # subfolder, should_run
34
+ PARAMS_SHOULD_RUN = [
35
+ ("forest-to-animal-housing", False),
36
+ ("forest-to-cropland", True),
37
+ ("forest-to-cropland-greater-than-100", True),
38
+ ("forest-to-cropland-less-than-100", True),
39
+ ("forest-to-cropland-lcc-q2", True),
40
+ ("forest-to-cropland-lcc-q3", True),
41
+ ("forest-to-cropland-lcc-q4", True),
42
+ ("forest-to-gohac", False),
43
+ ("forest-to-orchard", True),
44
+ ("forest-to-orchard-with-in-category-lcc", True),
45
+ ("historical-land-cover-mix", True),
46
+ ("historical-argentina-pasture", True),
47
+ ("historical-brazil-maize", True),
48
+ ("perennial-to-grassland-with-pasture-condition", True)
49
+ ]
50
+ IDS_SHOULD_RUN = [p[0] for p in PARAMS_SHOULD_RUN]
51
+
52
+
53
+ @mark.parametrize("subfolder, should_run", PARAMS_SHOULD_RUN, ids=IDS_SHOULD_RUN)
54
+ def test_should_run(subfolder: str, should_run: bool):
55
+ folder = f"{fixtures_folder}/{subfolder}"
56
+
57
+ site = _load_fixture(f"{folder}/site.jsonld", {})
58
+
59
+ result, *_ = _should_run(site)
60
+ assert result == should_run
61
+
62
+
63
+ def test_should_run_no_data():
64
+ SITE = {}
65
+ EXPECTED = False
66
+
67
+ result, *_ = _should_run(SITE)
68
+ assert result == EXPECTED
69
+
70
+
71
+ PARAMS_RUN = [subfolder for subfolder, should_run in PARAMS_SHOULD_RUN if should_run]
72
+
73
+
74
+ @mark.parametrize("subfolder", PARAMS_RUN)
75
+ @patch(f"{class_path}.calc_descriptive_stats", side_effect=_fake_calc_descriptive_stats)
76
+ @patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
77
+ @patch(f"{utils_path}._get_sample_func", return_value=sample_constant)
78
+ def test_run(
79
+ _get_sample_func_mock: MagicMock,
80
+ _new_measurement_mock: MagicMock,
81
+ _calc_descriptive_stats_mock: MagicMock,
82
+ subfolder: str
83
+ ):
84
+ folder = f"{fixtures_folder}/{subfolder}"
85
+
86
+ site = _load_fixture(f"{folder}/site.jsonld", {})
87
+ expected = _load_fixture(f"{folder}/result.jsonld", [])
88
+
89
+ with patch(f"{class_path}._ITERATIONS", _ITERATIONS):
90
+ result = run(site)
91
+
92
+ assert result == expected
93
+
94
+
95
+ # subfolder
96
+ PARAMS_RUN_WITH_STATS = [
97
+ "forest-to-cropland-with-stats",
98
+ "forest-to-orchard-with-in-category-lcc-with-stats",
99
+ "historical-land-cover-mix-with-stats"
100
+ ]
101
+
102
+
103
+ @mark.parametrize("subfolder", PARAMS_RUN_WITH_STATS)
104
+ @patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
105
+ def test_run_with_stats(
106
+ _new_measurement_mock: MagicMock,
107
+ subfolder: str
108
+ ):
109
+ folder = f"{fixtures_folder}/{subfolder}"
110
+
111
+ site = _load_fixture(f"{folder}/site.jsonld", {})
112
+ expected = _load_fixture(f"{folder}/result.jsonld", [])
113
+
114
+ with patch(f"{class_path}._ITERATIONS", _ITERATIONS):
115
+ result = run(site)
116
+
117
+ assert result == expected
118
+
119
+
120
+ # input, expected
121
+ PARAMS_BUILD_COLUMN_NAME = [
122
+ (BiomassCategory.ANNUAL_CROPS, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
123
+ (BiomassCategory.COCONUT, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
124
+ (BiomassCategory.FOREST, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_FOREST"),
125
+ (BiomassCategory.GRASSLAND, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
126
+ (BiomassCategory.JATROPHA, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
127
+ (BiomassCategory.JOJOBA, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
128
+ (BiomassCategory.NATURAL_FOREST, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_NATURAL_FOREST"),
129
+ (BiomassCategory.OIL_PALM, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
130
+ (BiomassCategory.OLIVE, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
131
+ (BiomassCategory.ORCHARD, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
132
+ (BiomassCategory.OTHER, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
133
+ (BiomassCategory.PLANTATION_FOREST, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_PLANTATION_FOREST"),
134
+ (BiomassCategory.RUBBER, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
135
+ (BiomassCategory.SHORT_ROTATION_COPPICE, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
136
+ (BiomassCategory.TEA, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
137
+ (BiomassCategory.VINE, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
138
+ (BiomassCategory.WOODY_PERENNIAL, "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER"),
139
+ ("Miscellaneous value", "BG_BIOMASS_EQUILIBRIUM_KG_C_HECTARE_OTHER")
140
+ ]
141
+ IDS_BUILD_COLUMN_NAME = [p[0] for p in PARAMS_BUILD_COLUMN_NAME]
142
+
143
+
144
+ @mark.parametrize("input, expected", PARAMS_BUILD_COLUMN_NAME, ids=IDS_BUILD_COLUMN_NAME)
145
+ def test_build_col_name(input: BiomassCategory, expected: str):
146
+ assert _build_col_name(input) == expected
@@ -0,0 +1,115 @@
1
+ from pytest import mark
2
+
3
+ from hestia_earth.models.ipcc2019.biomass_utils import (
4
+ _assign_biomass_category, _get_sample_func, _rescale_category_cover, BiomassCategory, detect_land_cover_change,
5
+ sample_constant, sample_plus_minus_error
6
+ )
7
+
8
+ _ITERATIONS = 1000
9
+
10
+
11
+ # input, expected
12
+ PARAMS_RESCALE_CATEGORY_COVER = [
13
+ (
14
+ {BiomassCategory.ANNUAL_CROPS: 90},
15
+ {BiomassCategory.ANNUAL_CROPS: 90, BiomassCategory.OTHER: 10}
16
+ ),
17
+ (
18
+ {BiomassCategory.OTHER: 90},
19
+ {BiomassCategory.OTHER: 100}
20
+ ),
21
+ (
22
+ {BiomassCategory.ANNUAL_CROPS: 60, BiomassCategory.VINE: 60},
23
+ {BiomassCategory.ANNUAL_CROPS: 50, BiomassCategory.VINE: 50}
24
+ ),
25
+ (
26
+ {BiomassCategory.NATURAL_FOREST: 100},
27
+ {BiomassCategory.NATURAL_FOREST: 100}
28
+ )
29
+ ]
30
+ IDS_RESCALE_CATEGORY_COVER = ["fill", "fill w/ other", "squash", "do nothing"]
31
+
32
+
33
+ @mark.parametrize("input, expected", PARAMS_RESCALE_CATEGORY_COVER, ids=IDS_RESCALE_CATEGORY_COVER)
34
+ def test_rescale_category_cover(input: dict, expected: dict):
35
+ assert _rescale_category_cover(input) == expected
36
+
37
+
38
+ # a, b, expected
39
+ PARAMS_IS_LCC_EVENT = [
40
+ (
41
+ {
42
+ "appleTree": 33.333,
43
+ "pearTree": 33.333,
44
+ BiomassCategory.ANNUAL_CROPS: 33.334,
45
+ },
46
+ {
47
+ "appleTree": 33.33333,
48
+ "pearTree": 33.33333,
49
+ BiomassCategory.ANNUAL_CROPS: 33.33334,
50
+ },
51
+ True
52
+ ),
53
+ (
54
+ {
55
+ "appleTree": 33.3333,
56
+ "pearTree": 33.3333,
57
+ BiomassCategory.ANNUAL_CROPS: 33.3334,
58
+ },
59
+ {
60
+ "appleTree": 33.33333,
61
+ "pearTree": 33.33333,
62
+ BiomassCategory.ANNUAL_CROPS: 33.33334,
63
+ },
64
+ False
65
+ )
66
+ ]
67
+ IDS_IS_LCC_EVENT = ["True", "False"]
68
+
69
+
70
+ @mark.parametrize("a, b, expected", PARAMS_IS_LCC_EVENT, ids=IDS_IS_LCC_EVENT)
71
+ def test_detect_land_cover_change(a: dict, b: dict, expected: bool):
72
+ assert detect_land_cover_change(a, b) is expected
73
+
74
+
75
+ # kwargs, sample_func, expected_shape
76
+ PARAMS_GET_SAMPLE_FUNC = [
77
+ ({"value": 1}, sample_constant),
78
+ ({"value": 1, "error": 10}, sample_plus_minus_error),
79
+ ]
80
+ IDS_GET_SAMPLE_FUNC = ["constant", "+/- error"]
81
+
82
+
83
+ @mark.parametrize("kwargs, sample_func", PARAMS_GET_SAMPLE_FUNC, ids=IDS_GET_SAMPLE_FUNC)
84
+ def test_get_sample_func(kwargs, sample_func):
85
+ result = _get_sample_func(kwargs)
86
+ assert result == sample_func
87
+
88
+
89
+ # input, expected
90
+ PARAMS_ASSIGN_BIOMASS_CATEGORY = [
91
+ ("Annual crops", BiomassCategory.ANNUAL_CROPS),
92
+ ("Coconut", BiomassCategory.COCONUT),
93
+ ("Forest", BiomassCategory.FOREST),
94
+ ("Grassland", BiomassCategory.GRASSLAND),
95
+ ("Jatropha", BiomassCategory.JATROPHA),
96
+ ("Jojoba", BiomassCategory.JOJOBA),
97
+ ("Natural forest", BiomassCategory.NATURAL_FOREST),
98
+ ("Oil palm", BiomassCategory.OIL_PALM),
99
+ ("Olive", BiomassCategory.OLIVE),
100
+ ("Orchard", BiomassCategory.ORCHARD),
101
+ ("Other", BiomassCategory.OTHER),
102
+ ("Plantation forest", BiomassCategory.PLANTATION_FOREST),
103
+ ("Rubber", BiomassCategory.RUBBER),
104
+ ("Short rotation coppice", BiomassCategory.SHORT_ROTATION_COPPICE),
105
+ ("Tea", BiomassCategory.TEA),
106
+ ("Vine", BiomassCategory.VINE),
107
+ ("Woody perennial", BiomassCategory.WOODY_PERENNIAL),
108
+ ("Miscellaneous value", None)
109
+ ]
110
+ IDS_ASSIGN_BIOMASS_CATEGORY = [p[0] for p in PARAMS_ASSIGN_BIOMASS_CATEGORY]
111
+
112
+
113
+ @mark.parametrize("input, expected", PARAMS_ASSIGN_BIOMASS_CATEGORY, ids=IDS_ASSIGN_BIOMASS_CATEGORY)
114
+ def test_assign_biomass_category(input: str, expected: BiomassCategory):
115
+ assert _assign_biomass_category(input) == expected
@@ -4,13 +4,13 @@ from os.path import isfile
4
4
  from pytest import mark
5
5
  from unittest.mock import patch
6
6
 
7
- from hestia_earth.models.ipcc2019.co2ToAirAboveGroundBiomassStockChangeLandUseChange import MODEL, run, TERM_ID
7
+ from hestia_earth.models.ipcc2019.co2ToAirAboveGroundBiomassStockChange import MODEL, run
8
8
 
9
- from tests.utils import fake_new_emission, fixtures_path
9
+ from tests.utils import fake_new_emission, fixtures_path, order_list
10
10
 
11
- class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
11
+ class_path = f"hestia_earth.models.{MODEL}.co2ToAirAboveGroundBiomassStockChange"
12
12
  utils_path = f"hestia_earth.models.{MODEL}.co2ToAirCarbonStockChange_utils"
13
- fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
13
+ fixtures_folder = f"{fixtures_path}/{MODEL}/co2ToAirAboveGroundBiomassStockChange"
14
14
 
15
15
  RUN_SCENARIOS = [
16
16
  ("no-overlapping-cycles", 3),
@@ -63,7 +63,7 @@ def test_run(_get_site_mock, related_cycles_mock, _new_emission_mock, subfolder,
63
63
  related_cycles_mock.return_value = cycles
64
64
 
65
65
  result = run(cycle)
66
- assert result == expected
66
+ assert order_list(result) == order_list(expected)
67
67
 
68
68
 
69
69
  @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
@@ -4,13 +4,13 @@ from os.path import isfile
4
4
  from pytest import mark
5
5
  from unittest.mock import patch
6
6
 
7
- from hestia_earth.models.ipcc2019.co2ToAirBelowGroundBiomassStockChangeLandUseChange import MODEL, run, TERM_ID
7
+ from hestia_earth.models.ipcc2019.co2ToAirBelowGroundBiomassStockChange import MODEL, run
8
8
 
9
- from tests.utils import fake_new_emission, fixtures_path
9
+ from tests.utils import fake_new_emission, fixtures_path, order_list
10
10
 
11
- class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
11
+ class_path = f"hestia_earth.models.{MODEL}.co2ToAirBelowGroundBiomassStockChange"
12
12
  utils_path = f"hestia_earth.models.{MODEL}.co2ToAirCarbonStockChange_utils"
13
- fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
13
+ fixtures_folder = f"{fixtures_path}/{MODEL}/co2ToAirBelowGroundBiomassStockChange"
14
14
 
15
15
  RUN_SCENARIOS = [
16
16
  ("no-overlapping-cycles", 3),
@@ -63,7 +63,7 @@ def test_run(_get_site_mock, related_cycles_mock, _new_emission_mock, subfolder,
63
63
  related_cycles_mock.return_value = cycles
64
64
 
65
65
  result = run(cycle)
66
- assert result == expected
66
+ assert order_list(result) == order_list(expected)
67
67
 
68
68
 
69
69
  @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
@@ -4,13 +4,13 @@ from os.path import isfile
4
4
  from pytest import mark
5
5
  from unittest.mock import patch
6
6
 
7
- from hestia_earth.models.ipcc2019.co2ToAirSoilOrganicCarbonStockChangeManagementChange import MODEL, run, TERM_ID
7
+ from hestia_earth.models.ipcc2019.co2ToAirSoilOrganicCarbonStockChange import MODEL, run
8
8
 
9
- from tests.utils import fake_new_emission, fixtures_path
9
+ from tests.utils import fake_new_emission, fixtures_path, order_list
10
10
 
11
- class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
11
+ class_path = f"hestia_earth.models.{MODEL}.co2ToAirSoilOrganicCarbonStockChange"
12
12
  utils_path = f"hestia_earth.models.{MODEL}.co2ToAirCarbonStockChange_utils"
13
- fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
13
+ fixtures_folder = f"{fixtures_path}/{MODEL}/co2ToAirSoilOrganicCarbonStockChange"
14
14
 
15
15
  RUN_SCENARIOS = [
16
16
  ("no-overlapping-cycles", 3),
@@ -63,7 +63,7 @@ def test_run(_get_site_mock, related_cycles_mock, _new_emission_mock, subfolder,
63
63
  related_cycles_mock.return_value = cycles
64
64
 
65
65
  result = run(cycle)
66
- assert result == expected
66
+ assert order_list(result) == order_list(expected)
67
67
 
68
68
 
69
69
  @patch(f"{class_path}._new_emission", side_effect=fake_new_emission)
@@ -13,8 +13,8 @@ def test_run_no_emissions():
13
13
  impact = json.load(f)
14
14
 
15
15
  impact['emissionsResourceUse'] = []
16
- value = run(impact)
17
- assert value is None
16
+ indicator = run(impact)
17
+ assert indicator.get('value') == 0
18
18
 
19
19
 
20
20
  @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)