hestia-earth-models 0.57.2__py3-none-any.whl → 0.59.0__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/cycle/aboveGroundCropResidueTotal.py +17 -12
- hestia_earth/models/cycle/excretaKgMass.py +4 -5
- hestia_earth/models/cycle/excretaKgN.py +4 -5
- hestia_earth/models/cycle/excretaKgVs.py +4 -5
- hestia_earth/models/cycle/inorganicFertiliser.py +2 -2
- hestia_earth/models/cycle/{irrigated.py → irrigatedTypeUnspecified.py} +4 -4
- hestia_earth/models/cycle/liveAnimal.py +9 -11
- hestia_earth/models/cycle/milkYield.py +154 -0
- hestia_earth/models/cycle/residueIncorporated.py +1 -1
- hestia_earth/models/cycle/utils.py +6 -0
- hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +3 -3
- hestia_earth/models/faostat2018/seed.py +2 -3
- hestia_earth/models/geospatialDatabase/clayContent.py +17 -4
- hestia_earth/models/geospatialDatabase/sandContent.py +17 -4
- hestia_earth/models/geospatialDatabase/siltContent.py +2 -2
- hestia_earth/models/impact_assessment/irrigated.py +0 -3
- hestia_earth/models/ipcc2006/co2ToAirOrganicSoilCultivation.py +2 -2
- hestia_earth/models/ipcc2006/n2OToAirCropResidueDecompositionIndirect.py +2 -2
- hestia_earth/models/ipcc2006/n2OToAirExcretaDirect.py +1 -1
- hestia_earth/models/ipcc2006/n2OToAirExcretaIndirect.py +8 -4
- hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserDirect.py +4 -1
- hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserDirect.py +1 -1
- hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2006/utils.py +11 -8
- hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +4 -4
- hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +16 -7
- hestia_earth/models/ipcc2019/co2ToAirSoilCarbonStockChangeManagementChange.py +759 -0
- hestia_earth/models/ipcc2019/croppingDuration.py +12 -6
- hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionDirect.py +5 -52
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserDirect.py +104 -0
- hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserDirect.py +105 -0
- hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py +1 -1
- hestia_earth/models/ipcc2019/no3ToGroundwaterCropResidueDecomposition.py +1 -1
- hestia_earth/models/ipcc2019/no3ToGroundwaterExcreta.py +1 -1
- hestia_earth/models/ipcc2019/no3ToGroundwaterInorganicFertiliser.py +1 -1
- hestia_earth/models/ipcc2019/no3ToGroundwaterOrganicFertiliser.py +1 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +1088 -1268
- hestia_earth/models/ipcc2019/pastureGrass.py +4 -4
- hestia_earth/models/ipcc2019/utils.py +102 -1
- hestia_earth/models/koble2014/aboveGroundCropResidue.py +15 -17
- hestia_earth/models/koble2014/cropResidueManagement.py +2 -2
- hestia_earth/models/koble2014/utils.py +19 -3
- hestia_earth/models/linkedImpactAssessment/__init__.py +4 -2
- hestia_earth/models/log.py +15 -3
- hestia_earth/models/mocking/search-results.json +184 -118
- hestia_earth/models/pooreNemecek2018/excretaKgN.py +6 -7
- hestia_earth/models/pooreNemecek2018/excretaKgVs.py +7 -6
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterCropResidueDecomposition.py +3 -2
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterExcreta.py +3 -2
- hestia_earth/models/pooreNemecek2018/no3ToGroundwaterInorganicFertiliser.py +3 -2
- hestia_earth/models/pooreNemecek2018/saplings.py +0 -1
- hestia_earth/models/site/management.py +168 -0
- hestia_earth/models/site/organicCarbonPerHa.py +251 -89
- hestia_earth/models/stehfestBouwman2006/n2OToAirCropResidueDecompositionDirect.py +3 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirExcretaDirect.py +3 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirInorganicFertiliserDirect.py +3 -2
- hestia_earth/models/stehfestBouwman2006/n2OToAirOrganicFertiliserDirect.py +3 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirCropResidueDecomposition.py +3 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirExcreta.py +3 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirInorganicFertiliser.py +3 -2
- hestia_earth/models/stehfestBouwman2006/noxToAirOrganicFertiliser.py +3 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirCropResidueDecomposition.py +3 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirExcreta.py +3 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirInorganicFertiliser.py +3 -2
- hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirOrganicFertiliser.py +3 -2
- hestia_earth/models/utils/aggregated.py +1 -0
- hestia_earth/models/utils/blank_node.py +394 -72
- hestia_earth/models/utils/cropResidue.py +13 -0
- hestia_earth/models/utils/cycle.py +18 -9
- hestia_earth/models/utils/measurement.py +1 -1
- hestia_earth/models/utils/property.py +4 -4
- hestia_earth/models/utils/term.py +48 -3
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/METADATA +5 -9
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/RECORD +109 -97
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/WHEEL +1 -1
- tests/models/cycle/animal/input/test_hestiaAggregatedData.py +2 -14
- tests/models/cycle/input/test_hestiaAggregatedData.py +4 -16
- tests/models/cycle/test_coldCarcassWeightPerHead.py +1 -1
- tests/models/cycle/test_coldDressedCarcassWeightPerHead.py +1 -1
- tests/models/cycle/{test_irrigated.py → test_irrigatedTypeUnspecified.py} +1 -1
- tests/models/cycle/test_milkYield.py +58 -0
- tests/models/cycle/test_readyToCookWeightPerHead.py +1 -1
- tests/models/emepEea2019/test_nh3ToAirInorganicFertiliser.py +1 -1
- tests/models/geospatialDatabase/test_clayContent.py +9 -3
- tests/models/geospatialDatabase/test_sandContent.py +9 -3
- tests/models/ipcc2006/test_n2OToAirExcretaDirect.py +7 -2
- tests/models/ipcc2006/test_n2OToAirExcretaIndirect.py +1 -1
- tests/models/ipcc2006/test_n2OToAirInorganicFertiliserDirect.py +7 -2
- tests/models/ipcc2006/test_n2OToAirInorganicFertiliserIndirect.py +7 -2
- tests/models/ipcc2006/test_n2OToAirOrganicFertiliserDirect.py +7 -2
- tests/models/ipcc2006/test_n2OToAirOrganicFertiliserIndirect.py +7 -2
- tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +1 -1
- tests/models/ipcc2019/test_co2ToAirSoilCarbonStockChangeManagementChange.py +228 -0
- tests/models/ipcc2019/test_n2OToAirInorganicFertiliserDirect.py +74 -0
- tests/models/ipcc2019/test_n2OToAirOrganicFertiliserDirect.py +74 -0
- tests/models/ipcc2019/test_organicCarbonPerHa.py +303 -1044
- tests/models/koble2014/test_residueBurnt.py +1 -2
- tests/models/koble2014/test_residueLeftOnField.py +1 -2
- tests/models/koble2014/test_residueRemoved.py +1 -2
- tests/models/koble2014/test_utils.py +52 -0
- tests/models/site/test_management.py +117 -0
- tests/models/site/test_organicCarbonPerHa.py +51 -5
- tests/models/utils/test_blank_node.py +230 -34
- tests/models/utils/test_term.py +17 -3
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/top_level.txt +0 -0
|
@@ -1,24 +1,12 @@
|
|
|
1
|
-
from copy import deepcopy
|
|
2
1
|
from unittest.mock import patch
|
|
3
2
|
import json
|
|
4
3
|
from numpy.testing import assert_almost_equal
|
|
4
|
+
from pytest import mark
|
|
5
5
|
import random
|
|
6
|
-
from typing import (
|
|
7
|
-
NamedTuple,
|
|
8
|
-
Optional,
|
|
9
|
-
Union
|
|
10
|
-
)
|
|
11
|
-
from hestia_earth.schema import (
|
|
12
|
-
SiteSiteType,
|
|
13
|
-
TermTermType
|
|
14
|
-
)
|
|
15
6
|
|
|
16
7
|
from tests.utils import (
|
|
17
8
|
fixtures_path,
|
|
18
9
|
fake_new_measurement,
|
|
19
|
-
PROPERTY,
|
|
20
|
-
MANAGEMENT,
|
|
21
|
-
MEASUREMENT,
|
|
22
10
|
)
|
|
23
11
|
from hestia_earth.models.ipcc2019.organicCarbonPerHa import (
|
|
24
12
|
_assign_ipcc_carbon_input_category,
|
|
@@ -28,45 +16,19 @@ from hestia_earth.models.ipcc2019.organicCarbonPerHa import (
|
|
|
28
16
|
_calc_temperature_factor,
|
|
29
17
|
_calc_tier_1_soc_stocks,
|
|
30
18
|
_calc_water_factor,
|
|
31
|
-
_check_cropland_high_with_manure_category,
|
|
32
|
-
_check_cropland_high_without_manure_category,
|
|
33
19
|
_check_cropland_low_category,
|
|
34
20
|
_check_cropland_medium_category,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
CarbonSource,
|
|
38
|
-
CLAY_CONTENT_MAX,
|
|
39
|
-
CLAY_CONTENT_TERM_ID,
|
|
21
|
+
_get_carbon_input_kwargs,
|
|
22
|
+
_iterate_soc_equilibriums,
|
|
40
23
|
IpccCarbonInputCategory,
|
|
41
24
|
IpccLandUseCategory,
|
|
42
25
|
IpccManagementCategory,
|
|
43
26
|
IpccSoilCategory,
|
|
44
27
|
MODEL,
|
|
45
28
|
run,
|
|
46
|
-
SAND_CONTENT_MIN,
|
|
47
|
-
SAND_CONTENT_TERM_ID,
|
|
48
29
|
TERM_ID
|
|
49
30
|
)
|
|
50
31
|
|
|
51
|
-
|
|
52
|
-
TIER_2_SUBFOLDERS = [
|
|
53
|
-
'Tier2/with-generalised-monthly-measurements', # Closes issue 600
|
|
54
|
-
'Tier2/with-incomplete-climate-data', # Closes issue 599
|
|
55
|
-
'Tier2/with-initial-soc',
|
|
56
|
-
'Tier2/with-multi-year-cycles',
|
|
57
|
-
'Tier2/without-any-measurements', # Closes issue 594
|
|
58
|
-
'Tier2/without-initial-soc'
|
|
59
|
-
]
|
|
60
|
-
|
|
61
|
-
TIER_1_SUBFOLDERS = [
|
|
62
|
-
'Tier1/cropland-with-measured-soc',
|
|
63
|
-
'Tier1/cropland-without-measured-soc',
|
|
64
|
-
'Tier1/permanent-pasture',
|
|
65
|
-
'Tier1/should-not-run',
|
|
66
|
-
'Tier1/without-management-with-measured-soc',
|
|
67
|
-
'Tier1/cropland-depth-as-float'
|
|
68
|
-
]
|
|
69
|
-
|
|
70
32
|
class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
|
|
71
33
|
fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
|
|
72
34
|
|
|
@@ -87,10 +49,10 @@ CROP_RESIDUE_INCORP_TERM_IDS = [
|
|
|
87
49
|
]
|
|
88
50
|
|
|
89
51
|
IRRIGATED_TERM_IDS = [
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
52
|
+
"rainfedDeepWater",
|
|
53
|
+
"rainfedDeepWaterWaterDepth100Cm",
|
|
54
|
+
"rainfedDeepWaterWaterDepth50100Cm",
|
|
55
|
+
"irrigatedTypeUnspecified",
|
|
94
56
|
"irrigatedCenterPivotIrrigation",
|
|
95
57
|
"irrigatedContinuouslyFlooded",
|
|
96
58
|
"irrigatedDripIrrigation",
|
|
@@ -98,11 +60,16 @@ IRRIGATED_TERM_IDS = [
|
|
|
98
60
|
"irrigatedLateralMoveIrrigation",
|
|
99
61
|
"irrigatedLocalizedIrrigation",
|
|
100
62
|
"irrigatedManualIrrigation",
|
|
101
|
-
"
|
|
102
|
-
"
|
|
63
|
+
"irrigatedSurfaceIrrigationMultipleDrainagePeriods",
|
|
64
|
+
"irrigatedSurfaceIrrigationSingleDrainagePeriod",
|
|
103
65
|
"irrigatedSprinklerIrrigation",
|
|
104
66
|
"irrigatedSubIrrigation",
|
|
105
|
-
"
|
|
67
|
+
"irrigatedSurfaceIrrigationDrainageRegimeUnspecified"
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
LONG_FALLOW_LAND_COVER_TERM_IDS = [
|
|
71
|
+
"longFallow",
|
|
72
|
+
"longBareFallow"
|
|
106
73
|
]
|
|
107
74
|
|
|
108
75
|
RESIDUE_REMOVED_OR_BURNT_TERM_IDS = [
|
|
@@ -110,91 +77,95 @@ RESIDUE_REMOVED_OR_BURNT_TERM_IDS = [
|
|
|
110
77
|
"residueRemoved"
|
|
111
78
|
]
|
|
112
79
|
|
|
113
|
-
|
|
80
|
+
UPLAND_RICE_LAND_COVER_TERM_IDS = [
|
|
114
81
|
"ricePlantUpland"
|
|
115
82
|
]
|
|
116
83
|
|
|
117
|
-
|
|
84
|
+
UPLAND_RICE_CROP_TERM_IDS = [
|
|
85
|
+
"riceGrainInHuskUpland"
|
|
86
|
+
]
|
|
118
87
|
|
|
119
88
|
|
|
120
|
-
|
|
121
|
-
with open(path, encoding='utf-8') as f:
|
|
122
|
-
cycles = json.load(f)
|
|
123
|
-
return cycles
|
|
89
|
+
# --- TIER 1 & TIER 2 TESTS ---
|
|
124
90
|
|
|
125
91
|
|
|
126
|
-
#
|
|
92
|
+
# subfolder, load_cycles
|
|
93
|
+
RUN_SUBFOLDERS = [
|
|
94
|
+
("tier-1-and-2/cropland", True),
|
|
95
|
+
("tier-2/with-generalised-monthly-measurements", True), # Closes issue 600
|
|
96
|
+
("tier-2/with-incomplete-climate-data", True), # Closes issue 599
|
|
97
|
+
("tier-2/with-initial-soc", True),
|
|
98
|
+
("tier-2/with-multi-year-cycles", True),
|
|
99
|
+
("tier-2/without-any-measurements", True), # Closes issue 594
|
|
100
|
+
("tier-2/without-initial-soc", True),
|
|
101
|
+
("tier-2/with-irrigation", True),
|
|
102
|
+
("tier-2/with-irrigation-dates", True),
|
|
103
|
+
("tier-2/with-paddy-rice", True),
|
|
104
|
+
("tier-2/with-irrigated-upland-rice", True),
|
|
105
|
+
("tier-1/cropland-depth-as-float", False),
|
|
106
|
+
("tier-1/cropland-with-measured-soc", False),
|
|
107
|
+
("tier-1/cropland-without-measured-soc", False),
|
|
108
|
+
("tier-1/permanent-pasture", False),
|
|
109
|
+
("tier-1/should-not-run", False),
|
|
110
|
+
("tier-1/without-management-with-measured-soc", False)
|
|
111
|
+
]
|
|
127
112
|
|
|
128
113
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
114
|
+
@mark.parametrize(
|
|
115
|
+
"subfolder, load_cycles",
|
|
116
|
+
RUN_SUBFOLDERS,
|
|
117
|
+
ids=[params[0] for params in RUN_SUBFOLDERS]
|
|
118
|
+
)
|
|
119
|
+
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
120
|
+
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
121
|
+
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
122
|
+
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
123
|
+
@patch(f"{class_path}.get_long_fallow_land_cover_terms", return_value=LONG_FALLOW_LAND_COVER_TERM_IDS)
|
|
124
|
+
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
125
|
+
@patch(f"{class_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
126
|
+
@patch(f"{class_path}.get_upland_rice_crop_terms", return_value=UPLAND_RICE_CROP_TERM_IDS)
|
|
127
|
+
@patch(f"{class_path}.related_cycles")
|
|
128
|
+
def test_run(
|
|
129
|
+
mock_related_cycles,
|
|
130
|
+
_mock_get_upland_rice_crop_terms,
|
|
131
|
+
_mock_get_upland_rice_land_cover_terms,
|
|
132
|
+
_mock_get_residue_removed_or_burnt_terms,
|
|
133
|
+
_mock_get_long_fallow_land_cover_terms,
|
|
134
|
+
_mock_get_irrigated_terms,
|
|
135
|
+
_mock_get_crop_residue_incorporated_or_left_on_field_terms,
|
|
136
|
+
_mock_get_cover_crop_property_terms,
|
|
137
|
+
_mock_new_measurement,
|
|
138
|
+
subfolder,
|
|
139
|
+
load_cycles
|
|
153
140
|
):
|
|
154
|
-
|
|
155
|
-
node['term']['@id'] = term_id
|
|
156
|
-
node['term']['termType'] = term_type.value
|
|
157
|
-
node['value'] = (
|
|
158
|
-
value[0] if isinstance(value, list) else value
|
|
159
|
-
)
|
|
160
|
-
if properties:
|
|
161
|
-
node['properties'] = (
|
|
162
|
-
properties if isinstance(properties, list) else [properties]
|
|
163
|
-
)
|
|
164
|
-
return node
|
|
141
|
+
folder = f"{fixtures_folder}/{subfolder}"
|
|
165
142
|
|
|
143
|
+
def load_cycles_from_file():
|
|
144
|
+
with open(f"{folder}/cycles.jsonld", encoding='utf-8') as f:
|
|
145
|
+
return json.load(f)
|
|
166
146
|
|
|
167
|
-
|
|
168
|
-
term_id: str,
|
|
169
|
-
value: Union[float, bool],
|
|
170
|
-
):
|
|
171
|
-
node = deepcopy(PROPERTY)
|
|
172
|
-
node['term']['@id'] = term_id
|
|
173
|
-
node['term']['termType'] = TermTermType.PROPERTY.value
|
|
174
|
-
node['value'] = (
|
|
175
|
-
value[0] if isinstance(value, list) else value
|
|
176
|
-
)
|
|
177
|
-
return node
|
|
147
|
+
mock_related_cycles.return_value = load_cycles_from_file() if load_cycles else []
|
|
178
148
|
|
|
149
|
+
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
150
|
+
site = json.load(f)
|
|
179
151
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
('soc_equilibriums', list[float]),
|
|
183
|
-
('expected', list[float])
|
|
184
|
-
])
|
|
185
|
-
|
|
152
|
+
with open(f"{folder}/result.jsonld", encoding='utf-8') as f:
|
|
153
|
+
expected = json.load(f)
|
|
186
154
|
|
|
187
|
-
|
|
155
|
+
result = run(site)
|
|
156
|
+
assert result == expected
|
|
188
157
|
|
|
189
158
|
|
|
190
159
|
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
191
160
|
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
192
161
|
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
193
162
|
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
163
|
+
@patch(f"{class_path}.get_long_fallow_land_cover_terms", return_value=LONG_FALLOW_LAND_COVER_TERM_IDS)
|
|
194
164
|
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
195
|
-
@patch(f"{class_path}.
|
|
165
|
+
@patch(f"{class_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
166
|
+
@patch(f"{class_path}.get_upland_rice_crop_terms", return_value=UPLAND_RICE_CROP_TERM_IDS)
|
|
196
167
|
@patch(f"{class_path}.related_cycles", return_value=[])
|
|
197
|
-
def
|
|
168
|
+
def test_run_no_data(*args):
|
|
198
169
|
SITE = {}
|
|
199
170
|
EXPECTED = []
|
|
200
171
|
result = run(SITE)
|
|
@@ -238,1012 +209,300 @@ def test_calc_water_factor():
|
|
|
238
209
|
assert _calc_water_factor(1, 1) == _calc_water_factor(1000, 1000)
|
|
239
210
|
|
|
240
211
|
|
|
241
|
-
|
|
242
|
-
"""
|
|
243
|
-
Test the _run_annual_organic_carbon_inputs model:
|
|
244
|
-
|
|
245
|
-
As the IPCC don't provide any test data, we can generate some random inputs and test that the results
|
|
246
|
-
fall within the minimum and maximum bounds.
|
|
247
|
-
"""
|
|
248
|
-
NUM_YEARS = 9999
|
|
249
|
-
MIN_SOURCES, MAX_SOURCES = 0, 99
|
|
250
|
-
MIN_MASS, MAX_MASS = 0, 9999
|
|
251
|
-
MIN_C, MAX_C = 0.1, 0.5
|
|
252
|
-
MIN_N, MAX_N = 0.001, 0.01
|
|
253
|
-
MIN_LIG, MAX_LIG = 0.01, 0.1
|
|
254
|
-
|
|
255
|
-
min_c_input = MIN_MASS * MIN_C * MIN_SOURCES
|
|
256
|
-
max_c_input = MAX_MASS * MAX_C * MAX_SOURCES
|
|
257
|
-
|
|
258
|
-
def generate_random_carbon_sources():
|
|
259
|
-
return [
|
|
260
|
-
CarbonSource(
|
|
261
|
-
mass=random.uniform(MIN_MASS, MAX_MASS),
|
|
262
|
-
carbon_content=random.uniform(MIN_C, MAX_C),
|
|
263
|
-
nitrogen_content=random.uniform(MIN_N, MAX_N),
|
|
264
|
-
lignin_content=random.uniform(MIN_LIG, MAX_LIG)
|
|
265
|
-
) for _ in range(0, random.randint(MIN_SOURCES, MAX_SOURCES))
|
|
266
|
-
]
|
|
267
|
-
|
|
268
|
-
timestamps = list(range(0, NUM_YEARS))
|
|
269
|
-
annual_carbon_sources = [
|
|
270
|
-
generate_random_carbon_sources() for _ in timestamps
|
|
271
|
-
]
|
|
272
|
-
|
|
273
|
-
result = _run_annual_organic_carbon_inputs(
|
|
274
|
-
timestamps,
|
|
275
|
-
annual_carbon_sources
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
for i in range(0, NUM_YEARS):
|
|
279
|
-
assert result.timestamps[i] == timestamps[i]
|
|
280
|
-
assert min_c_input <= result.organic_carbon_inputs[i] <= max_c_input
|
|
281
|
-
assert MIN_N <= result.average_nitrogen_contents[i] <= MAX_N
|
|
282
|
-
assert MIN_LIG <= result.average_lignin_contents[i] <= MAX_LIG
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
# --- TIER 2 TESTS: SOC MODEL ---
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
289
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
290
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
291
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
292
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
293
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
294
|
-
@patch(f"{class_path}.related_cycles")
|
|
295
|
-
def test_run_tier_2_with_generalised_monthly_measurements(mock_related_cycles, *args):
|
|
296
|
-
"""
|
|
297
|
-
Test for sites with monthly climate measurements (e.g., `precipitationMonthly`) with dates in the format `--MM`.
|
|
298
|
-
|
|
299
|
-
Tier 2 model should not run, as monthly climate measurements must be associated with a year and a month in the
|
|
300
|
-
format `YYYY-MM`. Therefore, `run` function is expected to return an empty list `[]`.
|
|
301
|
-
"""
|
|
302
|
-
|
|
303
|
-
SUBFOLDER = TIER_2_SUBFOLDERS[0]
|
|
304
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
305
|
-
|
|
306
|
-
mock_related_cycles.return_value = _load_cycles(f"{folder}/cycles.jsonld")
|
|
307
|
-
|
|
308
|
-
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
309
|
-
site = json.load(f)
|
|
310
|
-
|
|
311
|
-
result = run(site)
|
|
312
|
-
assert result == []
|
|
212
|
+
# --- IPCC SOIL CATEGORY TESTS ---
|
|
313
213
|
|
|
314
214
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
215
|
+
# subfolder, expected
|
|
216
|
+
SOIL_CATEGORY_PARAMS = [
|
|
217
|
+
("fractional", IpccSoilCategory.WETLAND_SOILS),
|
|
218
|
+
("no-measurements", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS),
|
|
219
|
+
("sandy-override", IpccSoilCategory.SANDY_SOILS),
|
|
220
|
+
("soilType/hac", IpccSoilCategory.HIGH_ACTIVITY_CLAY_SOILS),
|
|
221
|
+
("soilType/lac", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS),
|
|
222
|
+
("soilType/org", IpccSoilCategory.ORGANIC_SOILS),
|
|
223
|
+
("soilType/pod", IpccSoilCategory.SPODIC_SOILS),
|
|
224
|
+
("soilType/san", IpccSoilCategory.SANDY_SOILS),
|
|
225
|
+
("soilType/vol", IpccSoilCategory.VOLCANIC_SOILS),
|
|
226
|
+
("soilType/wet", IpccSoilCategory.WETLAND_SOILS),
|
|
227
|
+
("usdaSoilType/hac", IpccSoilCategory.HIGH_ACTIVITY_CLAY_SOILS),
|
|
228
|
+
("usdaSoilType/lac", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS),
|
|
229
|
+
("usdaSoilType/org", IpccSoilCategory.ORGANIC_SOILS),
|
|
230
|
+
("usdaSoilType/pod", IpccSoilCategory.SPODIC_SOILS),
|
|
231
|
+
("usdaSoilType/san", IpccSoilCategory.SANDY_SOILS),
|
|
232
|
+
("usdaSoilType/vol", IpccSoilCategory.VOLCANIC_SOILS),
|
|
233
|
+
("usdaSoilType/wet", IpccSoilCategory.WETLAND_SOILS)
|
|
234
|
+
]
|
|
323
235
|
|
|
324
|
-
SUBFOLDER = TIER_2_SUBFOLDERS[1]
|
|
325
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
326
236
|
|
|
327
|
-
|
|
237
|
+
@mark.parametrize(
|
|
238
|
+
"subfolder, expected",
|
|
239
|
+
SOIL_CATEGORY_PARAMS,
|
|
240
|
+
ids=[params[0] for params in SOIL_CATEGORY_PARAMS]
|
|
241
|
+
)
|
|
242
|
+
def test_assign_ipcc_soil_category(subfolder, expected):
|
|
243
|
+
folder = f"{fixtures_folder}/IpccSoilCategory/{subfolder}"
|
|
328
244
|
|
|
329
245
|
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
330
246
|
site = json.load(f)
|
|
331
247
|
|
|
332
|
-
result =
|
|
333
|
-
assert result ==
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
337
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
338
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
339
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
340
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
341
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
342
|
-
@patch(f"{class_path}.related_cycles")
|
|
343
|
-
def test_run_tier_2_with_initial_soc(mock_related_cycles, *args):
|
|
248
|
+
result = _assign_ipcc_soil_category(site.get("measurements", []))
|
|
249
|
+
assert result == expected
|
|
344
250
|
|
|
345
|
-
SUBFOLDER = TIER_2_SUBFOLDERS[2]
|
|
346
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
347
251
|
|
|
348
|
-
|
|
252
|
+
# --- IPCC LAND USE CATEGORY TESTS ---
|
|
349
253
|
|
|
350
|
-
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
351
|
-
site = json.load(f)
|
|
352
254
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
255
|
+
# subfolder, soil_category, expected
|
|
256
|
+
LAND_USE_CATEGORY_PARAMS = [
|
|
257
|
+
("annual-crops", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.ANNUAL_CROPS),
|
|
258
|
+
("annual-crops-wet", IpccSoilCategory.WETLAND_SOILS, IpccLandUseCategory.ANNUAL_CROPS_WET),
|
|
259
|
+
("forest", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.FOREST),
|
|
260
|
+
("fractional", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.PERENNIAL_CROPS),
|
|
261
|
+
("grassland", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.GRASSLAND),
|
|
262
|
+
("irrigated-upland-rice", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.PADDY_RICE_CULTIVATION),
|
|
263
|
+
("native", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.NATIVE),
|
|
264
|
+
("other", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.OTHER),
|
|
265
|
+
("paddy-rice-cultivation", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.PADDY_RICE_CULTIVATION),
|
|
266
|
+
("perennial-crops", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.PERENNIAL_CROPS),
|
|
267
|
+
("set-aside", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.SET_ASIDE),
|
|
268
|
+
("set-aside-override", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.SET_ASIDE),
|
|
269
|
+
("upland-rice", IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS, IpccLandUseCategory.ANNUAL_CROPS),
|
|
270
|
+
]
|
|
358
271
|
|
|
359
272
|
|
|
360
|
-
@
|
|
361
|
-
|
|
362
|
-
|
|
273
|
+
@mark.parametrize(
|
|
274
|
+
"subfolder, soil_category, expected",
|
|
275
|
+
LAND_USE_CATEGORY_PARAMS,
|
|
276
|
+
ids=[params[0] for params in LAND_USE_CATEGORY_PARAMS]
|
|
277
|
+
)
|
|
363
278
|
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
364
|
-
@patch(f"{class_path}.
|
|
365
|
-
@patch(f"{class_path}.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
279
|
+
@patch(f"{class_path}.get_long_fallow_land_cover_terms", return_value=LONG_FALLOW_LAND_COVER_TERM_IDS)
|
|
280
|
+
@patch(f"{class_path}.get_upland_rice_land_cover_terms", return_value=UPLAND_RICE_LAND_COVER_TERM_IDS)
|
|
281
|
+
def test_assign_ipcc_land_use_category(
|
|
282
|
+
_mock_get_upland_rice_land_cover_terms,
|
|
283
|
+
_mock_get_long_fallow_land_cover_terms,
|
|
284
|
+
_mock_get_irrigated_terms,
|
|
285
|
+
subfolder,
|
|
286
|
+
soil_category,
|
|
287
|
+
expected
|
|
288
|
+
):
|
|
289
|
+
folder = f"{fixtures_folder}/IpccLandUseCategory/{subfolder}"
|
|
373
290
|
|
|
374
291
|
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
375
292
|
site = json.load(f)
|
|
376
293
|
|
|
377
|
-
|
|
378
|
-
expected = json.load(f)
|
|
379
|
-
|
|
380
|
-
result = run(site)
|
|
294
|
+
result = _assign_ipcc_land_use_category(site.get("siteType"), site.get("management", []), soil_category)
|
|
381
295
|
assert result == expected
|
|
382
296
|
|
|
383
297
|
|
|
384
|
-
|
|
385
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
386
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
387
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
388
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
389
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
390
|
-
@patch(f"{class_path}.related_cycles")
|
|
391
|
-
def test_run_tier_2_without_any_measurements(mock_related_cycles, *args):
|
|
392
|
-
|
|
393
|
-
SUBFOLDER = TIER_2_SUBFOLDERS[4]
|
|
394
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
395
|
-
|
|
396
|
-
mock_related_cycles.return_value = _load_cycles(f"{folder}/cycles.jsonld")
|
|
397
|
-
|
|
398
|
-
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
399
|
-
site = json.load(f)
|
|
400
|
-
|
|
401
|
-
result = run(site)
|
|
402
|
-
assert result == []
|
|
298
|
+
# --- IPCC MANAGEMENT CATEGORY TESTS ---
|
|
403
299
|
|
|
404
300
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
301
|
+
# subfolder, land_use_category, expected
|
|
302
|
+
MANAGEMENT_CATEGORY_PARAMS = [
|
|
303
|
+
("fractional-annual-crops", IpccLandUseCategory.ANNUAL_CROPS, IpccManagementCategory.REDUCED_TILLAGE),
|
|
304
|
+
("fractional-annual-crops-wet", IpccLandUseCategory.ANNUAL_CROPS_WET, IpccManagementCategory.REDUCED_TILLAGE),
|
|
305
|
+
("fractional-grassland", IpccLandUseCategory.GRASSLAND, IpccManagementCategory.IMPROVED_GRASSLAND),
|
|
306
|
+
("full-tillage", IpccLandUseCategory.ANNUAL_CROPS, IpccManagementCategory.FULL_TILLAGE),
|
|
307
|
+
("high-intensity-grazing", IpccLandUseCategory.GRASSLAND, IpccManagementCategory.HIGH_INTENSITY_GRAZING),
|
|
308
|
+
("improved-grassland", IpccLandUseCategory.GRASSLAND, IpccManagementCategory.IMPROVED_GRASSLAND),
|
|
309
|
+
("no-management/annual-crops", IpccLandUseCategory.ANNUAL_CROPS, IpccManagementCategory.FULL_TILLAGE),
|
|
310
|
+
("no-management/annual-crops-wet", IpccLandUseCategory.ANNUAL_CROPS_WET, IpccManagementCategory.FULL_TILLAGE),
|
|
311
|
+
("no-management/grassland", IpccLandUseCategory.GRASSLAND, IpccManagementCategory.NOMINALLY_MANAGED),
|
|
312
|
+
("no-tillage", IpccLandUseCategory.ANNUAL_CROPS, IpccManagementCategory.NO_TILLAGE),
|
|
313
|
+
("nominally-managed", IpccLandUseCategory.GRASSLAND, IpccManagementCategory.NOMINALLY_MANAGED),
|
|
314
|
+
("other", IpccLandUseCategory.OTHER, IpccManagementCategory.OTHER),
|
|
315
|
+
("reduced-tillage", IpccLandUseCategory.ANNUAL_CROPS, IpccManagementCategory.REDUCED_TILLAGE),
|
|
316
|
+
("severely-degraded", IpccLandUseCategory.GRASSLAND, IpccManagementCategory.SEVERELY_DEGRADED),
|
|
317
|
+
]
|
|
413
318
|
|
|
414
|
-
SUBFOLDER = TIER_2_SUBFOLDERS[5]
|
|
415
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
416
319
|
|
|
417
|
-
|
|
320
|
+
@mark.parametrize(
|
|
321
|
+
"subfolder, land_use_category, expected",
|
|
322
|
+
MANAGEMENT_CATEGORY_PARAMS,
|
|
323
|
+
ids=[params[0] for params in MANAGEMENT_CATEGORY_PARAMS]
|
|
324
|
+
)
|
|
325
|
+
def test_assign_ipcc_management_category(subfolder, land_use_category, expected):
|
|
326
|
+
folder = f"{fixtures_folder}/IpccManagementCategory/{subfolder}"
|
|
418
327
|
|
|
419
328
|
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
420
329
|
site = json.load(f)
|
|
421
330
|
|
|
422
|
-
|
|
423
|
-
expected = json.load(f)
|
|
424
|
-
|
|
425
|
-
result = run(site)
|
|
331
|
+
result = _assign_ipcc_management_category(site.get("management", []), land_use_category)
|
|
426
332
|
assert result == expected
|
|
427
333
|
|
|
428
334
|
|
|
429
|
-
# --- IPCC SOIL CATEGORY TESTS ---
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
EXPECTED_IPCC_SOIL_CATEGORY_TO_SOIL_TYPE_TERM_IDS = {
|
|
433
|
-
IpccSoilCategory.ORGANIC_SOILS: 'histosol',
|
|
434
|
-
IpccSoilCategory.SANDY_SOILS: 'arenosols',
|
|
435
|
-
IpccSoilCategory.WETLAND_SOILS: 'gleysols',
|
|
436
|
-
IpccSoilCategory.VOLCANIC_SOILS: 'andosols',
|
|
437
|
-
IpccSoilCategory.SPODIC_SOILS: 'podzols',
|
|
438
|
-
IpccSoilCategory.HIGH_ACTIVITY_CLAY_SOILS: 'alisols',
|
|
439
|
-
IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS: 'cryosols'
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
EXPECTED_IPCC_SOIL_CATEGORY_TO_USDA_SOIL_TYPE_TERM_IDS = {
|
|
443
|
-
IpccSoilCategory.ORGANIC_SOILS: 'histosols',
|
|
444
|
-
IpccSoilCategory.SANDY_SOILS: 'psamments',
|
|
445
|
-
IpccSoilCategory.WETLAND_SOILS: 'aquicCalcixerepts',
|
|
446
|
-
IpccSoilCategory.VOLCANIC_SOILS: 'andisols',
|
|
447
|
-
IpccSoilCategory.SPODIC_SOILS: 'spodosols',
|
|
448
|
-
IpccSoilCategory.HIGH_ACTIVITY_CLAY_SOILS: 'vertisols',
|
|
449
|
-
IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS: 'alfisols'
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
def test_assign_ipcc_soil_category_standard_cases():
|
|
454
|
-
|
|
455
|
-
# soilType
|
|
456
|
-
for expected, term_id in EXPECTED_IPCC_SOIL_CATEGORY_TO_SOIL_TYPE_TERM_IDS.items():
|
|
457
|
-
measurements = [
|
|
458
|
-
fake_measurement(term_id, [100], TermTermType.SOILTYPE)
|
|
459
|
-
]
|
|
460
|
-
result = _assign_ipcc_soil_category(measurements)
|
|
461
|
-
|
|
462
|
-
assert result == expected
|
|
463
|
-
|
|
464
|
-
# usdaSoilType
|
|
465
|
-
for expected, term_id in EXPECTED_IPCC_SOIL_CATEGORY_TO_USDA_SOIL_TYPE_TERM_IDS.items():
|
|
466
|
-
measurements = [
|
|
467
|
-
fake_measurement(term_id, [100], TermTermType.USDASOILTYPE)
|
|
468
|
-
]
|
|
469
|
-
result = _assign_ipcc_soil_category(measurements)
|
|
470
|
-
|
|
471
|
-
assert result == expected
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
def test_assign_ipcc_soil_category_fractional_case():
|
|
475
|
-
|
|
476
|
-
EXPECTED = IpccSoilCategory.WETLAND_SOILS
|
|
477
|
-
USDA_SOIL_CATEGORY_TERM_IDS = [
|
|
478
|
-
'aquicCalcixerepts', # WET
|
|
479
|
-
'aquicXeropsamments', # WET
|
|
480
|
-
'aquicFraglossudalfs', # WET
|
|
481
|
-
'vertisols' # HAC
|
|
482
|
-
]
|
|
483
|
-
|
|
484
|
-
measurements = [
|
|
485
|
-
fake_measurement(term_id, [100/len(USDA_SOIL_CATEGORY_TERM_IDS)], TermTermType.USDASOILTYPE)
|
|
486
|
-
for term_id in USDA_SOIL_CATEGORY_TERM_IDS
|
|
487
|
-
]
|
|
488
|
-
result = _assign_ipcc_soil_category(measurements)
|
|
489
|
-
|
|
490
|
-
assert result == EXPECTED
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
def test_assign_ipcc_soil_category_sandy_override_case():
|
|
494
|
-
|
|
495
|
-
EXPECTED = IpccSoilCategory.SANDY_SOILS
|
|
496
|
-
LAC_SOIL_TYPE_TERM_ID = (
|
|
497
|
-
EXPECTED_IPCC_SOIL_CATEGORY_TO_SOIL_TYPE_TERM_IDS[IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS]
|
|
498
|
-
)
|
|
499
|
-
|
|
500
|
-
# `soilType` and/or `usdaSoilType` overridden by sand and clay content
|
|
501
|
-
measurements = [
|
|
502
|
-
fake_measurement(LAC_SOIL_TYPE_TERM_ID, [100], TermTermType.SOILTYPE),
|
|
503
|
-
fake_measurement(CLAY_CONTENT_TERM_ID, [CLAY_CONTENT_MAX-1], TermTermType.MEASUREMENT),
|
|
504
|
-
fake_measurement(SAND_CONTENT_TERM_ID, [SAND_CONTENT_MIN+1], TermTermType.MEASUREMENT)
|
|
505
|
-
]
|
|
506
|
-
result = _assign_ipcc_soil_category(measurements)
|
|
507
|
-
|
|
508
|
-
assert result == EXPECTED
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
def test_assign_ipcc_soil_category_no_measurements_case():
|
|
512
|
-
|
|
513
|
-
EXPECTED = IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS
|
|
514
|
-
|
|
515
|
-
measurements = []
|
|
516
|
-
result = _assign_ipcc_soil_category(measurements)
|
|
517
|
-
|
|
518
|
-
assert result == EXPECTED
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
# --- IPCC LAND USE CATEGORY TESTS ---
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
EXPECTED_IPCC_LAND_USE_CATEGORY_TO_SITE_TYPE = {
|
|
525
|
-
IpccLandUseCategory.GRASSLAND: SiteSiteType.PERMANENT_PASTURE.value,
|
|
526
|
-
IpccLandUseCategory.FOREST: SiteSiteType.FOREST.value,
|
|
527
|
-
IpccLandUseCategory.SET_ASIDE: SiteSiteType.CROPLAND.value,
|
|
528
|
-
IpccLandUseCategory.NATIVE: SiteSiteType.OTHER_NATURAL_VEGETATION.value,
|
|
529
|
-
IpccLandUseCategory.OTHER: SiteSiteType.AGRI_FOOD_PROCESSOR,
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
EXPECTED_IPCC_LAND_USE_CATEGORY_TO_LAND_COVER_TERM_ID = {
|
|
533
|
-
IpccLandUseCategory.PERENNIAL_CROPS: 'grapesVine',
|
|
534
|
-
IpccLandUseCategory.PADDY_RICE_CULTIVATION: 'ricePlantFlooded',
|
|
535
|
-
IpccLandUseCategory.ANNUAL_CROPS: 'kalePlant',
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
SITE_TYPE_CROPLAND = SiteSiteType.CROPLAND.value
|
|
539
|
-
IPCC_SOIL_CATEGORY_LAC = IpccSoilCategory.LOW_ACTIVITY_CLAY_SOILS
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
543
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
544
|
-
def test_assign_ipcc_land_use_category_standard_cases(*args):
|
|
545
|
-
# site type only
|
|
546
|
-
for expected, site_type in EXPECTED_IPCC_LAND_USE_CATEGORY_TO_SITE_TYPE.items():
|
|
547
|
-
|
|
548
|
-
management_nodes = []
|
|
549
|
-
result = _assign_ipcc_land_use_category(
|
|
550
|
-
site_type,
|
|
551
|
-
management_nodes,
|
|
552
|
-
IPCC_SOIL_CATEGORY_LAC
|
|
553
|
-
)
|
|
554
|
-
|
|
555
|
-
assert result == expected
|
|
556
|
-
|
|
557
|
-
# site type `cropland` and land cover
|
|
558
|
-
for expected, term_id in EXPECTED_IPCC_LAND_USE_CATEGORY_TO_LAND_COVER_TERM_ID.items():
|
|
559
|
-
|
|
560
|
-
management_nodes = [
|
|
561
|
-
fake_management(
|
|
562
|
-
term_id,
|
|
563
|
-
100,
|
|
564
|
-
TermTermType.LANDCOVER
|
|
565
|
-
)
|
|
566
|
-
]
|
|
567
|
-
result = _assign_ipcc_land_use_category(
|
|
568
|
-
SITE_TYPE_CROPLAND,
|
|
569
|
-
management_nodes,
|
|
570
|
-
IPCC_SOIL_CATEGORY_LAC
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
assert result == expected
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
577
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
578
|
-
def test_assign_ipcc_land_use_category_fractional_case(*args):
|
|
579
|
-
EXPECTED = IpccLandUseCategory.PERENNIAL_CROPS
|
|
580
|
-
LAND_COVER_TERM_IDS = [
|
|
581
|
-
'appleTree', # PERENNIAL_CROPS
|
|
582
|
-
'apricotTree', # PERENNIAL_CROPS
|
|
583
|
-
'wheatPlant', # ANNUAL_CROPS
|
|
584
|
-
'barleyPlant' # ANNUAL_CROPS
|
|
585
|
-
]
|
|
586
|
-
|
|
587
|
-
management_nodes = [
|
|
588
|
-
fake_management(
|
|
589
|
-
term_id, 100/len(LAND_COVER_TERM_IDS), TermTermType.LANDCOVER
|
|
590
|
-
) for term_id in LAND_COVER_TERM_IDS
|
|
591
|
-
]
|
|
592
|
-
result = _assign_ipcc_land_use_category(
|
|
593
|
-
SITE_TYPE_CROPLAND,
|
|
594
|
-
management_nodes,
|
|
595
|
-
IPCC_SOIL_CATEGORY_LAC
|
|
596
|
-
)
|
|
597
|
-
|
|
598
|
-
assert result == EXPECTED
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
602
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
603
|
-
def test_assign_ipcc_land_use_category_annual_crops_wet_case(*args):
|
|
604
|
-
EXPECTED = IpccLandUseCategory.ANNUAL_CROPS_WET
|
|
605
|
-
IPCC_SOIL_CATEGORY_WET = IpccSoilCategory.WETLAND_SOILS
|
|
606
|
-
|
|
607
|
-
management_nodes = [
|
|
608
|
-
fake_management(
|
|
609
|
-
EXPECTED_IPCC_LAND_USE_CATEGORY_TO_LAND_COVER_TERM_ID[IpccLandUseCategory.ANNUAL_CROPS],
|
|
610
|
-
100,
|
|
611
|
-
TermTermType.LANDCOVER
|
|
612
|
-
)
|
|
613
|
-
]
|
|
614
|
-
|
|
615
|
-
result = _assign_ipcc_land_use_category(
|
|
616
|
-
SITE_TYPE_CROPLAND,
|
|
617
|
-
management_nodes,
|
|
618
|
-
IPCC_SOIL_CATEGORY_WET
|
|
619
|
-
)
|
|
620
|
-
assert result == EXPECTED
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
624
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
625
|
-
def test_assign_ipcc_land_use_category_set_aside_case(*args):
|
|
626
|
-
EXPECTED = IpccLandUseCategory.SET_ASIDE
|
|
627
|
-
WHITE_CLOVER_PLANT_TERM_ID = 'whiteCloverPlant'
|
|
628
|
-
LONG_FALLOW_CROP_TERM_ID = 'longFallowCrop'
|
|
629
|
-
|
|
630
|
-
management_nodes = [
|
|
631
|
-
fake_management(
|
|
632
|
-
WHITE_CLOVER_PLANT_TERM_ID,
|
|
633
|
-
100,
|
|
634
|
-
TermTermType.LANDCOVER,
|
|
635
|
-
properties=[
|
|
636
|
-
fake_property(
|
|
637
|
-
LONG_FALLOW_CROP_TERM_ID,
|
|
638
|
-
True
|
|
639
|
-
)
|
|
640
|
-
]
|
|
641
|
-
)
|
|
642
|
-
]
|
|
643
|
-
|
|
644
|
-
result = _assign_ipcc_land_use_category(
|
|
645
|
-
SITE_TYPE_CROPLAND,
|
|
646
|
-
management_nodes,
|
|
647
|
-
IPCC_SOIL_CATEGORY_LAC
|
|
648
|
-
)
|
|
649
|
-
|
|
650
|
-
assert result == EXPECTED
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
654
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
655
|
-
def test_assign_ipcc_land_use_category_upland_rice_cases(*args):
|
|
656
|
-
EXPECTED_IRRIGATED = IpccLandUseCategory.PADDY_RICE_CULTIVATION
|
|
657
|
-
EXPECTED_NOT_IRRIGATED = IpccLandUseCategory.ANNUAL_CROPS
|
|
658
|
-
|
|
659
|
-
RICE_PLANT_UPLAND_TERM_ID = 'ricePlantUpland'
|
|
660
|
-
IRRIGATED_TERM_ID = 'irrigated'
|
|
661
|
-
|
|
662
|
-
# Irrigated upland rice
|
|
663
|
-
management_nodes_irrigated = [
|
|
664
|
-
fake_management(
|
|
665
|
-
RICE_PLANT_UPLAND_TERM_ID, 100, TermTermType.LANDCOVER
|
|
666
|
-
),
|
|
667
|
-
fake_management(
|
|
668
|
-
IRRIGATED_TERM_ID, 100, TermTermType.WATERREGIME
|
|
669
|
-
)
|
|
670
|
-
]
|
|
671
|
-
result_irrigated = _assign_ipcc_land_use_category(
|
|
672
|
-
SITE_TYPE_CROPLAND,
|
|
673
|
-
management_nodes_irrigated,
|
|
674
|
-
IPCC_SOIL_CATEGORY_LAC
|
|
675
|
-
)
|
|
676
|
-
|
|
677
|
-
assert result_irrigated == EXPECTED_IRRIGATED
|
|
678
|
-
|
|
679
|
-
# Not irrigated upland rice
|
|
680
|
-
management_nodes_not_irrigated = [
|
|
681
|
-
fake_management(
|
|
682
|
-
RICE_PLANT_UPLAND_TERM_ID, 100, TermTermType.LANDCOVER
|
|
683
|
-
)
|
|
684
|
-
]
|
|
685
|
-
result_not_irrigated = _assign_ipcc_land_use_category(
|
|
686
|
-
SITE_TYPE_CROPLAND,
|
|
687
|
-
management_nodes_not_irrigated,
|
|
688
|
-
IPCC_SOIL_CATEGORY_LAC
|
|
689
|
-
)
|
|
690
|
-
|
|
691
|
-
assert result_not_irrigated == EXPECTED_NOT_IRRIGATED
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
695
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
696
|
-
def test_assign_ipcc_land_use_category_no_site_type_case(*args):
|
|
697
|
-
EXPECTED = IpccLandUseCategory.OTHER
|
|
698
|
-
SITE_TYPE = None
|
|
699
|
-
MANAGEMENT_NODES = []
|
|
700
|
-
|
|
701
|
-
result = _assign_ipcc_land_use_category(
|
|
702
|
-
SITE_TYPE, MANAGEMENT_NODES, IPCC_SOIL_CATEGORY_LAC
|
|
703
|
-
)
|
|
704
|
-
|
|
705
|
-
assert result == EXPECTED
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
# --- IPCC MANAGEMENT CATEGORY TESTS ---
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
EXPECTED_IPCC_MANAGEMENT_CATEGORY_TO_LAND_COVER_TERM_ID = {
|
|
712
|
-
IpccManagementCategory.SEVERELY_DEGRADED: 'severelyDegradedPasture',
|
|
713
|
-
IpccManagementCategory.IMPROVED_GRASSLAND: 'improvedPasture',
|
|
714
|
-
IpccManagementCategory.HIGH_INTENSITY_GRAZING: 'highIntensityGrazingPasture',
|
|
715
|
-
IpccManagementCategory.NOMINALLY_MANAGED: 'nominallyManagedPasture',
|
|
716
|
-
IpccManagementCategory.OTHER: 'nativePasture'
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
EXPECTED_IPCC_MANAGEMENT_CATEGORY_TO_TILLAGE_TERM_ID = {
|
|
720
|
-
IpccManagementCategory.FULL_TILLAGE: 'fullTillage',
|
|
721
|
-
IpccManagementCategory.REDUCED_TILLAGE: 'minimumTillage',
|
|
722
|
-
IpccManagementCategory.NO_TILLAGE: 'noTillage'
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
def test_assign_ipcc_management_category_standard_cases():
|
|
727
|
-
|
|
728
|
-
# Grassland
|
|
729
|
-
for expected, term_id in EXPECTED_IPCC_MANAGEMENT_CATEGORY_TO_LAND_COVER_TERM_ID.items():
|
|
730
|
-
|
|
731
|
-
management_nodes = [
|
|
732
|
-
fake_management(
|
|
733
|
-
term_id,
|
|
734
|
-
100,
|
|
735
|
-
TermTermType.LANDCOVER
|
|
736
|
-
)
|
|
737
|
-
]
|
|
738
|
-
result = _assign_ipcc_management_category(
|
|
739
|
-
management_nodes,
|
|
740
|
-
IpccLandUseCategory.GRASSLAND
|
|
741
|
-
)
|
|
742
|
-
|
|
743
|
-
assert result == expected
|
|
744
|
-
|
|
745
|
-
# Annual crops
|
|
746
|
-
for expected, term_id in EXPECTED_IPCC_MANAGEMENT_CATEGORY_TO_TILLAGE_TERM_ID.items():
|
|
747
|
-
|
|
748
|
-
management_nodes = [
|
|
749
|
-
fake_management(term_id, 100, TermTermType.TILLAGE)
|
|
750
|
-
]
|
|
751
|
-
result = _assign_ipcc_management_category(
|
|
752
|
-
management_nodes,
|
|
753
|
-
IpccLandUseCategory.ANNUAL_CROPS
|
|
754
|
-
)
|
|
755
|
-
|
|
756
|
-
assert result == expected
|
|
757
|
-
|
|
758
|
-
# Annual crops wet
|
|
759
|
-
for expected, term_id in EXPECTED_IPCC_MANAGEMENT_CATEGORY_TO_TILLAGE_TERM_ID.items():
|
|
760
|
-
|
|
761
|
-
management_nodes = [
|
|
762
|
-
fake_management(term_id, 100, TermTermType.TILLAGE)
|
|
763
|
-
]
|
|
764
|
-
result = _assign_ipcc_management_category(
|
|
765
|
-
management_nodes,
|
|
766
|
-
IpccLandUseCategory.ANNUAL_CROPS_WET
|
|
767
|
-
)
|
|
768
|
-
|
|
769
|
-
assert result == expected
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
def test_assign_ipcc_management_fractional_cases():
|
|
773
|
-
EXPECTED_GRASSLAND = IpccManagementCategory.IMPROVED_GRASSLAND
|
|
774
|
-
LAND_COVER_TERM_IDS = [
|
|
775
|
-
'severelyDegradedPasture', # 25%
|
|
776
|
-
'improvedPasture', # 25%
|
|
777
|
-
'improvedPasture', # 25%
|
|
778
|
-
'nativePasture' # 25%
|
|
779
|
-
]
|
|
780
|
-
|
|
781
|
-
EXPECTED_CROPLAND = IpccManagementCategory.REDUCED_TILLAGE
|
|
782
|
-
TILLAGE_TERM_IDS = [
|
|
783
|
-
'fullTillage', # 25%
|
|
784
|
-
'mulchTillage', # 25%
|
|
785
|
-
'stripTillage', # 25%
|
|
786
|
-
'noTillage' # 25%
|
|
787
|
-
]
|
|
788
|
-
|
|
789
|
-
# Grassland
|
|
790
|
-
management_nodes_grassland = [
|
|
791
|
-
fake_management(
|
|
792
|
-
term_id,
|
|
793
|
-
100/len(LAND_COVER_TERM_IDS),
|
|
794
|
-
TermTermType.LANDCOVER
|
|
795
|
-
)
|
|
796
|
-
for term_id in LAND_COVER_TERM_IDS
|
|
797
|
-
]
|
|
798
|
-
result_grassland = _assign_ipcc_management_category(
|
|
799
|
-
management_nodes_grassland,
|
|
800
|
-
IpccLandUseCategory.GRASSLAND
|
|
801
|
-
)
|
|
802
|
-
|
|
803
|
-
assert result_grassland == EXPECTED_GRASSLAND
|
|
804
|
-
|
|
805
|
-
# Annual crops
|
|
806
|
-
management_nodes_cropland = [
|
|
807
|
-
fake_management(
|
|
808
|
-
term_id,
|
|
809
|
-
100/len(TILLAGE_TERM_IDS),
|
|
810
|
-
TermTermType.TILLAGE
|
|
811
|
-
)
|
|
812
|
-
for term_id in TILLAGE_TERM_IDS
|
|
813
|
-
]
|
|
814
|
-
result_cropland = _assign_ipcc_management_category(
|
|
815
|
-
management_nodes_cropland,
|
|
816
|
-
IpccLandUseCategory.ANNUAL_CROPS
|
|
817
|
-
)
|
|
818
|
-
|
|
819
|
-
assert result_cropland == EXPECTED_CROPLAND
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
def test_assign_ipcc_management_category_no_management_cases():
|
|
823
|
-
|
|
824
|
-
EXPECTED_GRASSLAND = IpccManagementCategory.NOMINALLY_MANAGED
|
|
825
|
-
EXPECTED_CROPLAND = IpccManagementCategory.FULL_TILLAGE
|
|
826
|
-
MANAGEMENT_NODES = []
|
|
827
|
-
|
|
828
|
-
result_grassland = _assign_ipcc_management_category(
|
|
829
|
-
MANAGEMENT_NODES, IpccLandUseCategory.GRASSLAND
|
|
830
|
-
)
|
|
831
|
-
|
|
832
|
-
assert result_grassland == EXPECTED_GRASSLAND
|
|
833
|
-
|
|
834
|
-
result_cropland = _assign_ipcc_management_category(
|
|
835
|
-
MANAGEMENT_NODES, IpccLandUseCategory.ANNUAL_CROPS
|
|
836
|
-
)
|
|
837
|
-
|
|
838
|
-
assert result_cropland == EXPECTED_CROPLAND
|
|
839
|
-
|
|
840
|
-
|
|
841
335
|
# --- IPCC CARBON INPUT CATEGORY TESTS ---
|
|
842
336
|
|
|
843
|
-
ANIMAL_MANURE_USED_NODE = fake_management(
|
|
844
|
-
'animalManureUsed', True, TermTermType.LANDUSEMANAGEMENT
|
|
845
|
-
)
|
|
846
|
-
|
|
847
|
-
BROCCOLI_PLANT_NODE = fake_management(
|
|
848
|
-
'broccoliPlant', 100, TermTermType.LANDCOVER
|
|
849
|
-
)
|
|
850
|
-
|
|
851
|
-
COMMON_BEAN_PLANT_NODE = fake_management(
|
|
852
|
-
'commonBeanPlant', 100, TermTermType.LANDCOVER
|
|
853
|
-
)
|
|
854
|
-
|
|
855
|
-
CLOVER_PLANT_NODE = fake_management(
|
|
856
|
-
'cloverPlant', 100, TermTermType.LANDCOVER
|
|
857
|
-
)
|
|
858
|
-
|
|
859
|
-
IRRIGATED_NODE = fake_management(
|
|
860
|
-
'irrigated', 100, TermTermType.WATERREGIME
|
|
861
|
-
)
|
|
862
|
-
|
|
863
|
-
INORGANIC_NITROGEN_FERTILISER_USED_NODE = fake_management(
|
|
864
|
-
'inorganicNitrogenFertiliserUsed', True, TermTermType.LANDUSEMANAGEMENT
|
|
865
|
-
)
|
|
866
|
-
|
|
867
|
-
MULCHING_NODE = fake_management(
|
|
868
|
-
'mulching', 100, TermTermType.LANDUSEMANAGEMENT
|
|
869
|
-
)
|
|
870
|
-
|
|
871
|
-
ORGANIC_FERTILISER_USED_NODE = fake_management(
|
|
872
|
-
'organicFertiliserOrSoilCarbonIncreasingAmendmentUsed',
|
|
873
|
-
100,
|
|
874
|
-
TermTermType.LANDUSEMANAGEMENT
|
|
875
|
-
)
|
|
876
|
-
|
|
877
|
-
RESIDUE_REMOVED_NODE = fake_management(
|
|
878
|
-
'residueRemoved', 100, TermTermType.CROPRESIDUEMANAGEMENT
|
|
879
|
-
)
|
|
880
|
-
|
|
881
|
-
SHORT_BARE_FALLOW_NODE = fake_management(
|
|
882
|
-
'shortBareFallow', 100, TermTermType.LANDUSEMANAGEMENT
|
|
883
|
-
)
|
|
884
|
-
|
|
885
|
-
RYEGRASS_PLANT_AS_COVER_CROP_NODE = fake_management(
|
|
886
|
-
'ryegrassPlant', 100, TermTermType.LANDCOVER,
|
|
887
|
-
properties=[
|
|
888
|
-
fake_property(
|
|
889
|
-
'coverCrop',
|
|
890
|
-
True
|
|
891
|
-
)
|
|
892
|
-
]
|
|
893
|
-
)
|
|
894
|
-
|
|
895
|
-
WHEAT_PLANT_NODE = fake_management(
|
|
896
|
-
'wheatPlant', 100, TermTermType.LANDCOVER
|
|
897
|
-
)
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
901
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
902
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
903
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
904
|
-
def test_check_cropland_high_with_manure_category(*args):
|
|
905
|
-
IPCC_CARBON_INPUT_CATEGORY = IpccCarbonInputCategory.CROPLAND_HIGH_WITH_MANURE
|
|
906
|
-
EXPECTED_CONDITION_KEY_TO_MANAGEMENT_NODES = {
|
|
907
|
-
1: [
|
|
908
|
-
COMMON_BEAN_PLANT_NODE, # N-fixing crop
|
|
909
|
-
ANIMAL_MANURE_USED_NODE
|
|
910
|
-
]
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
for expected, management_nodes in EXPECTED_CONDITION_KEY_TO_MANAGEMENT_NODES.items():
|
|
914
|
-
carbon_input_args = _make_carbon_input_args(management_nodes)
|
|
915
|
-
result = _check_cropland_high_with_manure_category(
|
|
916
|
-
carbon_input_args,
|
|
917
|
-
key=IPCC_CARBON_INPUT_CATEGORY
|
|
918
|
-
)
|
|
919
|
-
|
|
920
|
-
assert result == expected
|
|
921
|
-
pass
|
|
922
|
-
|
|
923
337
|
|
|
338
|
+
@mark.parametrize("key", [1, 2, 3, 4], ids=lambda key: f"scenario-{key}")
|
|
924
339
|
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
925
340
|
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
926
341
|
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
342
|
+
@patch(f"{class_path}.get_long_fallow_land_cover_terms", return_value=LONG_FALLOW_LAND_COVER_TERM_IDS)
|
|
927
343
|
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
928
|
-
def
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
carbon_input_args,
|
|
942
|
-
key=IPCC_CARBON_INPUT_CATEGORY
|
|
943
|
-
)
|
|
944
|
-
|
|
945
|
-
assert result == expected
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
949
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
950
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
951
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
952
|
-
def test_check_cropland_medium_category(*args):
|
|
953
|
-
IPCC_CARBON_INPUT_CATEGORY = IpccCarbonInputCategory.CROPLAND_MEDIUM
|
|
954
|
-
EXPECTED_CONDITION_KEY_TO_MANAGEMENT_NODES = {
|
|
955
|
-
1: [
|
|
956
|
-
WHEAT_PLANT_NODE, # Non-N-fixing & high-residue-producing crop
|
|
957
|
-
RESIDUE_REMOVED_NODE,
|
|
958
|
-
ANIMAL_MANURE_USED_NODE
|
|
959
|
-
],
|
|
960
|
-
2: [
|
|
961
|
-
BROCCOLI_PLANT_NODE, # Low-residue-producing crop
|
|
962
|
-
IRRIGATED_NODE
|
|
963
|
-
],
|
|
964
|
-
3: [
|
|
965
|
-
WHEAT_PLANT_NODE, # Non-N-fixing & high-residue-producing crop
|
|
966
|
-
RYEGRASS_PLANT_AS_COVER_CROP_NODE # Practice increasing C input
|
|
967
|
-
],
|
|
968
|
-
4: [
|
|
969
|
-
COMMON_BEAN_PLANT_NODE # N-fixing crop
|
|
970
|
-
]
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
for expected, management_nodes in EXPECTED_CONDITION_KEY_TO_MANAGEMENT_NODES.items():
|
|
974
|
-
carbon_input_args = _make_carbon_input_args(management_nodes)
|
|
975
|
-
result = _check_cropland_medium_category(
|
|
976
|
-
carbon_input_args,
|
|
977
|
-
key=IPCC_CARBON_INPUT_CATEGORY
|
|
978
|
-
)
|
|
979
|
-
|
|
980
|
-
assert result == expected
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
984
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
985
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
986
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
987
|
-
def test_check_cropland_low_category(*args):
|
|
988
|
-
IPCC_CARBON_INPUT_CATEGORY = IpccCarbonInputCategory.CROPLAND_LOW
|
|
989
|
-
EXPECTED_CONDITION_KEY_TO_MANAGEMENT_NODES = {
|
|
990
|
-
1: [
|
|
991
|
-
WHEAT_PLANT_NODE, # Non-N-fixing & high-residue-producing crop
|
|
992
|
-
RESIDUE_REMOVED_NODE
|
|
993
|
-
],
|
|
994
|
-
2: [
|
|
995
|
-
WHEAT_PLANT_NODE, # Low-residue-producing crop
|
|
996
|
-
SHORT_BARE_FALLOW_NODE
|
|
997
|
-
],
|
|
998
|
-
3: [],
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
for expected, management_nodes in EXPECTED_CONDITION_KEY_TO_MANAGEMENT_NODES.items():
|
|
1002
|
-
carbon_input_args = _make_carbon_input_args(management_nodes)
|
|
1003
|
-
result = _check_cropland_low_category(
|
|
1004
|
-
carbon_input_args,
|
|
1005
|
-
key=IPCC_CARBON_INPUT_CATEGORY
|
|
1006
|
-
)
|
|
1007
|
-
assert result == expected
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
1011
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
1012
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
1013
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
1014
|
-
def test_assign_ipcc_carbon_input_category_grassland_cases(*args):
|
|
1015
|
-
GRASSLAND_CARBON_INPUT_CATEGORY_MANAGEMENT_FIXTURES_GROUPED = {
|
|
1016
|
-
IpccCarbonInputCategory.GRASSLAND_HIGH: [
|
|
1017
|
-
[
|
|
1018
|
-
IRRIGATED_NODE,
|
|
1019
|
-
INORGANIC_NITROGEN_FERTILISER_USED_NODE
|
|
1020
|
-
],
|
|
1021
|
-
[
|
|
1022
|
-
MULCHING_NODE,
|
|
1023
|
-
CLOVER_PLANT_NODE
|
|
1024
|
-
]
|
|
1025
|
-
],
|
|
1026
|
-
IpccCarbonInputCategory.GRASSLAND_MEDIUM: [
|
|
1027
|
-
[
|
|
1028
|
-
ORGANIC_FERTILISER_USED_NODE
|
|
1029
|
-
],
|
|
1030
|
-
[
|
|
1031
|
-
CLOVER_PLANT_NODE
|
|
1032
|
-
]
|
|
1033
|
-
]
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
for expected, management_node_groups in GRASSLAND_CARBON_INPUT_CATEGORY_MANAGEMENT_FIXTURES_GROUPED.items():
|
|
1037
|
-
for management_nodes in management_node_groups:
|
|
1038
|
-
|
|
1039
|
-
result = _assign_ipcc_carbon_input_category(
|
|
1040
|
-
management_nodes,
|
|
1041
|
-
IpccManagementCategory.IMPROVED_GRASSLAND
|
|
1042
|
-
)
|
|
1043
|
-
|
|
1044
|
-
assert result == expected
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
# --- TIER 1 TESTS ---
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
def test_run_tier_1_soc_stocks():
|
|
1051
|
-
IPCC_TIMESTAMPS = [1990, 1995, 2000, 2005, 2010, 2015, 2020]
|
|
1052
|
-
|
|
1053
|
-
IPCC_TIER_1_SOC_STOCK_FIXTURES = [
|
|
1054
|
-
# Land unit 1
|
|
1055
|
-
Tier1SocStockFixtures(
|
|
1056
|
-
timestamps=IPCC_TIMESTAMPS,
|
|
1057
|
-
soc_equilibriums=[
|
|
1058
|
-
77.000, 70.840, 70.840, 70.840, 70.840, 70.840, 70.840
|
|
1059
|
-
],
|
|
1060
|
-
expected=[
|
|
1061
|
-
77.000, 75.460, 73.920, 72.380, 70.840, 70.840, 70.840
|
|
1062
|
-
]
|
|
1063
|
-
),
|
|
1064
|
-
# Land unit 2
|
|
1065
|
-
Tier1SocStockFixtures(
|
|
1066
|
-
timestamps=IPCC_TIMESTAMPS,
|
|
1067
|
-
soc_equilibriums=[
|
|
1068
|
-
77.000, 70.840, 70.840, 70.840, 80.850, 80.850, 80.850
|
|
1069
|
-
],
|
|
1070
|
-
expected=[
|
|
1071
|
-
77.000, 75.460, 73.920, 72.380, 74.498, 76.615, 78.733
|
|
1072
|
-
]
|
|
1073
|
-
),
|
|
1074
|
-
# Land unit 3
|
|
1075
|
-
Tier1SocStockFixtures(
|
|
1076
|
-
timestamps=IPCC_TIMESTAMPS,
|
|
1077
|
-
soc_equilibriums=[
|
|
1078
|
-
80.850, 70.840, 70.840, 70.840, 70.840, 80.850, 80.850
|
|
1079
|
-
],
|
|
1080
|
-
expected=[
|
|
1081
|
-
80.850, 78.348, 75.845, 73.343, 70.840, 73.343, 75.845
|
|
1082
|
-
]
|
|
1083
|
-
),
|
|
1084
|
-
# Land unit 4
|
|
1085
|
-
Tier1SocStockFixtures(
|
|
1086
|
-
timestamps=IPCC_TIMESTAMPS,
|
|
1087
|
-
soc_equilibriums=[
|
|
1088
|
-
80.850, 80.850, 77.000, 77.000, 77.000, 77.000, 77.000
|
|
1089
|
-
],
|
|
1090
|
-
expected=[
|
|
1091
|
-
80.850, 80.850, 79.888, 78.925, 77.963, 77.000, 77.000
|
|
1092
|
-
]
|
|
1093
|
-
),
|
|
1094
|
-
# Land unit 5
|
|
1095
|
-
Tier1SocStockFixtures(
|
|
1096
|
-
timestamps=IPCC_TIMESTAMPS,
|
|
1097
|
-
soc_equilibriums=[
|
|
1098
|
-
70.840, 70.840, 70.840, 70.840, 80.850, 80.850, 80.850
|
|
1099
|
-
],
|
|
1100
|
-
expected=[
|
|
1101
|
-
70.840, 70.840, 70.840, 70.840, 73.343, 75.845, 78.348
|
|
1102
|
-
]
|
|
1103
|
-
),
|
|
1104
|
-
# Land unit 6
|
|
1105
|
-
Tier1SocStockFixtures(
|
|
1106
|
-
timestamps=IPCC_TIMESTAMPS,
|
|
1107
|
-
soc_equilibriums=[
|
|
1108
|
-
70.840, 70.840, 80.850, 80.850, 80.850, 70.840, 80.850
|
|
1109
|
-
],
|
|
1110
|
-
expected=[
|
|
1111
|
-
70.840, 70.840, 73.343, 75.845, 78.348, 76.471, 77.565
|
|
1112
|
-
]
|
|
1113
|
-
)
|
|
1114
|
-
]
|
|
1115
|
-
|
|
1116
|
-
for fixture in IPCC_TIER_1_SOC_STOCK_FIXTURES:
|
|
1117
|
-
result = _calc_tier_1_soc_stocks(
|
|
1118
|
-
fixture.timestamps, fixture.soc_equilibriums
|
|
1119
|
-
)
|
|
1120
|
-
assert_almost_equal(result, fixture.expected, decimal=3)
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
1124
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
1125
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
1126
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
1127
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
1128
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
1129
|
-
@patch(f"{class_path}.related_cycles", return_value=[])
|
|
1130
|
-
def test_run_tier_1_cropland_with_measured_soc(*args):
|
|
1131
|
-
SUBFOLDER = TIER_1_SUBFOLDERS[0]
|
|
1132
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
344
|
+
def test_check_cropland_medium_category(
|
|
345
|
+
_mock_get_residue_removed_or_burnt_terms,
|
|
346
|
+
_mock_get_long_fallow_land_cover_terms,
|
|
347
|
+
_mock_get_irrigated_terms,
|
|
348
|
+
_mock_get_crop_residue_incorporated_or_left_on_field_terms,
|
|
349
|
+
_mock_get_cover_crop_property_terms,
|
|
350
|
+
key
|
|
351
|
+
):
|
|
352
|
+
"""
|
|
353
|
+
Tests each set of cropland medium conditions against a list of nodes that such satisfy it. The function returns the
|
|
354
|
+
key of the matching condition set, which should match the suffix of the fixtures subfolder.
|
|
355
|
+
"""
|
|
356
|
+
folder = f"{fixtures_folder}/IpccCarbonInputCategory/cropland-medium/scenario-{key}"
|
|
1133
357
|
|
|
1134
358
|
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
1135
359
|
site = json.load(f)
|
|
1136
360
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
result = run(site)
|
|
1141
|
-
assert result == expected
|
|
361
|
+
result = _check_cropland_medium_category(**_get_carbon_input_kwargs(site.get("management", [])))
|
|
362
|
+
assert result == key
|
|
1142
363
|
|
|
1143
364
|
|
|
1144
|
-
@
|
|
365
|
+
@mark.parametrize("key", [1, 2, 3], ids=lambda key: f"scenario-{key}")
|
|
1145
366
|
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
1146
367
|
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
1147
368
|
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
369
|
+
@patch(f"{class_path}.get_long_fallow_land_cover_terms", return_value=LONG_FALLOW_LAND_COVER_TERM_IDS)
|
|
1148
370
|
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
371
|
+
def test_check_cropland_low_category(
|
|
372
|
+
_mock_get_residue_removed_or_burnt_terms,
|
|
373
|
+
_mock_get_long_fallow_land_cover_terms,
|
|
374
|
+
_mock_get_irrigated_terms,
|
|
375
|
+
_mock_get_crop_residue_incorporated_or_left_on_field_terms,
|
|
376
|
+
_mock_get_cover_crop_property_terms,
|
|
377
|
+
key
|
|
378
|
+
):
|
|
379
|
+
"""
|
|
380
|
+
Tests each set of cropland low conditions against a list of nodes that such satisfy it. The function returns the
|
|
381
|
+
key of the matching condition set, which should match the suffix of the fixtures subfolder.
|
|
382
|
+
"""
|
|
383
|
+
folder = f"{fixtures_folder}/IpccCarbonInputCategory/cropland-low/scenario-{key}"
|
|
1155
384
|
|
|
1156
385
|
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
1157
386
|
site = json.load(f)
|
|
1158
387
|
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
388
|
+
result = _check_cropland_low_category(**_get_carbon_input_kwargs(site.get("management", [])))
|
|
389
|
+
assert result == key
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
# subfolder, management_category, expected
|
|
393
|
+
CARBON_INPUT_CATEGORY_PARAMS = [
|
|
394
|
+
(
|
|
395
|
+
"cropland-high-with-manure",
|
|
396
|
+
IpccManagementCategory.FULL_TILLAGE,
|
|
397
|
+
IpccCarbonInputCategory.CROPLAND_HIGH_WITH_MANURE
|
|
398
|
+
),
|
|
399
|
+
(
|
|
400
|
+
"cropland-high-without-manure",
|
|
401
|
+
IpccManagementCategory.FULL_TILLAGE,
|
|
402
|
+
IpccCarbonInputCategory.CROPLAND_HIGH_WITHOUT_MANURE
|
|
403
|
+
),
|
|
404
|
+
("cropland-low/scenario-1", IpccManagementCategory.FULL_TILLAGE, IpccCarbonInputCategory.CROPLAND_LOW),
|
|
405
|
+
("cropland-low/scenario-2", IpccManagementCategory.FULL_TILLAGE, IpccCarbonInputCategory.CROPLAND_LOW),
|
|
406
|
+
("cropland-low/scenario-3", IpccManagementCategory.FULL_TILLAGE, IpccCarbonInputCategory.CROPLAND_LOW),
|
|
407
|
+
("cropland-medium/scenario-1", IpccManagementCategory.FULL_TILLAGE, IpccCarbonInputCategory.CROPLAND_MEDIUM),
|
|
408
|
+
("cropland-medium/scenario-2", IpccManagementCategory.FULL_TILLAGE, IpccCarbonInputCategory.CROPLAND_MEDIUM),
|
|
409
|
+
("cropland-medium/scenario-3", IpccManagementCategory.FULL_TILLAGE, IpccCarbonInputCategory.CROPLAND_MEDIUM),
|
|
410
|
+
("cropland-medium/scenario-4", IpccManagementCategory.FULL_TILLAGE, IpccCarbonInputCategory.CROPLAND_MEDIUM),
|
|
411
|
+
("grassland-high", IpccManagementCategory.IMPROVED_GRASSLAND, IpccCarbonInputCategory.GRASSLAND_HIGH),
|
|
412
|
+
(
|
|
413
|
+
"grassland-medium/0-improvements",
|
|
414
|
+
IpccManagementCategory.IMPROVED_GRASSLAND,
|
|
415
|
+
IpccCarbonInputCategory.GRASSLAND_MEDIUM
|
|
416
|
+
),
|
|
417
|
+
(
|
|
418
|
+
"grassland-medium/1-improvements",
|
|
419
|
+
IpccManagementCategory.IMPROVED_GRASSLAND,
|
|
420
|
+
IpccCarbonInputCategory.GRASSLAND_MEDIUM
|
|
421
|
+
)
|
|
422
|
+
]
|
|
1164
423
|
|
|
1165
424
|
|
|
1166
|
-
@
|
|
425
|
+
@mark.parametrize(
|
|
426
|
+
"subfolder, management_category, expected",
|
|
427
|
+
CARBON_INPUT_CATEGORY_PARAMS,
|
|
428
|
+
ids=[params[0] for params in CARBON_INPUT_CATEGORY_PARAMS]
|
|
429
|
+
)
|
|
1167
430
|
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
1168
431
|
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
1169
432
|
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
433
|
+
@patch(f"{class_path}.get_long_fallow_land_cover_terms", return_value=LONG_FALLOW_LAND_COVER_TERM_IDS)
|
|
1170
434
|
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
435
|
+
def test_assign_ipcc_carbon_input_category(
|
|
436
|
+
_mock_get_residue_removed_or_burnt_terms,
|
|
437
|
+
_mock_get_long_fallow_land_cover_terms,
|
|
438
|
+
_mock_get_irrigated_terms,
|
|
439
|
+
_mock_get_crop_residue_incorporated_or_left_on_field_terms,
|
|
440
|
+
_mock_get_cover_crop_property_terms,
|
|
441
|
+
subfolder,
|
|
442
|
+
management_category,
|
|
443
|
+
expected
|
|
444
|
+
):
|
|
445
|
+
folder = f"{fixtures_folder}/IpccCarbonInputCategory/{subfolder}"
|
|
1177
446
|
|
|
1178
447
|
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
1179
448
|
site = json.load(f)
|
|
1180
449
|
|
|
1181
|
-
|
|
1182
|
-
expected = json.load(f)
|
|
1183
|
-
|
|
1184
|
-
result = run(site)
|
|
450
|
+
result = _assign_ipcc_carbon_input_category(site.get("management", []), management_category)
|
|
1185
451
|
assert result == expected
|
|
1186
452
|
|
|
1187
453
|
|
|
1188
|
-
|
|
1189
|
-
@patch(f"{class_path}.get_cover_crop_property_terms", return_value=COVER_CROP_PROPERTY_TERM_IDS)
|
|
1190
|
-
@patch(f"{class_path}.get_crop_residue_incorporated_or_left_on_field_terms", return_value=CROP_RESIDUE_INCORP_TERM_IDS)
|
|
1191
|
-
@patch(f"{class_path}.get_irrigated_terms", return_value=IRRIGATED_TERM_IDS)
|
|
1192
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
1193
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
1194
|
-
@patch(f"{class_path}.related_cycles", return_value=[])
|
|
1195
|
-
def test_run_tier_1_should_not_run(*args):
|
|
1196
|
-
|
|
1197
|
-
SUBFOLDER = TIER_1_SUBFOLDERS[3]
|
|
1198
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
1199
|
-
|
|
1200
|
-
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
1201
|
-
site = json.load(f)
|
|
1202
|
-
|
|
1203
|
-
result = run(site)
|
|
1204
|
-
assert result == []
|
|
454
|
+
# --- TIER 1 TESTS ---
|
|
1205
455
|
|
|
1206
456
|
|
|
1207
|
-
@
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
457
|
+
@mark.parametrize(
|
|
458
|
+
"soc_equilibriums, expected",
|
|
459
|
+
[
|
|
460
|
+
(
|
|
461
|
+
[77.000, 70.840, 70.840, 70.840, 70.840, 70.840, 70.840],
|
|
462
|
+
[77.000, 75.460, 73.920, 72.380, 70.840, 70.840, 70.840]
|
|
463
|
+
),
|
|
464
|
+
(
|
|
465
|
+
[77.000, 70.840, 70.840, 70.840, 80.850, 80.850, 80.850],
|
|
466
|
+
[77.000, 75.460, 73.920, 72.380, 74.498, 76.615, 78.733]
|
|
467
|
+
),
|
|
468
|
+
(
|
|
469
|
+
[80.850, 70.840, 70.840, 70.840, 70.840, 80.850, 80.850],
|
|
470
|
+
[80.850, 78.348, 75.845, 73.343, 70.840, 73.343, 75.845]
|
|
471
|
+
),
|
|
472
|
+
(
|
|
473
|
+
[80.850, 80.850, 77.000, 77.000, 77.000, 77.000, 77.000],
|
|
474
|
+
[80.850, 80.850, 79.888, 78.925, 77.963, 77.000, 77.000]
|
|
475
|
+
),
|
|
476
|
+
(
|
|
477
|
+
[70.840, 70.840, 70.840, 70.840, 80.850, 80.850, 80.850],
|
|
478
|
+
[70.840, 70.840, 70.840, 70.840, 73.343, 75.845, 78.348]
|
|
479
|
+
),
|
|
480
|
+
(
|
|
481
|
+
[70.840, 70.840, 80.850, 80.850, 80.850, 70.840, 80.850],
|
|
482
|
+
[70.840, 70.840, 73.343, 75.845, 78.348, 76.471, 77.565]
|
|
483
|
+
),
|
|
484
|
+
],
|
|
485
|
+
ids=["land-unit-1", "land-unit-2", "land-unit-3", "land-unit-4", "land-unit-5", "land-unit-6"]
|
|
486
|
+
)
|
|
487
|
+
def test_run_tier_1_soc_stocks(soc_equilibriums, expected):
|
|
1215
488
|
"""
|
|
1216
|
-
|
|
1217
|
-
The model should not run but should not raise errors either.
|
|
489
|
+
Test the interpolation between SOC equilibriums using test data provided in IPCC (2019).
|
|
1218
490
|
"""
|
|
491
|
+
TIMESTAMPS = [1990, 1995, 2000, 2005, 2010, 2015, 2020]
|
|
492
|
+
result = _calc_tier_1_soc_stocks(
|
|
493
|
+
TIMESTAMPS, soc_equilibriums
|
|
494
|
+
)
|
|
495
|
+
assert_almost_equal(result, expected, decimal=3)
|
|
1219
496
|
|
|
1220
|
-
SUBFOLDER = TIER_1_SUBFOLDERS[4]
|
|
1221
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
1222
|
-
|
|
1223
|
-
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
1224
|
-
site = json.load(f)
|
|
1225
|
-
|
|
1226
|
-
result = run(site)
|
|
1227
|
-
assert result == []
|
|
1228
497
|
|
|
498
|
+
def test_iterate_soc_equilibriums():
|
|
499
|
+
TIMESTAMPS = [1990, 2020]
|
|
500
|
+
SOC_EQUILIBRIUMS = [20000, 40000]
|
|
1229
501
|
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
@patch(f"{class_path}.get_residue_removed_or_burnt_terms", return_value=RESIDUE_REMOVED_OR_BURNT_TERM_IDS)
|
|
1235
|
-
@patch(f"{class_path}.get_rice_plant_upland_terms", return_value=RICE_PLANT_UPLAND_TERM_IDS)
|
|
1236
|
-
@patch(f"{class_path}.related_cycles", return_value=[])
|
|
1237
|
-
def test_run_tier_1_cropland_depth_as_float(*args):
|
|
1238
|
-
SUBFOLDER = TIER_1_SUBFOLDERS[5]
|
|
1239
|
-
folder = f"{fixtures_folder}/{SUBFOLDER}"
|
|
1240
|
-
|
|
1241
|
-
with open(f"{folder}/site.jsonld", encoding='utf-8') as f:
|
|
1242
|
-
site = json.load(f)
|
|
1243
|
-
|
|
1244
|
-
with open(f"{folder}/result.jsonld", encoding='utf-8') as f:
|
|
1245
|
-
expected = json.load(f)
|
|
502
|
+
EXPECTED = (
|
|
503
|
+
[1990, 2010, 2020],
|
|
504
|
+
[20000, 40000, 40000]
|
|
505
|
+
)
|
|
1246
506
|
|
|
1247
|
-
result =
|
|
1248
|
-
|
|
1249
|
-
assert result == expected
|
|
507
|
+
result = _iterate_soc_equilibriums(TIMESTAMPS, SOC_EQUILIBRIUMS)
|
|
508
|
+
assert result == EXPECTED
|