hestia-earth-models 0.64.4__py3-none-any.whl → 0.64.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hestia-earth-models might be problematic. Click here for more details.

Files changed (62) hide show
  1. hestia_earth/models/blonkConsultants2016/ch4ToAirNaturalVegetationBurning.py +5 -9
  2. hestia_earth/models/blonkConsultants2016/co2ToAirAboveGroundBiomassStockChangeLandUseChange.py +5 -9
  3. hestia_earth/models/blonkConsultants2016/n2OToAirNaturalVegetationBurningDirect.py +6 -13
  4. hestia_earth/models/cycle/animal/input/properties.py +6 -0
  5. hestia_earth/models/cycle/completeness/soilAmendment.py +3 -2
  6. hestia_earth/models/cycle/concentrateFeed.py +10 -4
  7. hestia_earth/models/cycle/input/properties.py +6 -0
  8. hestia_earth/models/cycle/liveAnimal.py +2 -2
  9. hestia_earth/models/cycle/milkYield.py +3 -3
  10. hestia_earth/models/cycle/otherSitesArea.py +59 -0
  11. hestia_earth/models/cycle/otherSitesUnusedDuration.py +9 -8
  12. hestia_earth/models/cycle/pastureSystem.py +3 -2
  13. hestia_earth/models/cycle/product/properties.py +6 -0
  14. hestia_earth/models/cycle/siteArea.py +83 -0
  15. hestia_earth/models/cycle/stockingDensityAnimalHousingAverage.py +28 -16
  16. hestia_earth/models/cycle/utils.py +1 -1
  17. hestia_earth/models/environmentalFootprintV3/soilQualityIndexLandOccupation.py +128 -0
  18. hestia_earth/models/environmentalFootprintV3/utils.py +17 -0
  19. hestia_earth/models/ipcc2006/co2ToAirOrganicSoilCultivation.py +17 -6
  20. hestia_earth/models/ipcc2006/n2OToAirOrganicSoilCultivationDirect.py +17 -6
  21. hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +904 -0
  22. hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +70 -618
  23. hestia_earth/models/mocking/search-results.json +395 -323
  24. hestia_earth/models/pooreNemecek2018/saplings.py +10 -7
  25. hestia_earth/models/site/management.py +18 -14
  26. hestia_earth/models/utils/__init__.py +38 -0
  27. hestia_earth/models/utils/array_builders.py +63 -52
  28. hestia_earth/models/utils/blank_node.py +137 -82
  29. hestia_earth/models/utils/descriptive_stats.py +3 -239
  30. hestia_earth/models/utils/feedipedia.py +15 -2
  31. hestia_earth/models/utils/landCover.py +9 -0
  32. hestia_earth/models/utils/lookup.py +13 -2
  33. hestia_earth/models/utils/measurement.py +3 -28
  34. hestia_earth/models/utils/stats.py +429 -0
  35. hestia_earth/models/utils/term.py +15 -3
  36. hestia_earth/models/utils/time_series.py +90 -0
  37. hestia_earth/models/version.py +1 -1
  38. {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/METADATA +1 -1
  39. {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/RECORD +62 -48
  40. tests/models/blonkConsultants2016/test_ch4ToAirNaturalVegetationBurning.py +2 -2
  41. tests/models/blonkConsultants2016/test_co2ToAirAboveGroundBiomassStockChangeLandUseChange.py +2 -2
  42. tests/models/blonkConsultants2016/test_n2OToAirNaturalVegetationBurningDirect.py +2 -2
  43. tests/models/cycle/completeness/test_soilAmendment.py +1 -1
  44. tests/models/cycle/test_liveAnimal.py +1 -1
  45. tests/models/cycle/test_milkYield.py +1 -1
  46. tests/models/cycle/test_otherSitesArea.py +68 -0
  47. tests/models/cycle/test_siteArea.py +51 -0
  48. tests/models/cycle/test_stockingDensityAnimalHousingAverage.py +2 -2
  49. tests/models/environmentalFootprintV3/test_soilQualityIndexLandOccupation.py +136 -0
  50. tests/models/ipcc2019/test_co2ToAirCarbonStockChange_utils.py +50 -0
  51. tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChangeManagementChange.py +1 -39
  52. tests/models/pooreNemecek2018/test_saplings.py +1 -1
  53. tests/models/site/test_management.py +3 -153
  54. tests/models/utils/test_array_builders.py +67 -6
  55. tests/models/utils/test_blank_node.py +191 -7
  56. tests/models/utils/test_descriptive_stats.py +2 -86
  57. tests/models/utils/test_measurement.py +1 -22
  58. tests/models/utils/test_stats.py +186 -0
  59. tests/models/utils/test_time_series.py +88 -0
  60. {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/LICENSE +0 -0
  61. {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/WHEEL +0 -0
  62. {hestia_earth_models-0.64.4.dist-info → hestia_earth_models-0.64.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,136 @@
1
+ import json
2
+ from unittest.mock import patch
3
+
4
+ from hestia_earth.models.environmentalFootprintV3.soilQualityIndexLandOccupation import MODEL, TERM_ID, run, _should_run
5
+ from tests.utils import fixtures_path, fake_new_indicator
6
+
7
+ class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
8
+ fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
9
+
10
+
11
+ def test_should_run():
12
+ with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
13
+ cycle = json.load(f)
14
+
15
+ # a LandCover type with no CF => no run
16
+ cycle['site']['management'] = [{"endDate": "2024-03-31", "@type": "Management",
17
+ "term": {"termType": "landCover", "@type": "Term", "@id": "ocean"}}]
18
+
19
+ should_run, *args = _should_run(cycle)
20
+ assert not should_run
21
+
22
+ # no management => no run
23
+ cycle['site']['management'] = []
24
+ should_run, *args = _should_run(cycle)
25
+ assert not should_run
26
+
27
+
28
+ @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
29
+ def test_run(*args):
30
+ """
31
+ Example data:
32
+ Country: Italy
33
+ Quantity in m^2: 1.3573373E-9
34
+ CF METHOD factor: 4.3198E+01
35
+ "Charact Result [soil quality index]" result also in result.jsonld : 5.86342566854E-08
36
+ siteArea in test file in ha: 1.3573373E-9 / 10 000 = 1.3573373e-13
37
+
38
+ Name Flow: forest Land occupation
39
+ Parameters
40
+ ----------
41
+ args
42
+
43
+ Returns
44
+ -------
45
+
46
+ """
47
+ with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
48
+ cycle = json.load(f)
49
+
50
+ with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
51
+ expected = json.load(f)
52
+
53
+ value = run(cycle)
54
+ assert value == expected
55
+
56
+
57
+ @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
58
+ def test_run_other_sites(*args):
59
+ """
60
+ This test case contains 2 sites:
61
+ One is a crop in france, with value:
62
+ CF_METHOD_factor_france_permanent_crops * ( siteArea_france_crop * time_in_years )
63
+ = 87.631 * ( 1.0082662E-7 * 1 )
64
+ = 8.835537537220001e-06
65
+
66
+ And one a forest in italy, with value:
67
+ CF_METHOD_factor_italy_forest * ( siteArea_italy_forest * time_in_years )
68
+ = 43.198 * ( 1.3573373E-9 * 1 )
69
+ = 5.86342566854E-08
70
+
71
+ We expect the model to return 8.835537537220001e-06 + 5.86342566854E-08 = 8.894171793905402e-06
72
+
73
+ """
74
+ with open(f"{fixtures_folder}/otherSites/cycle.jsonld", encoding='utf-8') as f:
75
+ cycle = json.load(f)
76
+
77
+ with open(f"{fixtures_folder}/otherSites/result.jsonld", encoding='utf-8') as f:
78
+ expected = json.load(f)
79
+
80
+ value = run(cycle)
81
+ assert value == expected
82
+
83
+
84
+ @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
85
+ def test_run_with_subclass_landcover(*args):
86
+ """
87
+ Example data:
88
+ Country: Italy
89
+ Quantity in m^2: 1.3573373E-9
90
+ CF METHOD factor: 4.3198E+01
91
+ "Charact Result [soil quality index]" result also in result.jsonld : 5.86342566854E-08
92
+ siteArea in test file in ha: 1.3573373E-9 / 10 000 = 1.3573373e-13
93
+
94
+ landCover field "plantationForest" should map to
95
+ Name Flow: "forest, intensive Land occupation"
96
+ """
97
+ with open(f"{fixtures_folder}/plantationForest/cycle.jsonld", encoding='utf-8') as f:
98
+ cycle = json.load(f)
99
+
100
+ with open(f"{fixtures_folder}/plantationForest/result.jsonld", encoding='utf-8') as f:
101
+ expected = json.load(f)
102
+
103
+ value = run(cycle)
104
+ assert value == expected
105
+
106
+
107
+ @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
108
+ def test_run_with_region_missing_data(*args):
109
+ """
110
+ When given valid sub-region or country not in the lookup file should default to 'region-world'
111
+ """
112
+ with open(f"{fixtures_folder}/default-region-world/cycle.jsonld", encoding='utf-8') as f:
113
+ cycle = json.load(f)
114
+
115
+ with open(f"{fixtures_folder}/default-region-world/result.jsonld", encoding='utf-8') as f:
116
+ expected = json.load(f)
117
+
118
+ value = run(cycle)
119
+ assert value == expected
120
+
121
+
122
+ @patch(f"{class_path}._new_indicator", side_effect=fake_new_indicator)
123
+ def test_run_with_no_region(*args):
124
+ """
125
+ When no location is specified, defaults to region world.
126
+ """
127
+ with open(f"{fixtures_folder}/cycle.jsonld", encoding='utf-8') as f:
128
+ cycle = json.load(f)
129
+
130
+ del cycle['site']['country']
131
+
132
+ with open(f"{fixtures_folder}/default-region-world/result.jsonld", encoding='utf-8') as f:
133
+ expected = json.load(f)
134
+
135
+ value = run(cycle)
136
+ assert value == expected
@@ -0,0 +1,50 @@
1
+ from hestia_earth.schema import EmissionMethodTier, MeasurementMethodClassification
2
+
3
+ from hestia_earth.models.ipcc2019.co2ToAirCarbonStockChange_utils import (
4
+ add_carbon_stock_change_emissions, calc_carbon_stock_change, calc_carbon_stock_change_emission, _convert_c_to_co2,
5
+ lerp_carbon_stocks, CarbonStock, CarbonStockChange, CarbonStockChangeEmission
6
+ )
7
+
8
+
9
+ def test_convert_c_to_co2():
10
+ KG_C = 1000
11
+ EXPECTED = 3663.836163836164
12
+ assert _convert_c_to_co2(KG_C) == EXPECTED
13
+
14
+
15
+ def test_lerp_carbon_stocks():
16
+ START = CarbonStock(20000, "2000-12-31", MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT)
17
+ END = CarbonStock(22000, "2002-12-31", MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT)
18
+ TARGET_DATE = "2001-12-31"
19
+ EXPECTED = CarbonStock(
20
+ 21000, "2001-12-31", MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT
21
+ )
22
+
23
+ result = lerp_carbon_stocks(START, END, TARGET_DATE)
24
+ assert result == EXPECTED
25
+
26
+
27
+ def test_calc_carbon_stock_change():
28
+ START = CarbonStock(20000, "2000", MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT)
29
+ END = CarbonStock(21000, "2001", MeasurementMethodClassification.TIER_1_MODEL)
30
+ EXPECTED = CarbonStockChange(1000, "2000", "2001", MeasurementMethodClassification.TIER_1_MODEL)
31
+
32
+ result = calc_carbon_stock_change(START, END)
33
+ assert result == EXPECTED
34
+
35
+
36
+ def test_calc_carbon_stock_change_emission():
37
+ SOC_STOCK_CHANGE = CarbonStockChange(-1000, "2000", "2001", MeasurementMethodClassification.TIER_1_MODEL)
38
+ EXPECTED = CarbonStockChangeEmission(3663.836163836164, "2000", "2001", EmissionMethodTier.TIER_1)
39
+
40
+ result = calc_carbon_stock_change_emission(SOC_STOCK_CHANGE)
41
+ assert result == EXPECTED
42
+
43
+
44
+ def test_add_carbon_stock_change_emissions():
45
+ EMISSION_1 = CarbonStockChangeEmission(3000, "2000", "2001", EmissionMethodTier.TIER_1)
46
+ EMISSION_2 = CarbonStockChangeEmission(2000, "2001", "2002", EmissionMethodTier.TIER_1)
47
+ EXPECTED = CarbonStockChangeEmission(5000, "2000", "2002", EmissionMethodTier.TIER_1)
48
+
49
+ result = add_carbon_stock_change_emissions(EMISSION_1, EMISSION_2)
50
+ assert result == EXPECTED
@@ -4,12 +4,7 @@ from os.path import isfile
4
4
  from pytest import mark
5
5
  from unittest.mock import patch
6
6
 
7
- from hestia_earth.schema import EmissionMethodTier, MeasurementMethodClassification
8
-
9
- from hestia_earth.models.ipcc2019.co2ToAirSoilOrganicCarbonStockChangeManagementChange import (
10
- calc_soc_stock_change, calc_soc_stock_change_emission, convert_c_to_co2, lerp_soc_stocks, MODEL, run, TERM_ID,
11
- SocStock, SocStockChange, SocStockChangeEmission
12
- )
7
+ from hestia_earth.models.ipcc2019.co2ToAirSoilOrganicCarbonStockChangeManagementChange import MODEL, run, TERM_ID
13
8
 
14
9
  from tests.utils import fake_new_emission, fixtures_path
15
10
 
@@ -85,36 +80,3 @@ def test_run_empty(_get_site_mock, related_cycles_mock, _new_emission_mock):
85
80
 
86
81
  result = run(CYCLE)
87
82
  assert result == EXPECTED
88
-
89
-
90
- def test_convert_c_to_co2():
91
- KG_C = 1000
92
- EXPECTED = 3663.836163836164
93
- assert convert_c_to_co2(KG_C) == EXPECTED
94
-
95
-
96
- def test_linear_interpolate_soc_stock():
97
- START = SocStock(20000, "2000-12-31", MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT)
98
- END = SocStock(22000, "2002-12-31", MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT)
99
- TARGET_DATE = "2001-12-31"
100
- EXPECTED = SocStock(21000, "2001-12-31", MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT)
101
-
102
- result = lerp_soc_stocks(START, END, TARGET_DATE)
103
- assert result == EXPECTED
104
-
105
-
106
- def test_calc_soc_stock_change():
107
- START = SocStock(20000, "2000", MeasurementMethodClassification.ON_SITE_PHYSICAL_MEASUREMENT)
108
- END = SocStock(21000, "2001", MeasurementMethodClassification.TIER_1_MODEL)
109
- EXPECTED = SocStockChange(1000, "2000", "2001", MeasurementMethodClassification.TIER_1_MODEL)
110
-
111
- result = calc_soc_stock_change(START, END)
112
- assert result == EXPECTED
113
-
114
-
115
- def test_calc_soc_stock_change_emission():
116
- SOC_STOCK_CHANGE = SocStockChange(-1000, "2000", "2001", MeasurementMethodClassification.TIER_1_MODEL)
117
- EXPECTED = SocStockChangeEmission(3663.836163836164, "2000", "2001", EmissionMethodTier.TIER_1)
118
-
119
- result = calc_soc_stock_change_emission(SOC_STOCK_CHANGE)
120
- assert result == EXPECTED
@@ -12,7 +12,7 @@ fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
12
12
  @patch(f"{class_path}.get_crop_lookup_value", return_value=10)
13
13
  @patch(f"{class_path}._is_term_type_incomplete", return_value=True)
14
14
  def test_should_run(mock_is_term_type_incomplete, *args):
15
- cycle = {'products': [{'term': {'@id': 'wheatGrain'}}]}
15
+ cycle = {'cycleDuration': 200, 'products': [{'term': {'@id': 'wheatGrain'}}]}
16
16
 
17
17
  mock_is_term_type_incomplete.return_value = False
18
18
  should_run, *args = _should_run(cycle)
@@ -5,7 +5,6 @@ import pytest
5
5
  from hestia_earth.schema import TermTermType, SiteSiteType
6
6
 
7
7
  from hestia_earth.models.site.management import MODEL, MODEL_KEY, run, _should_run
8
- from hestia_earth.models.utils.blank_node import condense_nodes
9
8
  from tests.utils import fixtures_path
10
9
 
11
10
  CLASS_PATH = f"hestia_earth.models.{MODEL}.{MODEL_KEY}"
@@ -39,152 +38,6 @@ def lookup_side_effect(*args, **kwargs):
39
38
  return True
40
39
 
41
40
 
42
- @pytest.mark.parametrize(
43
- "test_name,input_nodes,expected_output_nodes",
44
- [
45
- (
46
- "No match",
47
- [
48
- {"startDate": "2001", "endDate": "2002", "term": {"@id": "treeNutTree", "units": "% area"},
49
- "value": [2]},
50
- {"startDate": "2003", "endDate": "2004", "term": {"@id": "bananaPlant", "units": "% area"},
51
- "value": [2]},
52
- ],
53
- [
54
- {"startDate": "2001", "endDate": "2002", "term": {"@id": "treeNutTree", "units": "% area"},
55
- "value": [2]},
56
- {"startDate": "2003", "endDate": "2004", "term": {"@id": "bananaPlant", "units": "% area"},
57
- "value": [2]},
58
- ],
59
- ),
60
- (
61
- "No continuity",
62
- [
63
- {"startDate": "2001", "endDate": "2002", "term": {"@id": "treeNutTree", "units": "% area"},
64
- "value": [2]},
65
- {"startDate": "2004", "endDate": "2005", "term": {"@id": "treeNutTree", "units": "% area"},
66
- "value": [2]},
67
- ],
68
- [
69
- {"startDate": "2001", "endDate": "2002", "term": {"@id": "treeNutTree", "units": "% area"},
70
- "value": [2]},
71
- {"startDate": "2004", "endDate": "2005", "term": {"@id": "treeNutTree", "units": "% area"},
72
- "value": [2]},
73
- ],
74
- ),
75
- (
76
- "No continuity (multiple values differ)",
77
- [
78
- {"startDate": "2001", "endDate": "2002", "term": {"@id": "treeNutTree", "units": "% area"},
79
- "value": [10, 20]},
80
- {"startDate": "2003", "endDate": "2004", "term": {"@id": "treeNutTree", "units": "% area"},
81
- "value": [10, 30]},
82
- ],
83
- [
84
- {"startDate": "2001", "endDate": "2002", "term": {"@id": "treeNutTree", "units": "% area"},
85
- "value": [10, 20]},
86
- {"startDate": "2003", "endDate": "2004", "term": {"@id": "treeNutTree", "units": "% area"},
87
- "value": [10, 30]},
88
- ],
89
- ),
90
- (
91
- "2->1 condense (YYYY dates)",
92
- [
93
- {"startDate": "2001", "endDate": "2001", "term": {"@id": "treeNutTree", "units": "% area"},
94
- "value": [10, 20]},
95
- {"startDate": "2002", "endDate": "2002", "term": {"@id": "treeNutTree", "units": "% area"},
96
- "value": [10, 20]},
97
- ],
98
- [
99
- {"startDate": "2001-01-01", "endDate": "2002-12-31", "term": {"@id": "treeNutTree", "units": "% area"},
100
- "value": [10, 20]}
101
- ],
102
- ),
103
- (
104
- "4->2 condense (YYYY-MM dates)",
105
- [
106
- {"startDate": "2001-01", "endDate": "2001-12", "term": {"@id": "treeNutTree", "units": "% area"},
107
- "value": [2]},
108
- {"startDate": "2002-01", "endDate": "2002-03", "term": {"@id": "treeNutTree", "units": "% area"},
109
- "value": [2]},
110
- ],
111
- [
112
- {"startDate": "2001-01-01", "endDate": "2002-03-31", "term": {"@id": "treeNutTree", "units": "% area"},
113
- "value": [2]}
114
- ],
115
- ),
116
- (
117
- "2->1 condense (YYYY-MM-DD dates)",
118
- [
119
- {"startDate": "2001-01-01", "endDate": "2001-12-31", "term": {"@id": "treeNutTree", "units": "% area"},
120
- "value": [2]},
121
- {"startDate": "2002-01-01", "endDate": "2002-05-04", "term": {"@id": "treeNutTree", "units": "% area"},
122
- "value": [2]},
123
- ],
124
- [
125
- {"startDate": "2001-01-01", "endDate": "2002-05-04", "term": {"@id": "treeNutTree", "units": "% area"},
126
- "value": [2]}
127
- ],
128
- ),
129
- (
130
- "3->1 condense",
131
- [
132
- {"startDate": "2001-01-01", "endDate": "2001-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
133
- "value": [9]},
134
- {"startDate": "2002-01-01", "endDate": "2002-10-31", "term": {"@id": "bananaPlant", "units": "% area"},
135
- "value": [9]},
136
- {"startDate": "2002-11-01", "endDate": "2004-04-05", "term": {"@id": "bananaPlant", "units": "% area"},
137
- "value": [9]},
138
- ],
139
- [
140
- {"startDate": "2001-01-01", "endDate": "2004-04-05", "term": {"@id": "bananaPlant", "units": "% area"},
141
- "value": [9]}
142
- ],
143
- ),
144
- (
145
- "3->2 partial condense",
146
- [
147
- {"startDate": "2001-01-01", "endDate": "2001-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
148
- "value": [9]},
149
- {"startDate": "2012-02-01", "endDate": "2012-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
150
- "value": [9]},
151
- {"startDate": "2002-01-01", "endDate": "2003-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
152
- "value": [9]},
153
- ],
154
- [
155
- {"startDate": "2001-01-01", "endDate": "2003-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
156
- "value": [9]},
157
- {"startDate": "2012-02-01", "endDate": "2012-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
158
- "value": [9]}
159
- ],
160
- ),
161
- (
162
- "7->2 multi-condense",
163
- [
164
- {"startDate": "2001-01-01", "endDate": "2001-11-30", "term": {"@id": "bananaPlant", "units": "% area"},
165
- "value": [7]},
166
- {"startDate": "2012-02-01", "endDate": "2012-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
167
- "value": [7]},
168
- {"startDate": "2001-12-01", "endDate": "2001-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
169
- "value": [7]},
170
- {"startDate": "2002-01-01", "endDate": "2002-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
171
- "value": [7]},
172
- {"startDate": "2013-01-01", "endDate": "2013-05-20", "term": {"@id": "bananaPlant", "units": "% area"},
173
- "value": [7]},
174
- ],
175
- [
176
- {"startDate": "2001-01-01", "endDate": "2002-12-31", "term": {"@id": "bananaPlant", "units": "% area"},
177
- "value": [7]},
178
- {"startDate": "2012-02-01", "endDate": "2013-05-20", "term": {"@id": "bananaPlant", "units": "% area"},
179
- "value": [7]}
180
- ],
181
- ),
182
- ]
183
- )
184
- def test_condense_nodes(test_name, input_nodes, expected_output_nodes):
185
- assert condense_nodes(input_nodes) == expected_output_nodes
186
-
187
-
188
41
  @patch(f"{CLASS_PATH}.download_hestia", side_effect=lambda id, *args: TERM_BY_ID[id])
189
42
  @patch(f"{CLASS_PATH}.related_cycles")
190
43
  def test_should_run(mock_related_cycles, *args):
@@ -253,8 +106,7 @@ def test_should_run(mock_related_cycles, *args):
253
106
  },
254
107
  "value": [51],
255
108
  "startDate": "2001",
256
- "endDate": "2002",
257
- "properties": {"test": "properties"}
109
+ "endDate": "2002"
258
110
  }
259
111
  ],
260
112
  "startDate": "2021",
@@ -275,8 +127,7 @@ def test_should_run(mock_related_cycles, *args):
275
127
  },
276
128
  "value": [51],
277
129
  "startDate": "2001",
278
- "endDate": "2002",
279
- "properties": {"test": "properties"}
130
+ "endDate": "2002"
280
131
  }
281
132
  ],
282
133
  "startDate": "2021",
@@ -289,8 +140,7 @@ def test_should_run(mock_related_cycles, *args):
289
140
  'term': TERM_BY_ID['genericCropPlant'],
290
141
  'value': 100,
291
142
  'endDate': '2022',
292
- 'startDate': '2021',
293
- 'properties': {'test': 'properties'}
143
+ 'startDate': '2021'
294
144
  }]
295
145
 
296
146
 
@@ -1,16 +1,17 @@
1
- from numpy import array
2
- from numpy.testing import assert_array_equal
1
+ from numpy import array, corrcoef
2
+ from numpy.testing import assert_array_equal, assert_allclose
3
3
  from numpy.typing import NDArray
4
4
  from pytest import mark
5
5
 
6
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
7
+ avg_run_in_columnwise, avg_run_in_rowwise, correlated_normal_2d, discrete_uniform_1d, discrete_uniform_2d,
8
+ gen_seed, grouped_avg, normal_1d, normal_2d, plus_minus_uncertainty_to_normal_1d,
9
+ plus_minus_uncertainty_to_normal_2d, repeat_1d_array_as_columns, repeat_array_as_columns, repeat_array_as_rows,
10
+ repeat_single, triangular_1d, triangular_2d, truncated_normal_1d, truncated_normal_2d
11
11
  )
12
12
 
13
13
  SEED = 0
14
+ N_ITERATIONS = 10000
14
15
  SHAPE = (1000, 1000)
15
16
 
16
17
 
@@ -251,3 +252,63 @@ def test_gen_seed_no_id():
251
252
  EXPECTED = 2140941220
252
253
  result = gen_seed(NODE)
253
254
  assert result == EXPECTED
255
+
256
+
257
+ # means, sds, correlation_matrix, tol_kwargs
258
+ PARAMS_CORRELATED_NORMAL_2D = [
259
+ (
260
+ array([0, 0, 0, 0, 0]),
261
+ array([1, 1, 1, 1, 1]),
262
+ array([
263
+ [1.0, 0.5, 0.25, 0.125, 0.0625],
264
+ [0.5, 1.0, 0.5, 0.25, 0.125],
265
+ [0.25, 0.5, 1.0, 0.5, 0.25],
266
+ [0.125, 0.25, 0.5, 1.0, 0.5],
267
+ [0.0625, 0.125, 0.25, 0.5, 1.0]
268
+ ]),
269
+ {"atol": 0.05}
270
+ ),
271
+ (
272
+ array([40000, 42000, 43000, 44333.333]),
273
+ array([4000, 4200, 4300, 4433.333]),
274
+ array([
275
+ [1.0, 0.965867, 0.932987, 0.901227],
276
+ [0.965867, 1.0, 0.965959, 0.933076],
277
+ [0.932987, 0.965959, 1.0, 0.965959],
278
+ [0.901227, 0.933076, 0.965959, 1.0]
279
+ ]),
280
+ {"rtol": 0.05}
281
+ ),
282
+ (
283
+ array([40000, 42000, 43000, 44333.333]),
284
+ array([4000, 4200, 4300, 4433.333]),
285
+ array([
286
+ [1.0, 0, 0, 0],
287
+ [0, 1.0, 0, 0],
288
+ [0, 0, 1.0, 0],
289
+ [0, 0, 0, 1.0]
290
+ ]),
291
+ {"rtol": 0.05}
292
+ )
293
+ ]
294
+ IDS_CORRELATED_NORMAL_2D = [
295
+ "standard normal distributions",
296
+ "custom normal distributions",
297
+ "no correlation"
298
+ ]
299
+
300
+
301
+ @mark.parametrize(
302
+ "means, sds, correlation_matrix, tol_kwargs",
303
+ PARAMS_CORRELATED_NORMAL_2D,
304
+ ids=IDS_CORRELATED_NORMAL_2D
305
+ )
306
+ def test_correlated_normal_2d_standard_normal_dist(
307
+ means: NDArray, sds: NDArray, correlation_matrix: NDArray, tol_kwargs: dict
308
+ ):
309
+ result = correlated_normal_2d(N_ITERATIONS, means, sds, correlation_matrix, seed=SEED)
310
+ empirical_correlation_matrix = corrcoef(result)
311
+
312
+ assert_allclose(result.mean(axis=1), means, **tol_kwargs) # row-wise mean matches input
313
+ assert_allclose(result.std(axis=1), sds, **tol_kwargs) # row-wise SD matches input
314
+ assert_allclose(empirical_correlation_matrix, correlation_matrix, atol=0.05) # correlation matches input