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.
- hestia_earth/models/cml2001Baseline/abioticResourceDepletionFossilFuels.py +175 -0
- hestia_earth/models/cml2001Baseline/abioticResourceDepletionMineralsAndMetals.py +136 -0
- hestia_earth/models/cycle/siteArea.py +2 -1
- hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandOccupation.py +73 -82
- hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandTransformation.py +102 -116
- hestia_earth/models/environmentalFootprintV3/soilQualityIndexTotalLandUseEffects.py +27 -16
- hestia_earth/models/faostat2018/landTransformationFromCropland100YearAverage.py +3 -2
- hestia_earth/models/faostat2018/landTransformationFromCropland20YearAverage.py +3 -2
- hestia_earth/models/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +69 -37
- hestia_earth/models/ipcc2019/aboveGroundBiomass.py +31 -243
- hestia_earth/models/ipcc2019/animal/fatContent.py +38 -0
- hestia_earth/models/ipcc2019/animal/liveweightGain.py +3 -54
- hestia_earth/models/ipcc2019/animal/liveweightPerHead.py +3 -54
- hestia_earth/models/ipcc2019/animal/pregnancyRateTotal.py +38 -0
- hestia_earth/models/ipcc2019/animal/trueProteinContent.py +38 -0
- hestia_earth/models/ipcc2019/animal/utils.py +87 -3
- hestia_earth/models/ipcc2019/animal/weightAtMaturity.py +4 -10
- hestia_earth/models/ipcc2019/belowGroundBiomass.py +529 -0
- hestia_earth/models/ipcc2019/biomass_utils.py +406 -0
- hestia_earth/models/ipcc2019/{co2ToAirAboveGroundBiomassStockChangeLandUseChange.py → co2ToAirAboveGroundBiomassStockChange.py} +19 -7
- hestia_earth/models/ipcc2019/{co2ToAirBelowGroundBiomassStockChangeLandUseChange.py → co2ToAirBelowGroundBiomassStockChange.py} +19 -7
- hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +402 -73
- hestia_earth/models/ipcc2019/{co2ToAirSoilOrganicCarbonStockChangeManagementChange.py → co2ToAirSoilOrganicCarbonStockChange.py} +20 -8
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +3 -1
- hestia_earth/models/ipcc2019/pastureGrass_utils.py +6 -7
- hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToFreshwaterEcosystemsWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthParticulateMatterFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToMarineEcosystemsMarineEutrophication.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffects100Years/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToFreshwaterEcosystemsWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthParticulateMatterFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToMarineEcosystemsMarineEutrophication.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactAllEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToFreshwaterEcosystemsWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthParticulateMatterFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToMarineEcosystemsMarineEutrophication.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffects100Years/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsFreshwaterEutrophication.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToFreshwaterEcosystemsWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthParticulateMatterFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToMarineEcosystemsMarineEutrophication.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsPhotochemicalOzoneFormation.py +2 -2
- hestia_earth/models/lcImpactCertainEffectsInfinite/damageToTerrestrialEcosystemsTerrestrialAcidification.py +2 -2
- hestia_earth/models/mocking/build_mock_search.py +44 -0
- hestia_earth/models/mocking/mock_search.py +8 -49
- hestia_earth/models/mocking/search-results.json +3078 -575
- hestia_earth/models/poschEtAl2008/terrestrialAcidificationPotentialAccumulatedExceedance.py +6 -3
- hestia_earth/models/poschEtAl2008/terrestrialEutrophicationPotentialAccumulatedExceedance.py +6 -3
- hestia_earth/models/preload_requests.py +1 -1
- hestia_earth/models/schmidt2007/utils.py +13 -4
- hestia_earth/models/utils/__init__.py +5 -4
- hestia_earth/models/utils/blank_node.py +73 -3
- hestia_earth/models/utils/constant.py +8 -1
- hestia_earth/models/utils/cycle.py +10 -13
- hestia_earth/models/utils/fuel.py +1 -1
- hestia_earth/models/utils/impact_assessment.py +39 -15
- hestia_earth/models/utils/lookup.py +36 -7
- hestia_earth/models/utils/pesticideAI.py +1 -1
- hestia_earth/models/utils/property.py +11 -4
- hestia_earth/models/utils/term.py +15 -8
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/METADATA +2 -2
- {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/RECORD +103 -90
- {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/WHEEL +1 -1
- tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +196 -0
- tests/models/cml2001Baseline/test_abioticResourceDepletionMineralsAndMetals.py +124 -0
- tests/models/edip2003/test_ozoneDepletionPotential.py +1 -13
- tests/models/environmentalFootprintV3/test_soilQualityIndexLandOccupation.py +97 -66
- tests/models/environmentalFootprintV3/test_soilQualityIndexLandTransformation.py +136 -74
- tests/models/environmentalFootprintV3/test_soilQualityIndexTotalLandUseEffects.py +15 -10
- tests/models/frischknechtEtAl2000/test_ionisingRadiationKbqU235Eq.py +67 -44
- tests/models/impact_assessment/test_emissions.py +1 -0
- tests/models/ipcc2019/animal/test_fatContent.py +22 -0
- tests/models/ipcc2019/animal/test_liveweightGain.py +4 -2
- tests/models/ipcc2019/animal/test_liveweightPerHead.py +4 -2
- tests/models/ipcc2019/animal/test_pregnancyRateTotal.py +22 -0
- tests/models/ipcc2019/animal/test_trueProteinContent.py +22 -0
- tests/models/ipcc2019/animal/test_weightAtMaturity.py +2 -1
- tests/models/ipcc2019/test_aboveGroundBiomass.py +27 -63
- tests/models/ipcc2019/test_belowGroundBiomass.py +146 -0
- tests/models/ipcc2019/test_biomass_utils.py +115 -0
- tests/models/ipcc2019/{test_co2ToAirAboveGroundBiomassStockChangeLandUseChange.py → test_co2ToAirAboveGroundBiomassStockChange.py} +5 -5
- tests/models/ipcc2019/{test_co2ToAirBelowGroundBiomassStockChangeLandUseChange.py → test_co2ToAirBelowGroundBiomassStockChange.py} +5 -5
- tests/models/ipcc2019/{test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py → test_co2ToAirSoilOrganicCarbonStockChange.py} +5 -5
- tests/models/ipcc2021/test_gwp100.py +2 -2
- tests/models/poschEtAl2008/test_terrestrialAcidificationPotentialAccumulatedExceedance.py +30 -17
- tests/models/poschEtAl2008/test_terrestrialEutrophicationPotentialAccumulatedExceedance.py +28 -14
- hestia_earth/models/ipcc2019/aboveGroundBiomass_utils.py +0 -180
- tests/models/ipcc2019/test_aboveGroundBiomass_utils.py +0 -92
- {hestia_earth_models-0.64.8.dist-info → hestia_earth_models-0.64.10.dist-info}/LICENSE +0 -0
- {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']
|
|
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
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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}/
|
|
35
|
-
|
|
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
|
|
79
|
-
CF METHOD factor:
|
|
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/
|
|
103
|
-
|
|
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}/
|
|
119
|
-
|
|
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
|
|
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
|