hestia-earth-models 0.64.8__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 (105) hide show
  1. hestia_earth/models/cml2001Baseline/abioticResourceDepletionFossilFuels.py +175 -0
  2. hestia_earth/models/cml2001Baseline/abioticResourceDepletionMineralsAndMetals.py +136 -0
  3. hestia_earth/models/cycle/siteArea.py +2 -1
  4. hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandOccupation.py +73 -82
  5. hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandTransformation.py +102 -116
  6. hestia_earth/models/environmentalFootprintV3/soilQualityIndexTotalLandUseEffects.py +27 -16
  7. hestia_earth/models/faostat2018/landTransformationFromCropland100YearAverage.py +3 -2
  8. hestia_earth/models/faostat2018/landTransformationFromCropland20YearAverage.py +3 -2
  9. hestia_earth/models/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +69 -37
  10. hestia_earth/models/ipcc2019/aboveGroundBiomass.py +31 -243
  11. hestia_earth/models/ipcc2019/animal/fatContent.py +38 -0
  12. hestia_earth/models/ipcc2019/animal/liveweightGain.py +3 -54
  13. hestia_earth/models/ipcc2019/animal/liveweightPerHead.py +3 -54
  14. hestia_earth/models/ipcc2019/animal/pregnancyRateTotal.py +38 -0
  15. hestia_earth/models/ipcc2019/animal/trueProteinContent.py +38 -0
  16. hestia_earth/models/ipcc2019/animal/utils.py +87 -3
  17. hestia_earth/models/ipcc2019/animal/weightAtMaturity.py +4 -10
  18. hestia_earth/models/ipcc2019/belowGroundBiomass.py +529 -0
  19. hestia_earth/models/ipcc2019/biomass_utils.py +406 -0
  20. hestia_earth/models/ipcc2019/{co2ToAirAboveGroundBiomassStockChangeLandUseChange.py → co2ToAirAboveGroundBiomassStockChange.py} +19 -7
  21. hestia_earth/models/ipcc2019/{co2ToAirBelowGroundBiomassStockChangeLandUseChange.py → co2ToAirBelowGroundBiomassStockChange.py} +19 -7
  22. hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +402 -73
  23. hestia_earth/models/ipcc2019/{co2ToAirSoilOrganicCarbonStockChangeManagementChange.py → co2ToAirSoilOrganicCarbonStockChange.py} +20 -8
  24. hestia_earth/models/ipcc2019/organicCarbonPerHa.py +3 -1
  25. hestia_earth/models/ipcc2019/pastureGrass_utils.py +6 -7
  26. hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
  27. hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsWaterStress.py +2 -2
  28. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthParticulateMatterFormation.py +2 -2
  29. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
  30. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthWaterStress.py +2 -2
  31. hestia_earth/models/lcImpactAllEffects100Years/damageToMarineEcosystemsMarineEutrophication.py +2 -2
  32. hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
  33. hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
  34. hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
  35. hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsWaterStress.py +2 -2
  36. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthParticulateMatterFormation.py +2 -2
  37. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
  38. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
  39. hestia_earth/models/lcImpactAllEffectsInfinite/damageToMarineEcosystemsMarineEutrophication.py +2 -2
  40. hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
  41. hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
  42. hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
  43. hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsWaterStress.py +2 -2
  44. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthParticulateMatterFormation.py +2 -2
  45. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
  46. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthWaterStress.py +2 -2
  47. hestia_earth/models/lcImpactCertainEffects100Years/damageToMarineEcosystemsMarineEutrophication.py +2 -2
  48. hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
  49. hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
  50. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
  51. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsWaterStress.py +2 -2
  52. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthParticulateMatterFormation.py +2 -2
  53. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
  54. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
  55. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToMarineEcosystemsMarineEutrophication.py +2 -2
  56. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
  57. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
  58. hestia_earth/models/mocking/build_mock_search.py +44 -0
  59. hestia_earth/models/mocking/mock_search.py +8 -49
  60. hestia_earth/models/mocking/search-results.json +3078 -575
  61. hestia_earth/models/poschEtAl2008/terrestrialAcidificationPotentialAccumulatedExceedance.py +6 -3
  62. hestia_earth/models/poschEtAl2008/terrestrialEutrophicationPotentialAccumulatedExceedance.py +6 -3
  63. hestia_earth/models/preload_requests.py +1 -1
  64. hestia_earth/models/schmidt2007/utils.py +13 -4
  65. hestia_earth/models/utils/__init__.py +5 -4
  66. hestia_earth/models/utils/blank_node.py +73 -3
  67. hestia_earth/models/utils/constant.py +8 -1
  68. hestia_earth/models/utils/cycle.py +10 -13
  69. hestia_earth/models/utils/fuel.py +1 -1
  70. hestia_earth/models/utils/impact_assessment.py +39 -15
  71. hestia_earth/models/utils/lookup.py +36 -7
  72. hestia_earth/models/utils/pesticideAI.py +1 -1
  73. hestia_earth/models/utils/property.py +11 -4
  74. hestia_earth/models/utils/term.py +15 -8
  75. hestia_earth/models/version.py +1 -1
  76. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/METADATA +2 -2
  77. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/RECORD +103 -90
  78. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/WHEEL +1 -1
  79. tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +196 -0
  80. tests/models/cml2001Baseline/test_abioticResourceDepletionMineralsAndMetals.py +124 -0
  81. tests/models/edip2003/test_ozoneDepletionPotential.py +1 -13
  82. tests/models/environmentalFootprintV3/test_soilQualityIndexLandOccupation.py +97 -66
  83. tests/models/environmentalFootprintV3/test_soilQualityIndexLandTransformation.py +136 -74
  84. tests/models/environmentalFootprintV3/test_soilQualityIndexTotalLandUseEffects.py +15 -10
  85. tests/models/frischknechtEtAl2000/test_ionisingRadiationKbqU235Eq.py +67 -44
  86. tests/models/impact_assessment/test_emissions.py +1 -0
  87. tests/models/ipcc2019/animal/test_fatContent.py +22 -0
  88. tests/models/ipcc2019/animal/test_liveweightGain.py +4 -2
  89. tests/models/ipcc2019/animal/test_liveweightPerHead.py +4 -2
  90. tests/models/ipcc2019/animal/test_pregnancyRateTotal.py +22 -0
  91. tests/models/ipcc2019/animal/test_trueProteinContent.py +22 -0
  92. tests/models/ipcc2019/animal/test_weightAtMaturity.py +2 -1
  93. tests/models/ipcc2019/test_aboveGroundBiomass.py +27 -63
  94. tests/models/ipcc2019/test_belowGroundBiomass.py +146 -0
  95. tests/models/ipcc2019/test_biomass_utils.py +115 -0
  96. tests/models/ipcc2019/{test_co2ToAirAboveGroundBiomassStockChangeLandUseChange.py → test_co2ToAirAboveGroundBiomassStockChange.py} +5 -5
  97. tests/models/ipcc2019/{test_co2ToAirBelowGroundBiomassStockChangeLandUseChange.py → test_co2ToAirBelowGroundBiomassStockChange.py} +5 -5
  98. tests/models/ipcc2019/{test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py → test_co2ToAirSoilOrganicCarbonStockChange.py} +5 -5
  99. tests/models/ipcc2021/test_gwp100.py +2 -2
  100. tests/models/poschEtAl2008/test_terrestrialAcidificationPotentialAccumulatedExceedance.py +30 -17
  101. tests/models/poschEtAl2008/test_terrestrialEutrophicationPotentialAccumulatedExceedance.py +28 -14
  102. hestia_earth/models/ipcc2019/aboveGroundBiomass_utils.py +0 -180
  103. tests/models/ipcc2019/test_aboveGroundBiomass_utils.py +0 -92
  104. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/LICENSE +0 -0
  105. {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,196 @@
1
+ import json
2
+ from unittest.mock import patch
3
+
4
+ from pytest import mark
5
+
6
+ from hestia_earth.models.cml2001Baseline.abioticResourceDepletionFossilFuels import MODEL, TERM_ID, run, _should_run, \
7
+ download_all_non_renewable_terms
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
+ def fake_download_hestia(filename):
21
+ data = {
22
+ 'fuel.csv': ["lignite", "conventionalCrudeOil", "naturalGas", "coalTar"],
23
+ 'electricity.csv': ['electricityGridMarketMix', 'electricityGridHardCoal', 'electricityProducedOnSiteHardCoal',
24
+ 'electricityGridNaturalGas', 'electricityProducedOnSiteNaturalGas', 'electricityGridOil',
25
+ 'electricityProducedOnSiteOil', 'electricityGridNuclear']}
26
+ return data[filename]
27
+
28
+
29
+ input_lignite_mj = {"@id": "lignite", "name": "lignite (Brown coal)", "termType": "fuel", "units": "MJ"}
30
+ input_coal_tar_kg = {"@id": "coalTar", "name": "Coal tar unknown energy Content", "termType": "fuel", "units": "kg"}
31
+ input_crude_oil_kg_property = {
32
+ "@id": "conventionalCrudeOil", "name": "Conventional Crude Oil", "termType": "fuel", "units": "kg",
33
+ "properties": [{"@type": "Property", "value": 45.8,
34
+ "term": {"@type": "Term", "@id": "energyContentHigherHeatingValue", "units": "MJ / kg"}, }]}
35
+ input_crude_oil_kg_no_property = {
36
+ "@id": "conventionalCrudeOil", "name": "Conventional Crude Oil", "termType": "fuel", "units": "kg"}
37
+ input_natural_gas_m3 = {"@id": "naturalGas", "name": "Natural Gas", "termType": "fuel", "units": "m3"}
38
+ input_nuclear_fuel_mj = {"@id": "electricityGridNuclear", "name": "Any depleted nuclear fuel",
39
+ "termType": "electricity", "units": "MJ"}
40
+ input_nuclear_fuel_kwh = {"@id": "electricityGridNuclear", "termType": "electricity", "units": "kWh"}
41
+ input_excessIndustrialHeat_mj = {"@id": "excessIndustrialHeat", "name": "Excess industrial heat", "termType": "fuel",
42
+ "units": "MJ"}
43
+
44
+ wrong_indicator = {"term": {"@id": "BAD_INDICATOR_ID", "termType": "resourceUse"},
45
+ "value": 5,
46
+ "inputs": [input_lignite_mj]}
47
+
48
+ indicator_no_inputs = {"term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
49
+ "value": 5,
50
+ "inputs": []}
51
+
52
+ indicator_2_inputs = {"term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
53
+ "value": 5,
54
+ "inputs": [input_lignite_mj, input_lignite_mj]}
55
+
56
+ indicator_no_unit = {"term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
57
+ "value": 5,
58
+ "inputs": [{
59
+ "@id": "lignite",
60
+ "@type": "Term",
61
+ "name": "lignite (Brown coal)",
62
+ "termType": "fuel",
63
+ }]}
64
+
65
+ indicator_wrong_unit = {"term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
66
+ "value": 5,
67
+ "inputs": [
68
+ {
69
+ "@id": "lignite",
70
+ "@type": "Term",
71
+ "name": "lignite (Brown coal)",
72
+ "termType": "fuel",
73
+ "units": "ha"
74
+ }
75
+ ]}
76
+
77
+ indicator_bad_input_id = {"term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
78
+ "value": 5,
79
+ "inputs": [input_excessIndustrialHeat_mj]}
80
+
81
+ good_indicator_inputs_production_mj = {
82
+ "term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
83
+ "value": 5,
84
+ "inputs": [input_lignite_mj]
85
+ }
86
+
87
+ good_indicator_during_cycle_mj = {"term": {"@id": "resourceUseEnergyDepletionDuringCycle", "termType": "resourceUse"},
88
+ "value": 5,
89
+ "inputs": [input_lignite_mj]}
90
+
91
+ good_indicator_inputs_production_with_property = {
92
+ "term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
93
+ "value": 5,
94
+ "inputs": [input_crude_oil_kg_property]
95
+ }
96
+
97
+ good_indicator_inputs_production_with_no_property = {
98
+ "term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
99
+ "value": 5,
100
+ "inputs": [input_crude_oil_kg_no_property]
101
+ }
102
+
103
+ good_indicator_m3 = {"term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
104
+ "value": 5,
105
+ "inputs": [input_natural_gas_m3]}
106
+
107
+ good_nuclear_indicator_mj = {"term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
108
+ "value": 5,
109
+ "inputs": [input_nuclear_fuel_mj]}
110
+ good_nuclear_indicator_kwh = {"term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
111
+ "value": 1.3889,
112
+ "inputs": [input_nuclear_fuel_kwh]}
113
+
114
+ bad_fuel_indicator_no_property_lookup = {
115
+ "term": {"@id": "resourceUseEnergyDepletionInputsProduction", "termType": "resourceUse"},
116
+ "value": 5,
117
+ "inputs": [input_coal_tar_kg]}
118
+
119
+
120
+ @mark.parametrize(
121
+ "resources, expected, num_inputs",
122
+ [
123
+ ([], True, 0),
124
+ ([wrong_indicator], True, 0),
125
+ ([indicator_no_inputs], False, 0),
126
+ ([indicator_2_inputs], False, 2),
127
+ ([indicator_no_unit], False, 0),
128
+ ([indicator_wrong_unit], False, 0),
129
+ ([indicator_bad_input_id], False, 0),
130
+ ([good_indicator_inputs_production_mj], True, 1),
131
+ ([good_indicator_during_cycle_mj], True, 1),
132
+ ([good_indicator_inputs_production_with_property], True, 1),
133
+ ([good_indicator_inputs_production_with_no_property], True, 1),
134
+ ([good_indicator_m3], True, 1),
135
+ ([good_nuclear_indicator_mj], True, 1),
136
+ ([good_nuclear_indicator_kwh], True, 1),
137
+ ([bad_fuel_indicator_no_property_lookup], False, 0),
138
+ ],
139
+ ids=["No indicators", "wrong indicator", "indicator no inputs", "indicator 2 inputs", "missing unit", "wrong unit",
140
+ "input id not in requirements", "good input production mj", "good during cycle mj",
141
+ "good input with input property", "good input with no input property", "good indicator in m^3",
142
+ "good nuclear fuel use indicator in mj", "good nuclear fuel use indicator in kWh",
143
+ "bad indicator input in kg no property to convert to mj"]
144
+ )
145
+ @patch(f"{class_path}.download_all_non_renewable_terms", side_effect=fake_download_hestia)
146
+ def test_should_run(mock_download_all_non_renewable_terms, resources, expected, num_inputs):
147
+ with open(f"{fixtures_folder}/impactassessment.jsonld", encoding='utf-8') as f:
148
+ impactassessment = json.load(f)
149
+
150
+ impactassessment['emissionsResourceUse'] = resources
151
+
152
+ should_run, resources = _should_run(impactassessment)
153
+ assert should_run is expected
154
+ assert len(resources) == num_inputs
155
+
156
+
157
+ @patch(f"{class_path}.download_all_non_renewable_terms", side_effect=fake_download_hestia)
158
+ @patch(f"{class_path}._indicator", side_effect=fake_rounded_indicator)
159
+ def test_run(*args):
160
+ with open(f"{fixtures_folder}/impactassessment.jsonld", encoding='utf-8') as f:
161
+ impactassessment = json.load(f)
162
+
163
+ with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
164
+ expected = json.load(f)
165
+
166
+ value = run(impactassessment)
167
+ assert value == expected
168
+
169
+
170
+ @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
171
+ def test_run_no_emissions(*args):
172
+ """
173
+ Impact assessment with no emissions should return a indicator of 0
174
+ """
175
+ with open(f"{fixtures_folder}/impactassessment.jsonld", encoding='utf-8') as f:
176
+ impactassessment = json.load(f)
177
+
178
+ del impactassessment['emissionsResourceUse']
179
+
180
+ value = run(impactassessment)
181
+ assert value['value'] == 0
182
+
183
+
184
+ def test_download_all_non_renewable_terms(*args):
185
+ """
186
+ make sure download_all_non_renewable_terms() only returns terms we want
187
+ """
188
+ electricity_terms = download_all_non_renewable_terms("electricity.csv")
189
+
190
+ assert "electricityGridHardCoal" in electricity_terms
191
+ assert "electricityGridWind" not in electricity_terms
192
+
193
+ fuel_terms = download_all_non_renewable_terms("fuel.csv")
194
+
195
+ assert "coalTar" in fuel_terms
196
+ assert "sodPeat" not in fuel_terms
@@ -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
@@ -1,71 +1,107 @@
1
1
  import json
2
2
  from unittest.mock import patch
3
3
 
4
- from hestia_earth.models.environmentalFootprintV3.soilQualityIndexLandOccupation import MODEL, TERM_ID, run, _should_run
4
+ import pytest
5
+
6
+ from hestia_earth.models.environmentalFootprintV3.soilQualityIndexLandOccupation import MODEL, TERM_ID, run, \
7
+ _should_run
5
8
  from tests.utils import fixtures_path, fake_new_indicator
6
9
 
7
10
  class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
8
11
  fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
9
12
 
10
-
11
- with open(f"{fixtures_path}/impact_assessment/emissions/impact-assessment.jsonld", encoding='utf-8') as f:
12
- impact = json.load(f)
13
-
14
-
15
- def test_should_run():
16
- with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
17
- cycle = json.load(f)
18
-
19
- # a LandCover type with no CF => no run
20
- cycle['site']['management'] = [{"endDate": "2024-03-31", "@type": "Management",
21
- "term": {"termType": "landCover", "@type": "Term", "@id": "ocean"}}]
22
-
23
- should_run, *args = _should_run({'cycle': cycle})
24
- assert not should_run
25
-
26
- # no management => no run
27
- cycle['site']['management'] = []
28
- should_run, *args = _should_run({'cycle': cycle})
29
- assert not should_run
13
+ crop_land = {"@id": "cropland", "termType": "landCover"}
14
+ sea_land_cover = {"@id": "seaOrOcean", "termType": "landCover"}
15
+ forest = {"@id": "forest", "termType": "landCover"}
16
+
17
+ wrong_indicator = {"term": {"@id": "NOT_landOccupationInputsProduction", "termType": "resourceUse", "units": "m2*year"},
18
+ "value": 0.5, "landCover": crop_land}
19
+
20
+ indicator_no_land_cover = {
21
+ "term": {"@id": "landOccupationInputsProduction", "termType": "resourceUse", "units": "m2*year"},
22
+ "value": 0.5}
23
+
24
+ indicator_no_unit = {"term": {"@id": "landOccupationInputsProduction", "termType": "resourceUse"},
25
+ "value": 0.5, "landCover": crop_land}
26
+
27
+ indicator_wrong_unit = {
28
+ "term": {"@id": "landOccupationInputsProduction", "termType": "resourceUse", "units": "ha*day"}, "value": 0.5,
29
+ "landCover": crop_land}
30
+
31
+ indicator_bad_area_time_value = {
32
+ "term": {"@id": "landOccupationInputsProduction", "termType": "resourceUse", "units": "m2*year"}, "value": 0,
33
+ "landCover": crop_land}
34
+
35
+ inputs_production_indicator_no_cf = {
36
+ "term": {"@id": "landOccupationInputsProduction", "termType": "resourceUse", "units": "m2*year"}, "value": 0.5,
37
+ "landCover": sea_land_cover}
38
+
39
+ good_inputs_production_indicator_cropland = {
40
+ "term": {"@id": "landOccupationInputsProduction", "termType": "resourceUse", "units": "m2*year"}, "value": 0.5,
41
+ "landCover": crop_land}
42
+
43
+ good_inputs_production_indicator_forest = {
44
+ "term": {"@id": "landOccupationInputsProduction", "termType": "resourceUse", "units": "m2*year"}, "value": 0.5,
45
+ "landCover": forest}
46
+
47
+ good_during_cycle_indicator_cropland = {
48
+ "term": {"@id": "landOccupationDuringCycle", "termType": "resourceUse", "units": "m2*year"}, "value": 0.5,
49
+ "landCover": crop_land}
50
+
51
+ good_during_cycle_indicator_forest = {
52
+ "term": {"@id": "landOccupationDuringCycle", "termType": "resourceUse", "units": "m2*year"}, "value": 0.5,
53
+ "landCover": forest}
54
+
55
+
56
+ @pytest.mark.parametrize(
57
+ "resources, expected, num_inputs",
58
+ [
59
+ ([], False, 0),
60
+ ([wrong_indicator], False, 0),
61
+ ([indicator_no_land_cover], False, 0),
62
+ ([indicator_no_unit], False, 0),
63
+ ([indicator_wrong_unit], False, 0),
64
+ ([indicator_bad_area_time_value], False, 0),
65
+ ([inputs_production_indicator_no_cf], True, 0),
66
+ ([good_during_cycle_indicator_cropland], True, 1),
67
+ ([good_during_cycle_indicator_cropland, good_inputs_production_indicator_forest], True, 2),
68
+ ([good_during_cycle_indicator_cropland, inputs_production_indicator_no_cf], True, 1),
69
+ ([good_during_cycle_indicator_cropland, good_during_cycle_indicator_forest,
70
+ good_inputs_production_indicator_forest, good_inputs_production_indicator_cropland], True, 4),
71
+
72
+ ],
73
+ ids=["No emissionsResourceUse => no run",
74
+ "Wrong indicator termid => no run",
75
+ "Indicator no landcover terms => no run",
76
+ "Missing unit => no run",
77
+ "Wrong unit => no run",
78
+ "Bad area*time value => no run",
79
+ "Input with no cf => run, empty input",
80
+ "One good input => run, 1 dict",
81
+ "Two good input => run, 2 dict",
82
+ "One good input and One with no CF => run, 2 dict",
83
+ "Multiple good indicators with same id => run, 4 dict",
84
+ ]
85
+ )
86
+ def test_should_run(resources, expected, num_inputs):
87
+ with open(f"{fixtures_folder}/impact-assessment.jsonld", encoding='utf-8') as f:
88
+ impactassessment = json.load(f)
89
+
90
+ impactassessment['emissionsResourceUse'] = resources
91
+
92
+ should_run, resources_with_cf = _should_run(impactassessment)
93
+ assert should_run is expected
94
+ assert len(resources_with_cf) == num_inputs
30
95
 
31
96
 
32
97
  @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
33
98
  def test_run(*args):
34
- with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
35
- cycle = json.load(f)
99
+ with open(f"{fixtures_folder}/impact-assessment.jsonld", encoding='utf-8') as f:
100
+ impact = json.load(f)
36
101
 
37
102
  with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
38
103
  expected = json.load(f)
39
104
 
40
- impact['cycle'] = cycle
41
- value = run(impact)
42
- assert value == expected
43
-
44
-
45
- @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
46
- def test_run_other_sites(*args):
47
- """
48
- This test case contains 2 sites:
49
- One is a crop in france, with value:
50
- CF_METHOD_factor_france_permanent_crops * ( siteArea_france_crop * time_in_years )
51
- = 87.631 * ( 1.0082662E-7 * 1 )
52
- = 8.835537537220001e-06
53
-
54
- And one a forest in italy, with value:
55
- CF_METHOD_factor_italy_forest * ( siteArea_italy_forest * time_in_years )
56
- = 43.198 * ( 1.3573373E-9 * 1 )
57
- = 5.86342566854E-08
58
-
59
- We expect the model to return 8.835537537220001e-06 + 5.86342566854E-08 = 8.894171793905402e-06
60
-
61
- """
62
- with open(f"{fixtures_folder}/otherSites/cycle.jsonld", encoding='utf-8') as f:
63
- cycle = json.load(f)
64
-
65
- with open(f"{fixtures_folder}/otherSites/result.jsonld", encoding='utf-8') as f:
66
- expected = json.load(f)
67
-
68
- impact['cycle'] = cycle
69
105
  value = run(impact)
70
106
  assert value == expected
71
107
 
@@ -75,21 +111,18 @@ def test_run_with_subclass_landcover(*args):
75
111
  """
76
112
  Example data:
77
113
  Country: Italy
78
- Quantity in m^2: 1.3573373E-9
79
- CF METHOD factor: 4.3198E+01
80
- "Charact Result [soil quality index]" result also in result.jsonld : 5.86342566854E-08
81
- siteArea in test file in ha: 1.3573373E-9 / 10 000 = 1.3573373e-13
114
+ Quantity in m2*year: 1
115
+ CF METHOD factor: 50.438
82
116
 
83
117
  landCover field "plantationForest" should map to
84
118
  Name Flow: "forest, intensive Land occupation"
85
119
  """
86
- with open(f"{fixtures_folder}/plantationForest/cycle.jsonld", encoding='utf-8') as f:
87
- cycle = json.load(f)
88
120
 
121
+ with open(f"{fixtures_folder}/plantationForest/impact-assessment.jsonld", encoding='utf-8') as f:
122
+ impact = json.load(f)
89
123
  with open(f"{fixtures_folder}/plantationForest/result.jsonld", encoding='utf-8') as f:
90
124
  expected = json.load(f)
91
125
 
92
- impact['cycle'] = cycle
93
126
  value = run(impact)
94
127
  assert value == expected
95
128
 
@@ -99,13 +132,12 @@ def test_run_with_region_missing_data(*args):
99
132
  """
100
133
  When given valid sub-region or country not in the lookup file should default to 'region-world'
101
134
  """
102
- with open(f"{fixtures_folder}/default-region-world/cycle.jsonld", encoding='utf-8') as f:
103
- cycle = json.load(f)
135
+ with open(f"{fixtures_folder}/default-region-world/impact-assessment.jsonld", encoding='utf-8') as f:
136
+ impact = json.load(f)
104
137
 
105
138
  with open(f"{fixtures_folder}/default-region-world/result.jsonld", encoding='utf-8') as f:
106
139
  expected = json.load(f)
107
140
 
108
- impact['cycle'] = cycle
109
141
  value = run(impact)
110
142
  assert value == expected
111
143
 
@@ -115,14 +147,13 @@ def test_run_with_no_region(*args):
115
147
  """
116
148
  When no location is specified, defaults to region world.
117
149
  """
118
- with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
119
- cycle = json.load(f)
150
+ with open(f"{fixtures_folder}/default-region-world/impact-assessment.jsonld", encoding='utf-8') as f:
151
+ impact = json.load(f)
120
152
 
121
- del cycle['site']['country']
153
+ del impact['country']
122
154
 
123
155
  with open(f"{fixtures_folder}/default-region-world/result.jsonld", encoding='utf-8') as f:
124
156
  expected = json.load(f)
125
157
 
126
- impact['cycle'] = cycle
127
158
  value = run(impact)
128
159
  assert value == expected