hestia-earth-models 0.61.7__py3-none-any.whl → 0.61.8__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/completeness/electricityFuel.py +56 -0
- hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +44 -59
- hestia_earth/models/geospatialDatabase/histosol.py +4 -0
- hestia_earth/models/ipcc2006/co2ToAirOrganicSoilCultivation.py +4 -2
- hestia_earth/models/ipcc2006/n2OToAirOrganicSoilCultivationDirect.py +1 -1
- hestia_earth/models/ipcc2019/aboveGroundCropResidueTotal.py +1 -1
- hestia_earth/models/ipcc2019/belowGroundCropResidue.py +1 -1
- hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +1 -1
- hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +511 -458
- hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +5 -1
- hestia_earth/models/ipcc2019/organicCarbonPerHa.py +117 -3881
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +2060 -0
- hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +1630 -0
- hestia_earth/models/ipcc2019/organicCarbonPerHa_utils.py +324 -0
- hestia_earth/models/mocking/search-results.json +252 -252
- hestia_earth/models/site/organicCarbonPerHa.py +58 -44
- hestia_earth/models/site/soilMeasurement.py +18 -13
- hestia_earth/models/utils/__init__.py +28 -0
- hestia_earth/models/utils/array_builders.py +578 -0
- hestia_earth/models/utils/blank_node.py +2 -3
- hestia_earth/models/utils/descriptive_stats.py +285 -0
- hestia_earth/models/utils/emission.py +73 -2
- hestia_earth/models/utils/inorganicFertiliser.py +2 -2
- hestia_earth/models/utils/measurement.py +118 -4
- hestia_earth/models/version.py +1 -1
- {hestia_earth_models-0.61.7.dist-info → hestia_earth_models-0.61.8.dist-info}/METADATA +1 -1
- {hestia_earth_models-0.61.7.dist-info → hestia_earth_models-0.61.8.dist-info}/RECORD +43 -31
- tests/models/cycle/completeness/test_electricityFuel.py +21 -0
- tests/models/emepEea2019/test_nh3ToAirInorganicFertiliser.py +2 -2
- tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +54 -165
- tests/models/ipcc2019/test_organicCarbonPerHa.py +219 -460
- tests/models/ipcc2019/test_organicCarbonPerHa_tier_1_utils.py +471 -0
- tests/models/ipcc2019/test_organicCarbonPerHa_tier_2_utils.py +208 -0
- tests/models/ipcc2019/test_organicCarbonPerHa_utils.py +75 -0
- tests/models/site/test_organicCarbonPerHa.py +3 -12
- tests/models/site/test_soilMeasurement.py +3 -18
- tests/models/utils/test_array_builders.py +253 -0
- tests/models/utils/test_descriptive_stats.py +134 -0
- tests/models/utils/test_emission.py +51 -1
- tests/models/utils/test_measurement.py +54 -2
- {hestia_earth_models-0.61.7.dist-info → hestia_earth_models-0.61.8.dist-info}/LICENSE +0 -0
- {hestia_earth_models-0.61.7.dist-info → hestia_earth_models-0.61.8.dist-info}/WHEEL +0 -0
- {hestia_earth_models-0.61.7.dist-info → hestia_earth_models-0.61.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from pytest import mark
|
|
2
|
+
|
|
3
|
+
from hestia_earth.models.ipcc2019.organicCarbonPerHa_utils import (
|
|
4
|
+
format_bool, format_bool_list, format_enum, format_number, format_number_list, IpccSoilCategory
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@mark.parametrize(
|
|
9
|
+
"value, expected",
|
|
10
|
+
[
|
|
11
|
+
(True, "True"),
|
|
12
|
+
(False, "False"),
|
|
13
|
+
([], "False"),
|
|
14
|
+
("str", "True"),
|
|
15
|
+
(None, "False")
|
|
16
|
+
],
|
|
17
|
+
ids=["True", "False", "list", "str", "None"]
|
|
18
|
+
)
|
|
19
|
+
def test_format_bool(value, expected):
|
|
20
|
+
assert format_bool(value) == expected
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@mark.parametrize(
|
|
24
|
+
"value, expected",
|
|
25
|
+
[
|
|
26
|
+
([True, True, False], "True True False"),
|
|
27
|
+
([], "None"),
|
|
28
|
+
(["Yes", "No", ""], "True True False"),
|
|
29
|
+
(None, "None")
|
|
30
|
+
],
|
|
31
|
+
ids=["list", "empty list", "list[str]", "None"]
|
|
32
|
+
)
|
|
33
|
+
def test_format_bool_list(value, expected):
|
|
34
|
+
assert format_bool_list(value) == expected
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@mark.parametrize(
|
|
38
|
+
"value, expected",
|
|
39
|
+
[
|
|
40
|
+
(IpccSoilCategory.WETLAND_SOILS, IpccSoilCategory.WETLAND_SOILS.value),
|
|
41
|
+
("str", "None"),
|
|
42
|
+
(None, "None")
|
|
43
|
+
],
|
|
44
|
+
ids=["Enum", "str", "None"]
|
|
45
|
+
)
|
|
46
|
+
def test_format_enum(value, expected):
|
|
47
|
+
assert format_enum(value) == expected
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@mark.parametrize(
|
|
51
|
+
"value, expected",
|
|
52
|
+
[
|
|
53
|
+
(3.141592653, "3.1"),
|
|
54
|
+
(0, "0.0"),
|
|
55
|
+
("20", "None"),
|
|
56
|
+
(None, "None")
|
|
57
|
+
],
|
|
58
|
+
ids=["float", "zero", "str", "None"]
|
|
59
|
+
)
|
|
60
|
+
def test_format_number(value, expected):
|
|
61
|
+
assert format_number(value) == expected
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@mark.parametrize(
|
|
65
|
+
"value, expected",
|
|
66
|
+
[
|
|
67
|
+
([3.14, 31.4, 314], "3.1 31.4 314.0"),
|
|
68
|
+
([], "None"),
|
|
69
|
+
(["Yes", "No", ""], "None None None"),
|
|
70
|
+
(None, "None")
|
|
71
|
+
],
|
|
72
|
+
ids=["list", "empty list", "list[str]", "None"]
|
|
73
|
+
)
|
|
74
|
+
def test_format_number_list(value, expected):
|
|
75
|
+
assert format_number_list(value) == expected
|
|
@@ -5,7 +5,7 @@ from unittest.mock import patch
|
|
|
5
5
|
from tests.utils import fixtures_path, fake_new_measurement
|
|
6
6
|
|
|
7
7
|
from hestia_earth.models.site.organicCarbonPerHa import (
|
|
8
|
-
MODEL, TERM_ID, run, _cdf, _c_to_depth, _get_most_relevant_soc_node, _get_last_date
|
|
8
|
+
MODEL, TERM_ID, run, _cdf, _c_to_depth, _get_most_relevant_soc_node, _get_last_date
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
|
|
@@ -14,6 +14,8 @@ fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
|
|
|
14
14
|
SUBFOLDERS = [
|
|
15
15
|
"calculate-single",
|
|
16
16
|
"calculate-multiple",
|
|
17
|
+
"calculate-multiple-with-existing-soc-measurements", # Closes #823
|
|
18
|
+
"calculate-multiple-with-multiple-methods", # Closes #823
|
|
17
19
|
"rescale-single",
|
|
18
20
|
"rescale-multiple",
|
|
19
21
|
"calculate-and-rescale"
|
|
@@ -82,17 +84,6 @@ def test_get_most_relevant_soc_node(nodes, expected_id):
|
|
|
82
84
|
assert _get_most_relevant_soc_node(nodes).get("@id") == expected_id
|
|
83
85
|
|
|
84
86
|
|
|
85
|
-
@patch(f"{class_path}.find_term_match")
|
|
86
|
-
def test_should_run_measurements(mock_find):
|
|
87
|
-
# no measurement => no run
|
|
88
|
-
mock_find.return_value = {}
|
|
89
|
-
assert _should_run_calculation_group([]) is False
|
|
90
|
-
|
|
91
|
-
# with measurement => run
|
|
92
|
-
mock_find.return_value = {'value': [10], 'depthUpper': 0, 'depthLower': 10}
|
|
93
|
-
assert _should_run_calculation_group([]) is True
|
|
94
|
-
|
|
95
|
-
|
|
96
87
|
@mark.parametrize("subfolder", SUBFOLDERS)
|
|
97
88
|
@patch(f"{class_path}.get_source", return_value={})
|
|
98
89
|
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
@@ -135,23 +135,11 @@ def test_harmonise_measurements(measurements_list, returns_dict, expected_value)
|
|
|
135
135
|
)
|
|
136
136
|
]
|
|
137
137
|
)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
mock_get_lookup.return_value = True
|
|
141
|
-
model_key = "clayContent"
|
|
142
|
-
should_run, *args = _should_run(site=site, model_key=model_key)
|
|
138
|
+
def test_should_run(test_name, site, expected_should_run):
|
|
139
|
+
should_run, *args = _should_run(site)
|
|
143
140
|
assert should_run == expected_should_run, test_name
|
|
144
141
|
|
|
145
142
|
|
|
146
|
-
def lookup_side_effect(*args, **kwargs):
|
|
147
|
-
_ = kwargs
|
|
148
|
-
if args[0]["@id"] == "soilPh" and args[1] == "depthSensitive":
|
|
149
|
-
return False
|
|
150
|
-
elif args[0]["@id"] in {"baseSaturation", "soilDepth", "rainfallHourly"}:
|
|
151
|
-
return False
|
|
152
|
-
return True
|
|
153
|
-
|
|
154
|
-
|
|
155
143
|
@pytest.mark.parametrize(
|
|
156
144
|
"test_name",
|
|
157
145
|
[
|
|
@@ -165,10 +153,7 @@ def lookup_side_effect(*args, **kwargs):
|
|
|
165
153
|
]
|
|
166
154
|
)
|
|
167
155
|
@patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
|
|
168
|
-
|
|
169
|
-
def test_run(mock_lookup, mock_new_measurement, test_name):
|
|
170
|
-
mock_lookup.side_effect = lookup_side_effect
|
|
171
|
-
|
|
156
|
+
def test_run(mock_new_measurement, test_name):
|
|
172
157
|
with open(f"{fixtures_folder}/{test_name}/site.jsonld", encoding='utf-8') as f:
|
|
173
158
|
site = json.load(f)
|
|
174
159
|
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
from numpy import array
|
|
2
|
+
from numpy.testing import assert_array_equal
|
|
3
|
+
from numpy.typing import NDArray
|
|
4
|
+
from pytest import mark
|
|
5
|
+
|
|
6
|
+
from hestia_earth.models.utils.array_builders import (
|
|
7
|
+
avg_run_in_columnwise, avg_run_in_rowwise, discrete_uniform_1d, discrete_uniform_2d, gen_seed, grouped_avg,
|
|
8
|
+
normal_1d, normal_2d, plus_minus_uncertainty_to_normal_1d, plus_minus_uncertainty_to_normal_2d,
|
|
9
|
+
repeat_1d_array_as_columns, repeat_array_as_columns, repeat_array_as_rows, repeat_single, triangular_1d,
|
|
10
|
+
triangular_2d, truncated_normal_1d, truncated_normal_2d
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
SEED = 0
|
|
14
|
+
SHAPE = (1000, 1000)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def assert_rows_identical(arr: NDArray):
|
|
18
|
+
"""
|
|
19
|
+
Covert array to a set to remove repeated rows and check that number remaining rows is 1.
|
|
20
|
+
"""
|
|
21
|
+
assert len(set(map(tuple, arr))) == 1
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def assert_rows_unique(arr: NDArray):
|
|
25
|
+
"""
|
|
26
|
+
Covert array to a set to remove repeated rows and check that number remaining rows is the same as the number of
|
|
27
|
+
original rows.
|
|
28
|
+
"""
|
|
29
|
+
assert len(set(map(tuple, arr))) == len(arr)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def assert_elements_between(arr: NDArray, min: float, max: float):
|
|
33
|
+
assert ((min <= arr) & (arr <= max)).all()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
PARAMS_REPEAT_SINGLE = [
|
|
37
|
+
(3.14159, None, 3.14159),
|
|
38
|
+
(3.14159, bool, True),
|
|
39
|
+
(True, None, True),
|
|
40
|
+
(True, float, 1)
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
IDS_REPEAT_SINGLE = [
|
|
44
|
+
f"{type(value).__name__}{f' -> {dtype.__name__}' if dtype else ''}" for value, dtype, _ in PARAMS_REPEAT_SINGLE
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@mark.parametrize(
|
|
49
|
+
"value, dtype, expected_element",
|
|
50
|
+
[(3.14159, None, 3.14159), (3.14159, bool, True), (True, None, True), (True, float, 1)],
|
|
51
|
+
ids=IDS_REPEAT_SINGLE
|
|
52
|
+
)
|
|
53
|
+
def test_repeat_single(value, dtype, expected_element):
|
|
54
|
+
SHAPE = (3, 3)
|
|
55
|
+
EXPECTED = array([
|
|
56
|
+
[expected_element, expected_element, expected_element],
|
|
57
|
+
[expected_element, expected_element, expected_element],
|
|
58
|
+
[expected_element, expected_element, expected_element]
|
|
59
|
+
])
|
|
60
|
+
result = repeat_single(SHAPE, value, dtype=dtype)
|
|
61
|
+
assert_array_equal(result, EXPECTED)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_repeat_array_as_columns():
|
|
65
|
+
INPUT = array([
|
|
66
|
+
[1, 2, 3],
|
|
67
|
+
[4, 5, 6]
|
|
68
|
+
])
|
|
69
|
+
EXPECTED = array([
|
|
70
|
+
[1, 2, 3, 1, 2, 3],
|
|
71
|
+
[4, 5, 6, 4, 5, 6]
|
|
72
|
+
])
|
|
73
|
+
result = repeat_array_as_columns(2, INPUT)
|
|
74
|
+
assert_array_equal(result, EXPECTED)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_repeat_array_as_rows():
|
|
78
|
+
INPUT = array([
|
|
79
|
+
[1, 2, 3],
|
|
80
|
+
[4, 5, 6]
|
|
81
|
+
])
|
|
82
|
+
EXPECTED = array([
|
|
83
|
+
[1, 2, 3],
|
|
84
|
+
[4, 5, 6],
|
|
85
|
+
[1, 2, 3],
|
|
86
|
+
[4, 5, 6]
|
|
87
|
+
])
|
|
88
|
+
result = repeat_array_as_rows(2, INPUT)
|
|
89
|
+
assert_array_equal(result, EXPECTED)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_repeat_1d_array_as_columns():
|
|
93
|
+
INPUT = array([1, 2, 3])
|
|
94
|
+
EXPECTED = array([
|
|
95
|
+
[1, 1, 1],
|
|
96
|
+
[2, 2, 2],
|
|
97
|
+
[3, 3, 3]
|
|
98
|
+
])
|
|
99
|
+
result = repeat_1d_array_as_columns(3, INPUT)
|
|
100
|
+
assert_array_equal(result, EXPECTED)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_discrete_uniform_1d():
|
|
104
|
+
MIN, MAX = -100, 100
|
|
105
|
+
result = discrete_uniform_1d(SHAPE, MIN, MAX, seed=SEED)
|
|
106
|
+
assert_rows_identical(result)
|
|
107
|
+
assert_elements_between(result, MIN, MAX)
|
|
108
|
+
assert result.shape == SHAPE
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_discrete_uniform_2d():
|
|
112
|
+
MIN, MAX = -100, 100
|
|
113
|
+
result = discrete_uniform_2d(SHAPE, MIN, MAX, seed=SEED)
|
|
114
|
+
assert_rows_unique(result)
|
|
115
|
+
assert_elements_between(result, MIN, MAX)
|
|
116
|
+
assert result.shape == SHAPE
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_discrete_triangular_1d():
|
|
120
|
+
LOW, HIGH = -100, 100
|
|
121
|
+
MODE = -50
|
|
122
|
+
result = triangular_1d(SHAPE, LOW, HIGH, MODE, seed=SEED)
|
|
123
|
+
assert_rows_identical(result)
|
|
124
|
+
assert_elements_between(result, LOW, HIGH)
|
|
125
|
+
assert result.shape == SHAPE
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_discrete_triangular_2d():
|
|
129
|
+
LOW, HIGH = -100, 100
|
|
130
|
+
MODE = 50
|
|
131
|
+
result = triangular_2d(SHAPE, LOW, HIGH, MODE, seed=SEED)
|
|
132
|
+
assert_rows_unique(result)
|
|
133
|
+
assert_elements_between(result, LOW, HIGH)
|
|
134
|
+
assert result.shape == SHAPE
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_normal_1d():
|
|
138
|
+
MEAN = 0
|
|
139
|
+
SD = 50
|
|
140
|
+
result = normal_1d(SHAPE, MEAN, SD, seed=SEED)
|
|
141
|
+
assert_rows_identical(result)
|
|
142
|
+
assert result.shape == SHAPE
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def test_normal_2d():
|
|
146
|
+
MEAN = 0
|
|
147
|
+
SD = 50
|
|
148
|
+
result = normal_2d(SHAPE, MEAN, SD, seed=SEED)
|
|
149
|
+
assert_rows_unique(result)
|
|
150
|
+
assert result.shape == SHAPE
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def test_truncated_normal_1d():
|
|
154
|
+
MEAN = 0
|
|
155
|
+
SD = 50
|
|
156
|
+
LOW, HIGH = -50, 50
|
|
157
|
+
result = truncated_normal_1d(SHAPE, MEAN, SD, LOW, HIGH, seed=SEED)
|
|
158
|
+
assert_rows_identical(result)
|
|
159
|
+
assert_elements_between(result, LOW, HIGH)
|
|
160
|
+
assert result.shape == SHAPE
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def test_truncated_normal_2d():
|
|
164
|
+
MEAN = 0
|
|
165
|
+
SD = 50
|
|
166
|
+
LOW, HIGH = -50, 50
|
|
167
|
+
result = truncated_normal_2d(SHAPE, MEAN, SD, LOW, HIGH, seed=SEED)
|
|
168
|
+
assert_rows_unique(result)
|
|
169
|
+
assert_elements_between(result, LOW, HIGH)
|
|
170
|
+
assert result.shape == SHAPE
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def test_plus_minus_uncertainty_to_normal_1d():
|
|
174
|
+
MEAN = 10
|
|
175
|
+
UNCERTAINTY = 10
|
|
176
|
+
CONFIDENCE_INTERVAL = 95
|
|
177
|
+
result = plus_minus_uncertainty_to_normal_1d(SHAPE, MEAN, UNCERTAINTY, CONFIDENCE_INTERVAL)
|
|
178
|
+
assert_rows_identical(result)
|
|
179
|
+
assert result.shape == SHAPE
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def test_plus_minus_uncertainty_to_normal_2d():
|
|
183
|
+
MEAN = 10
|
|
184
|
+
UNCERTAINTY = 10
|
|
185
|
+
CONFIDENCE_INTERVAL = 95
|
|
186
|
+
result = plus_minus_uncertainty_to_normal_2d(SHAPE, MEAN, UNCERTAINTY, CONFIDENCE_INTERVAL)
|
|
187
|
+
assert_rows_unique(result)
|
|
188
|
+
assert result.shape == SHAPE
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_grouped_avg():
|
|
192
|
+
INPUT = array([
|
|
193
|
+
[1, 2, 3],
|
|
194
|
+
[4, 5, 6],
|
|
195
|
+
[7, 8, 9],
|
|
196
|
+
[10, 11, 12],
|
|
197
|
+
[13, 14, 15],
|
|
198
|
+
[16, 17, 18]
|
|
199
|
+
])
|
|
200
|
+
EXPECTED = array([
|
|
201
|
+
[4, 5, 6],
|
|
202
|
+
[13, 14, 15]
|
|
203
|
+
])
|
|
204
|
+
result = grouped_avg(INPUT, n=3)
|
|
205
|
+
assert_array_equal(result, EXPECTED)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def test_avg_run_in_columnwise():
|
|
209
|
+
INPUT = array([
|
|
210
|
+
[1, 2, 3],
|
|
211
|
+
[4, 5, 6],
|
|
212
|
+
[7, 8, 9],
|
|
213
|
+
[10, 11, 12],
|
|
214
|
+
[13, 14, 15],
|
|
215
|
+
[16, 17, 18]
|
|
216
|
+
])
|
|
217
|
+
EXPECTED = array([
|
|
218
|
+
[4, 5, 6],
|
|
219
|
+
[10, 11, 12],
|
|
220
|
+
[13, 14, 15],
|
|
221
|
+
[16, 17, 18]
|
|
222
|
+
])
|
|
223
|
+
result = avg_run_in_columnwise(INPUT, n=3)
|
|
224
|
+
assert_array_equal(result, EXPECTED)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def test_avg_run_in_rowwise():
|
|
228
|
+
INPUT = array([
|
|
229
|
+
[1, 2, 3, 4, 5],
|
|
230
|
+
[6, 7, 8, 9, 10],
|
|
231
|
+
[11, 12, 13, 14, 15]
|
|
232
|
+
])
|
|
233
|
+
EXPECTED = array([
|
|
234
|
+
[2, 4, 5],
|
|
235
|
+
[7, 9, 10],
|
|
236
|
+
[12, 14, 15]
|
|
237
|
+
])
|
|
238
|
+
result = avg_run_in_rowwise(INPUT, n=3)
|
|
239
|
+
assert_array_equal(result, EXPECTED)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_gen_seed():
|
|
243
|
+
NODE = {"@id": "site"}
|
|
244
|
+
EXPECTED = 2926675914
|
|
245
|
+
result = gen_seed(NODE)
|
|
246
|
+
assert result == EXPECTED
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def test_gen_seed_no_id():
|
|
250
|
+
NODE = {}
|
|
251
|
+
EXPECTED = 2140941220
|
|
252
|
+
result = gen_seed(NODE)
|
|
253
|
+
assert result == EXPECTED
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
from numpy import array, inf
|
|
2
|
+
from numpy.testing import assert_almost_equal
|
|
3
|
+
from pytest import mark
|
|
4
|
+
|
|
5
|
+
from hestia_earth.schema import MeasurementStatsDefinition
|
|
6
|
+
|
|
7
|
+
from hestia_earth.models.utils.descriptive_stats import (
|
|
8
|
+
_calc_confidence_level, calc_confidence_level_monte_carlo, calc_descriptive_stats, calc_precision_monte_carlo,
|
|
9
|
+
calc_required_iterations_monte_carlo, calc_z_critical
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
# confidence_level, n_sided, z_critical
|
|
13
|
+
CONFIDENCE_INTERVAL_PARAMS = [
|
|
14
|
+
# 1 sided
|
|
15
|
+
(0, 1, -inf),
|
|
16
|
+
(50, 1, 0),
|
|
17
|
+
(80, 1, 0.8416),
|
|
18
|
+
(90, 1, 1.2816),
|
|
19
|
+
(95, 1, 1.6449),
|
|
20
|
+
(99, 1, 2.3263),
|
|
21
|
+
(100, 1, inf),
|
|
22
|
+
# 2 sided
|
|
23
|
+
(0, 2, 0),
|
|
24
|
+
(50, 2, 0.6745),
|
|
25
|
+
(80, 2, 1.2816),
|
|
26
|
+
(90, 2, 1.6449),
|
|
27
|
+
(95, 2, 1.9600),
|
|
28
|
+
(99, 2, 2.5758),
|
|
29
|
+
(100, 2, inf)
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@mark.parametrize(
|
|
34
|
+
"confidence_level, n_sided, z_critical",
|
|
35
|
+
CONFIDENCE_INTERVAL_PARAMS,
|
|
36
|
+
ids=[f"z={z}, n={n}" for _, n, z in CONFIDENCE_INTERVAL_PARAMS]
|
|
37
|
+
)
|
|
38
|
+
def test_calc_confidence_level(confidence_level, n_sided, z_critical):
|
|
39
|
+
result = _calc_confidence_level(z_critical, n_sided=n_sided)
|
|
40
|
+
assert_almost_equal(result, confidence_level, decimal=2)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@mark.parametrize(
|
|
44
|
+
"confidence_level, n_sided, z_critical",
|
|
45
|
+
CONFIDENCE_INTERVAL_PARAMS,
|
|
46
|
+
ids=[f"conf={conf}, n={n}" for conf, n, _ in CONFIDENCE_INTERVAL_PARAMS]
|
|
47
|
+
)
|
|
48
|
+
def test_calc_z_critical(confidence_level, n_sided, z_critical):
|
|
49
|
+
result = calc_z_critical(confidence_level, n_sided=n_sided)
|
|
50
|
+
assert_almost_equal(result, z_critical, decimal=4)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# confidence_level, n_iterations, precision, sd
|
|
54
|
+
MONTE_CARLO_PARAMS = [
|
|
55
|
+
(95, 80767, 0.01, 1.45),
|
|
56
|
+
(95, 1110, 0.01, 0.17),
|
|
57
|
+
(99, 1917, 0.01, 0.17),
|
|
58
|
+
(50, 102, 100.18, 1500)
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@mark.parametrize(
|
|
63
|
+
"confidence_level, n_iterations, precision, sd",
|
|
64
|
+
MONTE_CARLO_PARAMS,
|
|
65
|
+
ids=[f"n={n}, prec={prec}, sd={sd}" for _, n, prec, sd in MONTE_CARLO_PARAMS]
|
|
66
|
+
)
|
|
67
|
+
def test_calc_confidence_level_monte_carlo(confidence_level, n_iterations, precision, sd):
|
|
68
|
+
result = calc_confidence_level_monte_carlo(n_iterations, precision, sd,)
|
|
69
|
+
assert_almost_equal(result, confidence_level, decimal=2)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@mark.parametrize(
|
|
73
|
+
"confidence_level, n_iterations, precision, sd",
|
|
74
|
+
MONTE_CARLO_PARAMS,
|
|
75
|
+
ids=[f"conf={conf}, prec={prec}, sd={sd}" for conf, _, prec, sd in MONTE_CARLO_PARAMS]
|
|
76
|
+
)
|
|
77
|
+
def test_calc_required_iterations_monte_carlo(confidence_level, n_iterations, precision, sd):
|
|
78
|
+
result = calc_required_iterations_monte_carlo(confidence_level, precision, sd)
|
|
79
|
+
assert result == n_iterations
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@mark.parametrize(
|
|
83
|
+
"confidence_level, n_iterations, precision, sd",
|
|
84
|
+
MONTE_CARLO_PARAMS,
|
|
85
|
+
ids=[f"conf={conf}, n={n}, sd={sd}" for conf, n, _, sd in MONTE_CARLO_PARAMS]
|
|
86
|
+
)
|
|
87
|
+
def test_calc_precision_monte_carlo(confidence_level, n_iterations, precision, sd):
|
|
88
|
+
result = calc_precision_monte_carlo(confidence_level, n_iterations, sd)
|
|
89
|
+
assert_almost_equal(result, precision, decimal=2)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
EXPECTED_FLATTENED = {
|
|
93
|
+
"value": [5],
|
|
94
|
+
"sd": [2.581989],
|
|
95
|
+
"min": [1],
|
|
96
|
+
"max": [9],
|
|
97
|
+
"statsDefinition": "simulated",
|
|
98
|
+
"observations": [9]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
EXPECTED_COLUMNWISE = {
|
|
102
|
+
"value": [4, 5, 6],
|
|
103
|
+
"sd": [2.44949, 2.44949, 2.44949],
|
|
104
|
+
"min": [1, 2, 3],
|
|
105
|
+
"max": [7, 8, 9],
|
|
106
|
+
"statsDefinition": "simulated",
|
|
107
|
+
"observations": [3, 3, 3]
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
EXPECTED_ROWWISE = {
|
|
111
|
+
"value": [2, 5, 8],
|
|
112
|
+
"sd": [0.816497, 0.816497, 0.816497],
|
|
113
|
+
"min": [1, 4, 7],
|
|
114
|
+
"max": [3, 6, 9],
|
|
115
|
+
"statsDefinition": "simulated",
|
|
116
|
+
"observations": [3, 3, 3]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@mark.parametrize(
|
|
121
|
+
"axis, expected",
|
|
122
|
+
[(None, EXPECTED_FLATTENED), (0, EXPECTED_COLUMNWISE), (1, EXPECTED_ROWWISE)],
|
|
123
|
+
ids=["flattened", "columnwise", "rowwise"]
|
|
124
|
+
)
|
|
125
|
+
@mark.parametrize("stats_definition", [MeasurementStatsDefinition.SIMULATED, "simulated"], ids=["Enum", "str"])
|
|
126
|
+
def test_calc_descriptive_stats(stats_definition, axis, expected):
|
|
127
|
+
ARR = array([
|
|
128
|
+
[1, 2, 3],
|
|
129
|
+
[4, 5, 6],
|
|
130
|
+
[7, 8, 9]
|
|
131
|
+
])
|
|
132
|
+
|
|
133
|
+
result = calc_descriptive_stats(ARR, stats_definition, axis=axis)
|
|
134
|
+
assert result == expected
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
from pytest import mark
|
|
1
2
|
from unittest.mock import patch
|
|
2
3
|
|
|
4
|
+
from hestia_earth.schema import EmissionMethodTier
|
|
5
|
+
|
|
3
6
|
from tests.utils import TERM
|
|
4
|
-
from hestia_earth.models.utils.emission import _new_emission, is_in_system_boundary
|
|
7
|
+
from hestia_earth.models.utils.emission import _new_emission, is_in_system_boundary, min_emission_method_tier
|
|
5
8
|
|
|
6
9
|
class_path = 'hestia_earth.models.utils.emission'
|
|
7
10
|
|
|
@@ -27,3 +30,50 @@ def test_new_emission(*args):
|
|
|
27
30
|
def test_is_in_system_boundary():
|
|
28
31
|
assert is_in_system_boundary('ch4ToAirCropResidueBurning') is True
|
|
29
32
|
assert is_in_system_boundary('codToWaterInputsProduction') is False
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@mark.parametrize(
|
|
36
|
+
"input, expected",
|
|
37
|
+
[
|
|
38
|
+
(
|
|
39
|
+
(
|
|
40
|
+
EmissionMethodTier.TIER_1,
|
|
41
|
+
EmissionMethodTier.TIER_2,
|
|
42
|
+
EmissionMethodTier.TIER_3
|
|
43
|
+
),
|
|
44
|
+
EmissionMethodTier.TIER_1
|
|
45
|
+
),
|
|
46
|
+
(
|
|
47
|
+
[
|
|
48
|
+
EmissionMethodTier.TIER_1,
|
|
49
|
+
EmissionMethodTier.TIER_2,
|
|
50
|
+
EmissionMethodTier.TIER_3
|
|
51
|
+
],
|
|
52
|
+
EmissionMethodTier.TIER_1
|
|
53
|
+
),
|
|
54
|
+
(
|
|
55
|
+
[], EmissionMethodTier.NOT_RELEVANT
|
|
56
|
+
),
|
|
57
|
+
(
|
|
58
|
+
(
|
|
59
|
+
EmissionMethodTier.TIER_1.value,
|
|
60
|
+
EmissionMethodTier.TIER_2.value,
|
|
61
|
+
EmissionMethodTier.TIER_3.value
|
|
62
|
+
),
|
|
63
|
+
EmissionMethodTier.TIER_1
|
|
64
|
+
),
|
|
65
|
+
(
|
|
66
|
+
[
|
|
67
|
+
EmissionMethodTier.TIER_1.value,
|
|
68
|
+
EmissionMethodTier.TIER_2.value,
|
|
69
|
+
EmissionMethodTier.TIER_3.value
|
|
70
|
+
],
|
|
71
|
+
EmissionMethodTier.TIER_1
|
|
72
|
+
),
|
|
73
|
+
|
|
74
|
+
],
|
|
75
|
+
ids=["Enum", "list[Enum]", "None", "str", "list[str]"]
|
|
76
|
+
)
|
|
77
|
+
def test_min_emission_method_tier(input, expected):
|
|
78
|
+
result = min_emission_method_tier(input)
|
|
79
|
+
assert result == expected
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
from unittest.mock import patch
|
|
2
1
|
import json
|
|
2
|
+
from pytest import mark
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
|
|
5
|
+
from hestia_earth.schema import MeasurementMethodClassification
|
|
6
|
+
|
|
3
7
|
from tests.utils import fixtures_path, TERM
|
|
4
8
|
|
|
5
9
|
from hestia_earth.models.utils.measurement import (
|
|
6
|
-
_new_measurement, most_relevant_measurement_value, _most_recent_measurements, _shallowest_measurement
|
|
10
|
+
_new_measurement, most_relevant_measurement_value, _most_recent_measurements, _shallowest_measurement,
|
|
11
|
+
min_measurement_method_classification
|
|
7
12
|
)
|
|
8
13
|
|
|
9
14
|
class_path = 'hestia_earth.models.utils.measurement'
|
|
@@ -83,3 +88,50 @@ def test_shallowest_measurement():
|
|
|
83
88
|
expected = json.load(f)
|
|
84
89
|
|
|
85
90
|
assert _shallowest_measurement(measurements) == expected
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@mark.parametrize(
|
|
94
|
+
"input, expected",
|
|
95
|
+
[
|
|
96
|
+
(
|
|
97
|
+
(
|
|
98
|
+
MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT,
|
|
99
|
+
MeasurementMethodClassification.TIER_2_MODEL,
|
|
100
|
+
MeasurementMethodClassification.TIER_1_MODEL
|
|
101
|
+
),
|
|
102
|
+
MeasurementMethodClassification.TIER_1_MODEL
|
|
103
|
+
),
|
|
104
|
+
(
|
|
105
|
+
[
|
|
106
|
+
MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT,
|
|
107
|
+
MeasurementMethodClassification.TIER_2_MODEL,
|
|
108
|
+
MeasurementMethodClassification.TIER_1_MODEL
|
|
109
|
+
],
|
|
110
|
+
MeasurementMethodClassification.TIER_1_MODEL
|
|
111
|
+
),
|
|
112
|
+
(
|
|
113
|
+
[], MeasurementMethodClassification.UNSOURCED_ASSUMPTION
|
|
114
|
+
),
|
|
115
|
+
(
|
|
116
|
+
(
|
|
117
|
+
MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT.value,
|
|
118
|
+
MeasurementMethodClassification.TIER_2_MODEL.value,
|
|
119
|
+
MeasurementMethodClassification.TIER_1_MODEL.value
|
|
120
|
+
),
|
|
121
|
+
MeasurementMethodClassification.TIER_1_MODEL
|
|
122
|
+
),
|
|
123
|
+
(
|
|
124
|
+
[
|
|
125
|
+
MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT.value,
|
|
126
|
+
MeasurementMethodClassification.TIER_2_MODEL.value,
|
|
127
|
+
MeasurementMethodClassification.TIER_1_MODEL.value
|
|
128
|
+
],
|
|
129
|
+
MeasurementMethodClassification.TIER_1_MODEL
|
|
130
|
+
),
|
|
131
|
+
|
|
132
|
+
],
|
|
133
|
+
ids=["Enum", "list[Enum]", "None", "str", "list[str]"]
|
|
134
|
+
)
|
|
135
|
+
def test_min_measurement_method_classification(input, expected):
|
|
136
|
+
result = min_measurement_method_classification(input)
|
|
137
|
+
assert result == expected
|
|
File without changes
|
|
File without changes
|
|
File without changes
|