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.

Files changed (109) hide show
  1. hestia_earth/models/cycle/aboveGroundCropResidueTotal.py +17 -12
  2. hestia_earth/models/cycle/excretaKgMass.py +4 -5
  3. hestia_earth/models/cycle/excretaKgN.py +4 -5
  4. hestia_earth/models/cycle/excretaKgVs.py +4 -5
  5. hestia_earth/models/cycle/inorganicFertiliser.py +2 -2
  6. hestia_earth/models/cycle/{irrigated.py → irrigatedTypeUnspecified.py} +4 -4
  7. hestia_earth/models/cycle/liveAnimal.py +9 -11
  8. hestia_earth/models/cycle/milkYield.py +154 -0
  9. hestia_earth/models/cycle/residueIncorporated.py +1 -1
  10. hestia_earth/models/cycle/utils.py +6 -0
  11. hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +3 -3
  12. hestia_earth/models/faostat2018/seed.py +2 -3
  13. hestia_earth/models/geospatialDatabase/clayContent.py +17 -4
  14. hestia_earth/models/geospatialDatabase/sandContent.py +17 -4
  15. hestia_earth/models/geospatialDatabase/siltContent.py +2 -2
  16. hestia_earth/models/impact_assessment/irrigated.py +0 -3
  17. hestia_earth/models/ipcc2006/co2ToAirOrganicSoilCultivation.py +2 -2
  18. hestia_earth/models/ipcc2006/n2OToAirCropResidueDecompositionIndirect.py +2 -2
  19. hestia_earth/models/ipcc2006/n2OToAirExcretaDirect.py +1 -1
  20. hestia_earth/models/ipcc2006/n2OToAirExcretaIndirect.py +8 -4
  21. hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserDirect.py +4 -1
  22. hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py +1 -1
  23. hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserDirect.py +1 -1
  24. hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserIndirect.py +1 -1
  25. hestia_earth/models/ipcc2006/utils.py +11 -8
  26. hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +4 -4
  27. hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +16 -7
  28. hestia_earth/models/ipcc2019/co2ToAirSoilCarbonStockChangeManagementChange.py +759 -0
  29. hestia_earth/models/ipcc2019/croppingDuration.py +12 -6
  30. hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionDirect.py +5 -52
  31. hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserDirect.py +104 -0
  32. hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py +1 -1
  33. hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserDirect.py +105 -0
  34. hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py +1 -1
  35. hestia_earth/models/ipcc2019/no3ToGroundwaterCropResidueDecomposition.py +1 -1
  36. hestia_earth/models/ipcc2019/no3ToGroundwaterExcreta.py +1 -1
  37. hestia_earth/models/ipcc2019/no3ToGroundwaterInorganicFertiliser.py +1 -1
  38. hestia_earth/models/ipcc2019/no3ToGroundwaterOrganicFertiliser.py +1 -1
  39. hestia_earth/models/ipcc2019/organicCarbonPerHa.py +1088 -1268
  40. hestia_earth/models/ipcc2019/pastureGrass.py +4 -4
  41. hestia_earth/models/ipcc2019/utils.py +102 -1
  42. hestia_earth/models/koble2014/aboveGroundCropResidue.py +15 -17
  43. hestia_earth/models/koble2014/cropResidueManagement.py +2 -2
  44. hestia_earth/models/koble2014/utils.py +19 -3
  45. hestia_earth/models/linkedImpactAssessment/__init__.py +4 -2
  46. hestia_earth/models/log.py +15 -3
  47. hestia_earth/models/mocking/search-results.json +184 -118
  48. hestia_earth/models/pooreNemecek2018/excretaKgN.py +6 -7
  49. hestia_earth/models/pooreNemecek2018/excretaKgVs.py +7 -6
  50. hestia_earth/models/pooreNemecek2018/no3ToGroundwaterCropResidueDecomposition.py +3 -2
  51. hestia_earth/models/pooreNemecek2018/no3ToGroundwaterExcreta.py +3 -2
  52. hestia_earth/models/pooreNemecek2018/no3ToGroundwaterInorganicFertiliser.py +3 -2
  53. hestia_earth/models/pooreNemecek2018/saplings.py +0 -1
  54. hestia_earth/models/site/management.py +168 -0
  55. hestia_earth/models/site/organicCarbonPerHa.py +251 -89
  56. hestia_earth/models/stehfestBouwman2006/n2OToAirCropResidueDecompositionDirect.py +3 -2
  57. hestia_earth/models/stehfestBouwman2006/n2OToAirExcretaDirect.py +3 -2
  58. hestia_earth/models/stehfestBouwman2006/n2OToAirInorganicFertiliserDirect.py +3 -2
  59. hestia_earth/models/stehfestBouwman2006/n2OToAirOrganicFertiliserDirect.py +3 -2
  60. hestia_earth/models/stehfestBouwman2006/noxToAirCropResidueDecomposition.py +3 -2
  61. hestia_earth/models/stehfestBouwman2006/noxToAirExcreta.py +3 -2
  62. hestia_earth/models/stehfestBouwman2006/noxToAirInorganicFertiliser.py +3 -2
  63. hestia_earth/models/stehfestBouwman2006/noxToAirOrganicFertiliser.py +3 -2
  64. hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirCropResidueDecomposition.py +3 -2
  65. hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirExcreta.py +3 -2
  66. hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirInorganicFertiliser.py +3 -2
  67. hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirOrganicFertiliser.py +3 -2
  68. hestia_earth/models/utils/aggregated.py +1 -0
  69. hestia_earth/models/utils/blank_node.py +394 -72
  70. hestia_earth/models/utils/cropResidue.py +13 -0
  71. hestia_earth/models/utils/cycle.py +18 -9
  72. hestia_earth/models/utils/measurement.py +1 -1
  73. hestia_earth/models/utils/property.py +4 -4
  74. hestia_earth/models/utils/term.py +48 -3
  75. hestia_earth/models/version.py +1 -1
  76. {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/METADATA +5 -9
  77. {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/RECORD +109 -97
  78. {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/WHEEL +1 -1
  79. tests/models/cycle/animal/input/test_hestiaAggregatedData.py +2 -14
  80. tests/models/cycle/input/test_hestiaAggregatedData.py +4 -16
  81. tests/models/cycle/test_coldCarcassWeightPerHead.py +1 -1
  82. tests/models/cycle/test_coldDressedCarcassWeightPerHead.py +1 -1
  83. tests/models/cycle/{test_irrigated.py → test_irrigatedTypeUnspecified.py} +1 -1
  84. tests/models/cycle/test_milkYield.py +58 -0
  85. tests/models/cycle/test_readyToCookWeightPerHead.py +1 -1
  86. tests/models/emepEea2019/test_nh3ToAirInorganicFertiliser.py +1 -1
  87. tests/models/geospatialDatabase/test_clayContent.py +9 -3
  88. tests/models/geospatialDatabase/test_sandContent.py +9 -3
  89. tests/models/ipcc2006/test_n2OToAirExcretaDirect.py +7 -2
  90. tests/models/ipcc2006/test_n2OToAirExcretaIndirect.py +1 -1
  91. tests/models/ipcc2006/test_n2OToAirInorganicFertiliserDirect.py +7 -2
  92. tests/models/ipcc2006/test_n2OToAirInorganicFertiliserIndirect.py +7 -2
  93. tests/models/ipcc2006/test_n2OToAirOrganicFertiliserDirect.py +7 -2
  94. tests/models/ipcc2006/test_n2OToAirOrganicFertiliserIndirect.py +7 -2
  95. tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +1 -1
  96. tests/models/ipcc2019/test_co2ToAirSoilCarbonStockChangeManagementChange.py +228 -0
  97. tests/models/ipcc2019/test_n2OToAirInorganicFertiliserDirect.py +74 -0
  98. tests/models/ipcc2019/test_n2OToAirOrganicFertiliserDirect.py +74 -0
  99. tests/models/ipcc2019/test_organicCarbonPerHa.py +303 -1044
  100. tests/models/koble2014/test_residueBurnt.py +1 -2
  101. tests/models/koble2014/test_residueLeftOnField.py +1 -2
  102. tests/models/koble2014/test_residueRemoved.py +1 -2
  103. tests/models/koble2014/test_utils.py +52 -0
  104. tests/models/site/test_management.py +117 -0
  105. tests/models/site/test_organicCarbonPerHa.py +51 -5
  106. tests/models/utils/test_blank_node.py +230 -34
  107. tests/models/utils/test_term.py +17 -3
  108. {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/LICENSE +0 -0
  109. {hestia_earth_models-0.57.2.dist-info → hestia_earth_models-0.59.0.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,10 @@
1
1
  from unittest.mock import patch
2
2
  import json
3
- from tests.utils import fixtures_path, fake_new_practice
3
+ from tests.utils import RESIDUE_TERMS, fixtures_path, fake_new_practice
4
4
 
5
5
  from hestia_earth.models.koble2014.residueBurnt import MODEL, TERM_ID, run
6
6
 
7
7
  fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
8
- RESIDUE_TERMS = ['residueIncorporated', 'residueRemoved', 'residueBurnt', 'residueLeftOnField']
9
8
 
10
9
 
11
10
  @patch(f"hestia_earth.models.{MODEL}.utils.get_crop_residue_management_terms", return_value=RESIDUE_TERMS)
@@ -1,12 +1,11 @@
1
1
  from unittest.mock import patch
2
2
  import json
3
- from tests.utils import fixtures_path, fake_new_practice
3
+ from tests.utils import RESIDUE_TERMS, fixtures_path, fake_new_practice
4
4
 
5
5
  from hestia_earth.models.koble2014 import MODEL
6
6
  from hestia_earth.models.koble2014.residueLeftOnField import TERM_ID, run
7
7
 
8
8
  fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
9
- RESIDUE_TERMS = ['residueIncorporated', 'residueRemoved', 'residueBurnt', 'residueLeftOnField']
10
9
 
11
10
 
12
11
  @patch(f"hestia_earth.models.{MODEL}.utils.get_crop_residue_management_terms", return_value=RESIDUE_TERMS)
@@ -1,11 +1,10 @@
1
1
  from unittest.mock import patch
2
2
  import json
3
- from tests.utils import fixtures_path, fake_new_practice
3
+ from tests.utils import RESIDUE_TERMS, fixtures_path, fake_new_practice
4
4
 
5
5
  from hestia_earth.models.koble2014.residueRemoved import MODEL, TERM_ID, run
6
6
 
7
7
  fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
8
- RESIDUE_TERMS = ['residueIncorporated', 'residueRemoved', 'residueBurnt', 'residueLeftOnField']
9
8
 
10
9
 
11
10
  @patch(f"hestia_earth.models.{MODEL}.utils.get_crop_residue_management_terms", return_value=RESIDUE_TERMS)
@@ -0,0 +1,52 @@
1
+ from unittest.mock import patch
2
+ from tests.utils import RESIDUE_TERMS
3
+
4
+ from hestia_earth.models.koble2014 import MODEL
5
+ from hestia_earth.models.koble2014.utils import _should_run
6
+
7
+ class_path = '.'.join(['hestia_earth', 'models', MODEL, 'utils'])
8
+
9
+
10
+ @patch(f"hestia_earth.models.{MODEL}.utils.get_crop_residue_management_terms", return_value=RESIDUE_TERMS)
11
+ @patch(f"{class_path}.find_primary_product", return_value={})
12
+ def test_should_run(*args):
13
+ cycle = {'completeness': {'cropResidue': False}}
14
+
15
+ # with 100% practices => no run
16
+ cycle['practices'] = [
17
+ {
18
+ 'term': {'termType': 'cropResidueManagement', '@id': RESIDUE_TERMS[0]},
19
+ 'value': [100]
20
+ }
21
+ ]
22
+ should_run, *ars = _should_run('', cycle)
23
+ assert not should_run
24
+
25
+ # with below 100% practices => run
26
+ cycle['practices'] = [
27
+ {
28
+ 'term': {'termType': 'cropResidueManagement', '@id': RESIDUE_TERMS[0]},
29
+ 'value': [50]
30
+ }
31
+ ]
32
+ should_run, *ars = _should_run('', cycle)
33
+ assert should_run is True
34
+
35
+ # requires country / no country => no run
36
+ should_run, *ars = _should_run('', cycle, require_country=True)
37
+ assert not should_run
38
+
39
+ # requires country / with country => run
40
+ cycle['site'] = {'country': {'@id': 'GADM-GBR'}}
41
+ should_run, *ars = _should_run('', cycle, require_country=True)
42
+ assert should_run is True
43
+
44
+ # with existing product => no run
45
+ cycle['products'] = [
46
+ {
47
+ 'term': {'termType': 'cropResidue', '@id': 'aboveGroundCropResidueRemoved'},
48
+ 'value': [50]
49
+ }
50
+ ]
51
+ should_run, *ars = _should_run('', cycle)
52
+ assert not should_run
@@ -0,0 +1,117 @@
1
+ import json
2
+ from unittest.mock import patch
3
+ from hestia_earth.schema import TermTermType
4
+
5
+ from hestia_earth.models.site.management import MODEL, MODEL_KEY, run, should_run
6
+ from tests.utils import fixtures_path
7
+
8
+ CLASS_PATH = f"hestia_earth.models.{MODEL}.{MODEL_KEY}"
9
+ fixtures_folder = f"{fixtures_path}/{MODEL}/{MODEL_KEY}"
10
+
11
+ TERM_BY_ID = {
12
+ 'genericCropPlant': {'@type': 'Term', '@id': 'genericCropPlant', 'termType': TermTermType.LANDCOVER.value}
13
+ }
14
+
15
+
16
+ @patch(f"{CLASS_PATH}.download_hestia", side_effect=lambda id, *args: TERM_BY_ID[id])
17
+ @patch(f"{CLASS_PATH}.related_cycles")
18
+ def test_should_run(mock_related_cycles, *args):
19
+ # no cycles => do not run
20
+ mock_related_cycles.return_value = []
21
+ _should_run, *args = should_run({})
22
+ assert _should_run is False
23
+
24
+ # no products => do not run
25
+ mock_related_cycles.return_value = [{"products": []}]
26
+ _should_run, *args = should_run({})
27
+ assert _should_run is False
28
+
29
+ # with irrelevant termType => do not run
30
+ mock_related_cycles.return_value = [
31
+ {
32
+ "products": [
33
+ {"term": {"termType": TermTermType.BUILDING.value}},
34
+ {"term": {"termType": TermTermType.EXCRETA.value}}
35
+ ],
36
+ "startDate": "2021",
37
+ "endDate": "2022"
38
+ }
39
+ ]
40
+ _should_run, *args = should_run({})
41
+ assert _should_run is False
42
+
43
+ # products and practices but no relevant terms/termTypes => do not run
44
+ mock_related_cycles.return_value = [
45
+ {
46
+ "practices": [
47
+ {"term": {"@id": "soilAssociationOrganicStandard"}},
48
+ {"term": {"@id": "noTillage"}}
49
+ ],
50
+ "products": [
51
+ {"term": {"termType": TermTermType.BUILDING.value}},
52
+ {"term": {"termType": TermTermType.EXCRETA.value}}
53
+ ]
54
+ }
55
+ ]
56
+ _should_run, *args = should_run({})
57
+ assert _should_run is False
58
+
59
+ # # practices with relevant termType => run
60
+ mock_related_cycles.return_value = [
61
+ {
62
+ "practices": [
63
+ {"term": {"termType": TermTermType.WATERREGIME.value}},
64
+ {"term": {"termType": TermTermType.MACHINERY.value}}
65
+ ],
66
+ "startDate": "2021",
67
+ "endDate": "2022"
68
+ }
69
+ ]
70
+ _should_run, *args = should_run({})
71
+ assert _should_run is True
72
+
73
+ # with relevant product => run
74
+ mock_related_cycles.return_value = [
75
+ {
76
+ "products": [
77
+ {
78
+ "term": {
79
+ "termType": TermTermType.CROP.value,
80
+ "@id": "genericCropProduct"
81
+ },
82
+ "value": [51],
83
+ "startDate": "2001",
84
+ "endDate": "2002",
85
+ "properties": {"test": "properties"}
86
+ }
87
+ ],
88
+ "startDate": "2021",
89
+ "endDate": "2022"
90
+ }
91
+ ]
92
+ _should_run, *args = should_run({})
93
+ assert _should_run is True
94
+ assert args[0] == [{
95
+ 'term': TERM_BY_ID['genericCropPlant'],
96
+ 'value': 100,
97
+ 'endDate': '2002',
98
+ 'startDate': '2001',
99
+ 'properties': {'test': 'properties'}
100
+ }]
101
+
102
+
103
+ @patch(f"{CLASS_PATH}.download_hestia", side_effect=lambda id, *args: TERM_BY_ID[id])
104
+ @patch(f"{CLASS_PATH}.related_cycles")
105
+ def test_run(mock_related_cycles, *args):
106
+ with open(f"{fixtures_folder}/cycles.jsonld", encoding='utf-8') as f:
107
+ cycles = json.load(f)
108
+ mock_related_cycles.return_value = cycles
109
+
110
+ with open(f"{fixtures_folder}/site.jsonld", encoding='utf-8') as f:
111
+ site = json.load(f)
112
+
113
+ with open(f"{fixtures_folder}/result.jsonld", encoding='utf-8') as f:
114
+ expected = json.load(f)
115
+
116
+ result = run(site)
117
+ assert result == expected
@@ -5,13 +5,19 @@ 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_last_date, _should_run_measurements
8
+ MODEL, TERM_ID, run, _cdf, _c_to_depth, _get_most_relevant_soc_node, _get_last_date, _should_run_calculation_group
9
9
  )
10
10
 
11
11
  class_path = f"hestia_earth.models.{MODEL}.{TERM_ID}"
12
12
  fixtures_folder = f"{fixtures_path}/{MODEL}/{TERM_ID}"
13
13
 
14
- SUBFOLDERS = ["calculate", "rescale", "calculate-and-rescale"]
14
+ SUBFOLDERS = [
15
+ "calculate-single",
16
+ "calculate-multiple",
17
+ "rescale-single",
18
+ "rescale-multiple",
19
+ "calculate-and-rescale"
20
+ ]
15
21
 
16
22
 
17
23
  @mark.parametrize("depth, expected", [(0, 0), (1, 10.41666666666667)], ids=["0m", "1m"])
@@ -36,21 +42,55 @@ def test_cdf(depth_upper, depth_lower, expected):
36
42
  (["2020-01-01", "2020-02-28"], "2020-02-28"),
37
43
  ([], None)
38
44
  ],
39
- ids=["YYYY", "YYYY-MM", "YYYY-MM-DD", "Empty list"]
45
+ ids=["YYYY", "YYYY-MM", "YYYY-MM-DD", "empty-list"]
40
46
  )
41
47
  def test_get_node_date(dates, expected):
42
48
  assert _get_last_date(dates) == expected
43
49
 
44
50
 
51
+ @mark.parametrize(
52
+ "nodes, expected_id",
53
+ [
54
+ (
55
+ [
56
+ {"@id": "1", "depthUpper": 0, "depthLower": 10},
57
+ {"@id": "2", "depthUpper": 0, "depthLower": 40},
58
+ {"@id": "3", "depthUpper": 0, "depthLower": 100}
59
+ ],
60
+ "2"
61
+ ),
62
+ (
63
+ [
64
+ {"@id": "1", "depthUpper": 0, "depthLower": 5},
65
+ {"@id": "2", "depthUpper": 0, "depthLower": 10},
66
+ {"@id": "3", "depthUpper": 0, "depthLower": 20}
67
+ ],
68
+ "3"
69
+ ),
70
+ (
71
+ [
72
+ {"@id": "1", "depthUpper": 0, "depthLower": 20},
73
+ {"@id": "2", "depthUpper": 0, "depthLower": 40},
74
+ {"@id": "3", "depthUpper": 0, "depthLower": 100}
75
+ ],
76
+ "2"
77
+ )
78
+ ],
79
+ ids=["simple", "no-priority", "tie"]
80
+ )
81
+ def test_get_most_relevant_soc_node(nodes, expected_id):
82
+ assert _get_most_relevant_soc_node(nodes).get("@id") == expected_id
83
+
84
+
45
85
  @patch(f"{class_path}.find_term_match")
46
86
  def test_should_run_measurements(mock_find):
47
87
  # no measurement => no run
48
88
  mock_find.return_value = {}
49
- assert not _should_run_measurements({}, [])
89
+ assert _should_run_calculation_group([]) is False
50
90
 
51
91
  # with measurement => run
52
92
  mock_find.return_value = {'value': [10], 'depthUpper': 0, 'depthLower': 10}
53
- assert _should_run_measurements({}, []) is True
93
+ assert _should_run_calculation_group([]) is True
54
94
 
55
95
 
56
96
  @mark.parametrize("subfolder", SUBFOLDERS)
@@ -65,3 +105,9 @@ def test_run(_new_measurement_mock, get_source_mock, subfolder):
65
105
 
66
106
  value = run(site)
67
107
  assert value == expected
108
+
109
+
110
+ @patch(f"{class_path}.get_source", return_value={})
111
+ @patch(f"{class_path}._new_measurement", side_effect=fake_new_measurement)
112
+ def test_run_empty(_new_measurement_mock, get_source_mock):
113
+ assert run({}) == []