hestia-earth-models 0.62.4__py3-none-any.whl → 0.62.6__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 (55) hide show
  1. hestia_earth/models/cycle/croppingIntensity.py +57 -0
  2. hestia_earth/models/cycle/longFallowRatio.py +52 -0
  3. hestia_earth/models/cycle/siteDuration.py +23 -3
  4. hestia_earth/models/cycle/siteUnusedDuration.py +64 -0
  5. hestia_earth/models/emepEea2019/co2ToAirFuelCombustion.py +2 -10
  6. hestia_earth/models/emepEea2019/n2OToAirFuelCombustionDirect.py +2 -10
  7. hestia_earth/models/emepEea2019/nh3ToAirExcreta.py +2 -9
  8. hestia_earth/models/emepEea2019/nh3ToAirInorganicFertiliser.py +2 -9
  9. hestia_earth/models/emepEea2019/noxToAirFuelCombustion.py +2 -10
  10. hestia_earth/models/emepEea2019/pm10ToAirAnimalHousing.py +57 -0
  11. hestia_earth/models/emepEea2019/pm25ToAirAnimalHousing.py +57 -0
  12. hestia_earth/models/emepEea2019/so2ToAirFuelCombustion.py +2 -10
  13. hestia_earth/models/emepEea2019/tspToAirAnimalHousing.py +57 -0
  14. hestia_earth/models/emepEea2019/utils.py +60 -1
  15. hestia_earth/models/geospatialDatabase/croppingIntensity.py +32 -22
  16. hestia_earth/models/geospatialDatabase/longFallowRatio.py +34 -23
  17. hestia_earth/models/ipcc2019/animal/pastureGrass.py +2 -2
  18. hestia_earth/models/ipcc2019/pastureGrass.py +2 -2
  19. hestia_earth/models/ipcc2019/pastureGrass_utils.py +1 -10
  20. hestia_earth/models/mocking/mock_search.py +14 -8
  21. hestia_earth/models/mocking/search-results.json +27 -27
  22. hestia_earth/models/pooreNemecek2018/longFallowPeriod.py +1 -2
  23. hestia_earth/models/pooreNemecek2018/nurseryDensity.py +1 -2
  24. hestia_earth/models/pooreNemecek2018/nurseryDuration.py +1 -2
  25. hestia_earth/models/pooreNemecek2018/plantationDensity.py +1 -2
  26. hestia_earth/models/pooreNemecek2018/plantationLifespan.py +1 -2
  27. hestia_earth/models/pooreNemecek2018/plantationProductiveLifespan.py +1 -2
  28. hestia_earth/models/preload_requests.py +14 -7
  29. hestia_earth/models/site/management.py +7 -5
  30. hestia_earth/models/utils/__init__.py +0 -9
  31. hestia_earth/models/utils/cycle.py +20 -3
  32. hestia_earth/models/utils/product.py +2 -2
  33. hestia_earth/models/version.py +1 -1
  34. {hestia_earth_models-0.62.4.dist-info → hestia_earth_models-0.62.6.dist-info}/METADATA +2 -2
  35. {hestia_earth_models-0.62.4.dist-info → hestia_earth_models-0.62.6.dist-info}/RECORD +55 -43
  36. tests/models/cycle/test_croppingIntensity.py +53 -0
  37. tests/models/cycle/test_longFallowRatio.py +49 -0
  38. tests/models/cycle/test_siteDuration.py +41 -14
  39. tests/models/cycle/test_siteUnusedDuration.py +55 -0
  40. tests/models/emepEea2019/test_co2ToAirFuelCombustion.py +3 -2
  41. tests/models/emepEea2019/test_n2OToAirFuelCombustionDirect.py +3 -2
  42. tests/models/emepEea2019/test_nh3ToAirExcreta.py +2 -1
  43. tests/models/emepEea2019/test_nh3ToAirInorganicFertiliser.py +4 -3
  44. tests/models/emepEea2019/test_noxToAirFuelCombustion.py +3 -2
  45. tests/models/emepEea2019/test_pm10ToAirAnimalHousing.py +21 -0
  46. tests/models/emepEea2019/test_pm25ToAirAnimalHousing.py +21 -0
  47. tests/models/emepEea2019/test_so2ToAirFuelCombustion.py +3 -2
  48. tests/models/emepEea2019/test_tspToAirAnimalHousing.py +21 -0
  49. tests/models/emepEea2019/test_utils.py +198 -1
  50. tests/models/geospatialDatabase/test_croppingIntensity.py +5 -3
  51. tests/models/geospatialDatabase/test_longFallowRatio.py +5 -3
  52. tests/models/site/test_management.py +1 -0
  53. {hestia_earth_models-0.62.4.dist-info → hestia_earth_models-0.62.6.dist-info}/LICENSE +0 -0
  54. {hestia_earth_models-0.62.4.dist-info → hestia_earth_models-0.62.6.dist-info}/WHEEL +0 -0
  55. {hestia_earth_models-0.62.4.dist-info → hestia_earth_models-0.62.6.dist-info}/top_level.txt +0 -0
@@ -1,31 +1,40 @@
1
1
  from hestia_earth.schema import TermTermType
2
- from hestia_earth.utils.model import find_primary_product
2
+ from hestia_earth.utils.model import find_primary_product, linked_node
3
+ from hestia_earth.utils.tools import non_empty_list
3
4
 
4
- from hestia_earth.models.log import logRequirements, logShouldRun
5
+ from hestia_earth.models.log import logRequirements, logShouldRun, debugValues, log_as_table
5
6
  from hestia_earth.models.utils.practice import _new_practice
6
7
  from hestia_earth.models.utils.crop import is_plantation
8
+ from hestia_earth.models.utils.cycle import get_allowed_sites
7
9
  from .utils import get_region_factor
8
10
  from . import MODEL
9
11
 
10
12
  REQUIREMENTS = {
11
13
  "Cycle": {
12
- "products": [{
13
- "@type": "Product",
14
- "primary": "True",
15
- "term.termType": "crop"
16
- }],
17
14
  "site": {
18
15
  "@type": "Site",
19
16
  "or": [
20
17
  {"region": {"@type": "Term"}},
21
18
  {"country": {"@type": "Term"}}
22
19
  ]
20
+ },
21
+ "optional": {
22
+ "otherSites": [
23
+ {
24
+ "@type": "Site",
25
+ "or": [
26
+ {"region": {"@type": "Term"}},
27
+ {"country": {"@type": "Term"}}
28
+ ]
29
+ }
30
+ ]
23
31
  }
24
32
  }
25
33
  }
26
34
  RETURNS = {
27
35
  "Practice": [{
28
- "value": ""
36
+ "value": "",
37
+ "site": ""
29
38
  }]
30
39
  }
31
40
  LOOKUPS = {
@@ -35,25 +44,14 @@ LOOKUPS = {
35
44
  TERM_ID = 'croppingIntensity'
36
45
 
37
46
 
38
- def _practice(value: float):
47
+ def _practice(site: dict, value: float):
39
48
  practice = _new_practice(TERM_ID)
49
+ practice['site'] = linked_node(site)
40
50
  # force conversion to float from numpy, avoiding errors when reading it in other models
41
51
  practice['value'] = [float(round(value, 7))]
42
52
  return practice
43
53
 
44
54
 
45
- def _run(cycle: dict):
46
- site = cycle.get('site')
47
- region_factor = get_region_factor(TERM_ID, site, TermTermType.LANDUSEMANAGEMENT)
48
-
49
- logRequirements(site, model=MODEL, term=TERM_ID,
50
- region_factor=region_factor)
51
-
52
- should_run = all([region_factor])
53
- logShouldRun(site, MODEL, TERM_ID, should_run)
54
- return [_practice(region_factor)] if should_run else []
55
-
56
-
57
55
  def _should_run(cycle: dict):
58
56
  product = find_primary_product(cycle) or {}
59
57
  not_plantation = not is_plantation(MODEL, TERM_ID, product.get('term', {}).get('@id'))
@@ -66,4 +64,16 @@ def _should_run(cycle: dict):
66
64
  return should_run
67
65
 
68
66
 
69
- def run(cycle: dict): return _run(cycle) if _should_run(cycle) else []
67
+ def run(cycle: dict):
68
+ sites = get_allowed_sites(MODEL, TERM_ID, TermTermType.LANDUSEMANAGEMENT, cycle) if _should_run(cycle) else []
69
+ sites = [
70
+ (site, get_region_factor(TERM_ID, site, TermTermType.LANDUSEMANAGEMENT)) for site in sites
71
+ ]
72
+
73
+ debugValues(cycle, model=MODEL, term=TERM_ID,
74
+ site_factors=log_as_table([{
75
+ 'site-id': site.get('@id', site.get('id')),
76
+ 'factor': factor
77
+ } for site, factor in sites]))
78
+
79
+ return non_empty_list([_practice(site, factor) for site, factor in sites if bool(factor)])
@@ -1,31 +1,40 @@
1
1
  from hestia_earth.schema import TermTermType
2
- from hestia_earth.utils.model import find_primary_product
2
+ from hestia_earth.utils.model import find_primary_product, linked_node
3
+ from hestia_earth.utils.tools import non_empty_list
3
4
 
4
- from hestia_earth.models.log import logRequirements, logShouldRun
5
+ from hestia_earth.models.log import logRequirements, logShouldRun, debugValues, log_as_table
5
6
  from hestia_earth.models.utils.practice import _new_practice
6
7
  from hestia_earth.models.utils.crop import is_plantation
8
+ from hestia_earth.models.utils.cycle import get_allowed_sites
7
9
  from .utils import get_region_factor
8
10
  from . import MODEL
9
11
 
10
12
  REQUIREMENTS = {
11
13
  "Cycle": {
12
- "products": [{
13
- "@type": "Product",
14
- "primary": "True",
15
- "term.termType": "crop"
16
- }],
17
14
  "site": {
18
15
  "@type": "Site",
19
16
  "or": [
20
17
  {"region": {"@type": "Term"}},
21
18
  {"country": {"@type": "Term"}}
22
19
  ]
20
+ },
21
+ "optional": {
22
+ "otherSites": [
23
+ {
24
+ "@type": "Site",
25
+ "or": [
26
+ {"region": {"@type": "Term"}},
27
+ {"country": {"@type": "Term"}}
28
+ ]
29
+ }
30
+ ]
23
31
  }
24
32
  }
25
33
  }
26
34
  RETURNS = {
27
35
  "Practice": [{
28
- "value": ""
36
+ "value": "",
37
+ "site": ""
29
38
  }]
30
39
  }
31
40
  LOOKUPS = {
@@ -35,24 +44,14 @@ LOOKUPS = {
35
44
  TERM_ID = 'longFallowRatio'
36
45
 
37
46
 
38
- def _practice(value: float):
47
+ def _practice(site: dict, value: float):
39
48
  practice = _new_practice(TERM_ID)
40
- practice['value'] = [round(value, 7)]
49
+ practice['site'] = linked_node(site)
50
+ # force conversion to float from numpy, avoiding errors when reading it in other models
51
+ practice['value'] = [float(round(value, 7))]
41
52
  return practice
42
53
 
43
54
 
44
- def _run(cycle: dict):
45
- site = cycle.get('site')
46
- region_factor = get_region_factor(TERM_ID, site, TermTermType.LANDUSEMANAGEMENT)
47
-
48
- logRequirements(site, model=MODEL, term=TERM_ID,
49
- region_factor=region_factor)
50
-
51
- should_run = all([region_factor])
52
- logShouldRun(site, MODEL, TERM_ID, should_run)
53
- return [_practice(region_factor)] if should_run else []
54
-
55
-
56
55
  def _should_run(cycle: dict):
57
56
  product = find_primary_product(cycle) or {}
58
57
  not_plantation = not is_plantation(MODEL, TERM_ID, product.get('term', {}).get('@id'))
@@ -65,4 +64,16 @@ def _should_run(cycle: dict):
65
64
  return should_run
66
65
 
67
66
 
68
- def run(cycle: dict): return _run(cycle) if _should_run(cycle) else []
67
+ def run(cycle: dict):
68
+ sites = get_allowed_sites(MODEL, TERM_ID, TermTermType.LANDUSEMANAGEMENT, cycle) if _should_run(cycle) else []
69
+ sites = [
70
+ (site, get_region_factor(TERM_ID, site, TermTermType.LANDUSEMANAGEMENT)) for site in sites
71
+ ]
72
+
73
+ debugValues(cycle, model=MODEL, term=TERM_ID,
74
+ site_factors=log_as_table([{
75
+ 'site-id': site.get('@id', site.get('id')),
76
+ 'factor': factor
77
+ } for site, factor in sites]))
78
+
79
+ return non_empty_list([_practice(site, factor) for site, factor in sites if bool(factor)])
@@ -18,6 +18,7 @@ from hestia_earth.models.utils.input import _new_input
18
18
  from hestia_earth.models.utils.term import get_wool_terms, get_lookup_value
19
19
  from hestia_earth.models.utils.completeness import _is_term_type_complete, _is_term_type_incomplete
20
20
  from hestia_earth.models.utils.property import get_node_property
21
+ from hestia_earth.models.utils.cycle import get_animals_by_period
21
22
  from .. import MODEL
22
23
  from ..pastureGrass_utils import (
23
24
  practice_input_id,
@@ -29,7 +30,6 @@ from ..pastureGrass_utils import (
29
30
  calculate_NEfeed,
30
31
  calculate_GE,
31
32
  product_wool_energy,
32
- get_animals,
33
33
  get_animal_values
34
34
  )
35
35
 
@@ -308,7 +308,7 @@ def _should_run(cycle: dict, animals: list, practices: dict):
308
308
 
309
309
 
310
310
  def run(cycle: dict):
311
- animals = get_animals(cycle)
311
+ animals = get_animals_by_period(cycle)
312
312
  practices = list(filter(should_run_practice(cycle), cycle.get('practices', [])))
313
313
  should_run, meanDE, meanECHHV, system = _should_run(cycle, animals, practices)
314
314
  return list(map(_run_animal(cycle, meanDE, meanECHHV, system, practices), animals)) if should_run else []
@@ -17,6 +17,7 @@ from hestia_earth.models.utils.blank_node import lookups_logs, properties_logs
17
17
  from hestia_earth.models.utils.input import _new_input
18
18
  from hestia_earth.models.utils.term import get_wool_terms
19
19
  from hestia_earth.models.utils.completeness import _is_term_type_complete, _is_term_type_incomplete
20
+ from hestia_earth.models.utils.cycle import get_animals_by_period
20
21
  from . import MODEL
21
22
  from .pastureGrass_utils import (
22
23
  practice_input_id,
@@ -28,7 +29,6 @@ from .pastureGrass_utils import (
28
29
  calculate_NEfeed,
29
30
  calculate_GE,
30
31
  product_wool_energy,
31
- get_animals,
32
32
  get_animal_values
33
33
  )
34
34
 
@@ -164,7 +164,7 @@ def calculate_NEwool(cycle: dict) -> float:
164
164
 
165
165
 
166
166
  def _run_practice(cycle: dict, meanDE: float, meanECHHV: float, system: dict):
167
- animals = get_animals(cycle)
167
+ animals = get_animals_by_period(cycle)
168
168
  REM = calculate_REM(meanDE)
169
169
  REG = calculate_REG(meanDE)
170
170
  NEwool = calculate_NEwool(cycle)
@@ -1,4 +1,4 @@
1
- from hestia_earth.schema import TermTermType, AnimalReferencePeriod
1
+ from hestia_earth.schema import TermTermType
2
2
  from hestia_earth.utils.api import download_hestia
3
3
  from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name, extract_grouped_data
4
4
  from hestia_earth.utils.tools import list_sum, safe_parse_float
@@ -341,12 +341,3 @@ def should_run_practice(cycle: dict):
341
341
  return all([len(value) > 0, term_id == MODEL_KEY, key_term_type in KEY_TERM_TYPES])
342
342
 
343
343
  return should_run
344
-
345
-
346
- def get_animals(cycle: dict):
347
- return [
348
- a for a in cycle.get('animals', []) if all([
349
- a.get('value'),
350
- a.get('referencePeriod') == AnimalReferencePeriod.AVERAGE.value
351
- ])
352
- ]
@@ -52,20 +52,26 @@ def _load_results(filepath: str):
52
52
 
53
53
  def _find_search_result(filepath: str, query: dict):
54
54
  search_results = _load_results(filepath)
55
- res = next((n for n in search_results if n['query'] == query), {})
56
- return res.get('results', [])
55
+ res = next((n for n in search_results if n['query'] == query), None)
56
+ return None if res is None else res.get('results', [])
57
57
 
58
58
 
59
- def _fake_search(filepath: str):
60
- def mock(query: dict, *_a, **_b): return _find_search_result(filepath, query)
59
+ def _mocked_search(original_func, filepath: str):
60
+ def mock(query: dict, **kwargs):
61
+ result = _find_search_result(filepath, query)
62
+ return original_func(query, **kwargs) if result is None else result
61
63
  return mock
62
64
 
63
65
 
64
- def _fake_find_node(filepath: str):
65
- def mock(_n, query: dict, *_a, **_b): return _find_search_result(filepath, query)
66
+ def _mocked_find_node(original_func, filepath: str):
67
+ def mock(node_type: str, query: dict, **kwargs):
68
+ result = _find_search_result(filepath, query)
69
+ return original_func(node_type, query, **kwargs) if result is None else result
66
70
  return mock
67
71
 
68
72
 
69
73
  def mock(filepath: str):
70
- term.search = _fake_search(filepath)
71
- term.find_node = _fake_find_node(filepath)
74
+ original_search = term.search
75
+ term.search = _mocked_search(original_search, filepath)
76
+ original_find_node = term.find_node
77
+ term.find_node = _mocked_find_node(original_find_node, filepath)
@@ -1054,11 +1054,11 @@
1054
1054
  "results": [
1055
1055
  {
1056
1056
  "@type": "Term",
1057
- "@id": "residueIncorporatedLessThan30DaysBeforeCultivation"
1057
+ "@id": "residueIncorporated"
1058
1058
  },
1059
1059
  {
1060
1060
  "@type": "Term",
1061
- "@id": "residueIncorporated"
1061
+ "@id": "residueIncorporatedMoreThan30DaysBeforeCultivation"
1062
1062
  },
1063
1063
  {
1064
1064
  "@type": "Term",
@@ -1066,7 +1066,7 @@
1066
1066
  },
1067
1067
  {
1068
1068
  "@type": "Term",
1069
- "@id": "residueIncorporatedMoreThan30DaysBeforeCultivation"
1069
+ "@id": "residueIncorporatedLessThan30DaysBeforeCultivation"
1070
1070
  },
1071
1071
  {
1072
1072
  "@type": "Term",
@@ -1110,27 +1110,27 @@
1110
1110
  },
1111
1111
  {
1112
1112
  "@type": "Term",
1113
- "@id": "aboveGroundCropResidueBurnt"
1113
+ "@id": "discardedCropRemoved"
1114
1114
  },
1115
1115
  {
1116
1116
  "@type": "Term",
1117
- "@id": "belowGroundCropResidue"
1117
+ "@id": "aboveGroundCropResidueTotal"
1118
1118
  },
1119
1119
  {
1120
1120
  "@type": "Term",
1121
- "@id": "aboveGroundCropResidueLeftOnField"
1121
+ "@id": "aboveGroundCropResidueIncorporated"
1122
1122
  },
1123
1123
  {
1124
1124
  "@type": "Term",
1125
- "@id": "discardedCropRemoved"
1125
+ "@id": "aboveGroundCropResidueBurnt"
1126
1126
  },
1127
1127
  {
1128
1128
  "@type": "Term",
1129
- "@id": "aboveGroundCropResidueTotal"
1129
+ "@id": "belowGroundCropResidue"
1130
1130
  },
1131
1131
  {
1132
1132
  "@type": "Term",
1133
- "@id": "aboveGroundCropResidueIncorporated"
1133
+ "@id": "aboveGroundCropResidueLeftOnField"
1134
1134
  }
1135
1135
  ]
1136
1136
  },
@@ -1486,7 +1486,7 @@
1486
1486
  "@type": "Term",
1487
1487
  "name": "Generic crop, seed",
1488
1488
  "@id": "genericCropSeed",
1489
- "_score": 25.968466
1489
+ "_score": 26.344206
1490
1490
  }
1491
1491
  ]
1492
1492
  },
@@ -1534,10 +1534,6 @@
1534
1534
  "@type": "Term",
1535
1535
  "@id": "rainfedDeepWaterWaterDepth100Cm"
1536
1536
  },
1537
- {
1538
- "@type": "Term",
1539
- "@id": "irrigatedTypeUnspecified"
1540
- },
1541
1537
  {
1542
1538
  "@type": "Term",
1543
1539
  "@id": "irrigatedLocalizedIrrigation"
@@ -1550,6 +1546,10 @@
1550
1546
  "@type": "Term",
1551
1547
  "@id": "irrigatedSubIrrigation"
1552
1548
  },
1549
+ {
1550
+ "@type": "Term",
1551
+ "@id": "irrigatedTypeUnspecified"
1552
+ },
1553
1553
  {
1554
1554
  "@type": "Term",
1555
1555
  "@id": "irrigatedDripIrrigation"
@@ -1722,61 +1722,61 @@
1722
1722
  "@type": "Term",
1723
1723
  "name": "Glass or high accessible cover",
1724
1724
  "@id": "glassOrHighAccessibleCover",
1725
- "_score": 60.694187
1725
+ "_score": 59.78251
1726
1726
  },
1727
1727
  {
1728
1728
  "@type": "Term",
1729
1729
  "name": "River or stream",
1730
1730
  "@id": "riverOrStream",
1731
- "_score": 50.06671
1731
+ "_score": 51.118263
1732
1732
  },
1733
1733
  {
1734
1734
  "@type": "Term",
1735
1735
  "name": "Other natural vegetation",
1736
1736
  "@id": "otherNaturalVegetation",
1737
- "_score": 40.722
1737
+ "_score": 41.25843
1738
1738
  },
1739
1739
  {
1740
1740
  "@type": "Term",
1741
1741
  "name": "Natural forest",
1742
1742
  "@id": "naturalForest",
1743
- "_score": 31.252472
1743
+ "_score": 31.747753
1744
1744
  },
1745
1745
  {
1746
1746
  "@type": "Term",
1747
1747
  "name": "Permanent pasture",
1748
1748
  "@id": "permanentPasture",
1749
- "_score": 27.857792
1749
+ "_score": 28.454437
1750
1750
  },
1751
1751
  {
1752
1752
  "@type": "Term",
1753
1753
  "name": "Animal housing",
1754
1754
  "@id": "animalHousing",
1755
- "_score": 26.769783
1755
+ "_score": 27.424242
1756
1756
  },
1757
1757
  {
1758
1758
  "@type": "Term",
1759
1759
  "name": "Root or tuber crop plant",
1760
1760
  "@id": "rootOrTuberCropPlant",
1761
- "_score": 24.781918
1761
+ "_score": 25.260658
1762
1762
  },
1763
1763
  {
1764
1764
  "@type": "Term",
1765
1765
  "name": "High intensity grazing pasture",
1766
1766
  "@id": "highIntensityGrazingPasture",
1767
- "_score": 23.502655
1767
+ "_score": 24.038225
1768
1768
  },
1769
1769
  {
1770
1770
  "@type": "Term",
1771
1771
  "name": "Permanent cropland",
1772
1772
  "@id": "permanentCropland",
1773
- "_score": 20.467493
1773
+ "_score": 20.689457
1774
1774
  },
1775
1775
  {
1776
1776
  "@type": "Term",
1777
1777
  "name": "Forest",
1778
1778
  "@id": "forest",
1779
- "_score": 19.942879
1779
+ "_score": 20.366226
1780
1780
  }
1781
1781
  ]
1782
1782
  },
@@ -2024,15 +2024,15 @@
2024
2024
  "results": [
2025
2025
  {
2026
2026
  "@type": "Term",
2027
- "@id": "verticalTillage"
2027
+ "@id": "noTillage"
2028
2028
  },
2029
2029
  {
2030
2030
  "@type": "Term",
2031
- "@id": "noTillage"
2031
+ "@id": "ridgeTillage"
2032
2032
  },
2033
2033
  {
2034
2034
  "@type": "Term",
2035
- "@id": "ridgeTillage"
2035
+ "@id": "verticalTillage"
2036
2036
  },
2037
2037
  {
2038
2038
  "@type": "Term",
@@ -7,8 +7,7 @@ from . import MODEL
7
7
 
8
8
  REQUIREMENTS = {
9
9
  "Cycle": {
10
- "products": [{"@type": "Product", "value": "", "term.termType": "crop"}],
11
- "site": {"@type": "Site", "siteType": "cropland"}
10
+ "products": [{"@type": "Product", "value": "", "term.termType": "crop"}]
12
11
  }
13
12
  }
14
13
  LOOKUPS = {
@@ -7,8 +7,7 @@ from . import MODEL
7
7
 
8
8
  REQUIREMENTS = {
9
9
  "Cycle": {
10
- "products": [{"@type": "Product", "value": "", "term.termType": "crop"}],
11
- "site": {"@type": "Site", "siteType": "cropland"}
10
+ "products": [{"@type": "Product", "value": "", "term.termType": "crop"}]
12
11
  }
13
12
  }
14
13
  LOOKUPS = {
@@ -7,8 +7,7 @@ from . import MODEL
7
7
 
8
8
  REQUIREMENTS = {
9
9
  "Cycle": {
10
- "products": [{"@type": "Product", "value": "", "term.termType": "crop"}],
11
- "site": {"@type": "Site", "siteType": "cropland"}
10
+ "products": [{"@type": "Product", "value": "", "term.termType": "crop"}]
12
11
  }
13
12
  }
14
13
  LOOKUPS = {
@@ -7,8 +7,7 @@ from . import MODEL
7
7
 
8
8
  REQUIREMENTS = {
9
9
  "Cycle": {
10
- "products": [{"@type": "Product", "value": "", "term.termType": "crop"}],
11
- "site": {"@type": "Site", "siteType": "cropland"}
10
+ "products": [{"@type": "Product", "value": "", "term.termType": "crop"}]
12
11
  }
13
12
  }
14
13
  LOOKUPS = {
@@ -7,8 +7,7 @@ from . import MODEL
7
7
 
8
8
  REQUIREMENTS = {
9
9
  "Cycle": {
10
- "products": [{"@type": "Product", "value": "", "term.termType": "crop"}],
11
- "site": {"@type": "Site", "siteType": "cropland"}
10
+ "products": [{"@type": "Product", "value": "", "term.termType": "crop"}]
12
11
  }
13
12
  }
14
13
  LOOKUPS = {
@@ -9,8 +9,7 @@ from . import MODEL
9
9
 
10
10
  REQUIREMENTS = {
11
11
  "Cycle": {
12
- "products": [{"@type": "Product", "value": "", "term.termType": "crop"}],
13
- "site": {"@type": "Site", "siteType": "cropland"}
12
+ "products": [{"@type": "Product", "value": "", "term.termType": "crop"}]
14
13
  }
15
14
  }
16
15
  LOOKUPS = {
@@ -2,13 +2,14 @@
2
2
  Preload all search requests to avoid making the same searches many times while running models.
3
3
  """
4
4
  import json
5
+ import os
5
6
 
6
7
  from .log import logger
7
8
  from .mocking.mock_search import create_search_results
8
9
  from .mocking import RESULTS_PATH, enable_mock as _mock
9
10
 
10
11
 
11
- def enable_preload(filepath: str = RESULTS_PATH, node: dict = None):
12
+ def enable_preload(filepath: str = RESULTS_PATH, node: dict = None, overwrite_existing: bool = True):
12
13
  """
13
14
  Prefetch calls to HESTIA API in a local file.
14
15
 
@@ -18,15 +19,21 @@ def enable_preload(filepath: str = RESULTS_PATH, node: dict = None):
18
19
  The path of the file containing the search results. Defaults to current library folder.
19
20
  node : dict
20
21
  Optional - The node used to run calculations. This is especially useful when running calculations on a Site.
22
+ overwrite_existing : bool
23
+ Optional - If the file already exists, the file can be used instead of generating it again.
24
+ Will overwrite by default.
21
25
  """
22
- logger.debug('Preloading search results and storing in %s', filepath)
26
+ should_generate = overwrite_existing or not os.path.exists(filepath)
23
27
 
24
- # build the search results
25
- data = create_search_results()
28
+ if should_generate:
29
+ logger.debug('Preloading search results and storing in %s', filepath)
26
30
 
27
- # store in file
28
- with open(filepath, 'w') as f:
29
- f.write(json.dumps(data, indent=2, ensure_ascii=False))
31
+ # build the search results
32
+ data = create_search_results()
33
+
34
+ # store in file
35
+ with open(filepath, 'w') as f:
36
+ f.write(json.dumps(data, indent=2, ensure_ascii=False))
30
37
 
31
38
  # enable mock search results from file
32
39
  _mock(filepath=filepath, node=node)
@@ -18,7 +18,7 @@ from functools import reduce
18
18
  from hestia_earth.schema import SchemaType, TermTermType, SiteSiteType
19
19
  from hestia_earth.utils.api import download_hestia
20
20
  from hestia_earth.utils.model import filter_list_term_type, linked_node
21
- from hestia_earth.utils.tools import safe_parse_float, flatten
21
+ from hestia_earth.utils.tools import safe_parse_float, flatten, non_empty_list
22
22
  from hestia_earth.utils.blank_node import get_node_value
23
23
 
24
24
  from hestia_earth.models.log import logRequirements, logShouldRun, log_blank_nodes_id
@@ -48,7 +48,8 @@ REQUIREMENTS = {
48
48
  "waterRegime",
49
49
  "tillage",
50
50
  "cropResidueManagement",
51
- "landUseManagement"
51
+ "landUseManagement",
52
+ "system"
52
53
  ],
53
54
  "units": ["% area", "boolean"],
54
55
  "value": ""
@@ -72,7 +73,7 @@ RETURNS = {
72
73
  "Management": [{
73
74
  "@type": "Management",
74
75
  "term.termType": [
75
- "landCover", "waterRegime", "tillage", "cropResidueManagement", "landUseManagement"
76
+ "landCover", "waterRegime", "tillage", "cropResidueManagement", "landUseManagement", "system"
76
77
  ],
77
78
  "value": "",
78
79
  "endDate": "",
@@ -247,7 +248,7 @@ def _should_run_all_products(cycles: list, site_type: str):
247
248
  for product in list(filter(_get_landCover_term_id, [i for i in products_crop_forage]))
248
249
  ] if site_type else []
249
250
  dates = sorted(list(set(
250
- flatten([[cycle.get('startDate'), cycle.get('endDate')] for cycle in cycles])
251
+ non_empty_list(flatten([[cycle.get('startDate'), cycle.get('endDate')] for cycle in cycles]))
251
252
  ))) if site_type not in _SKIP_LAND_COVER_SITE_TYPES else []
252
253
  site_type_term = download_hestia(get_landCover_term_id_from_site_type(site_type)) if all([
253
254
  len(dates) >= 2,
@@ -286,7 +287,8 @@ def _should_run(site: dict):
286
287
  TermTermType.WATERREGIME,
287
288
  TermTermType.TILLAGE,
288
289
  TermTermType.CROPRESIDUEMANAGEMENT,
289
- TermTermType.LANDUSEMANAGEMENT
290
+ TermTermType.LANDUSEMANAGEMENT,
291
+ TermTermType.SYSTEM
290
292
  ]
291
293
  )
292
294
  ]
@@ -122,15 +122,6 @@ def get_kg_term_units(term_id: str, units: str):
122
122
  }.get(units, lambda x: None)(term_id)
123
123
 
124
124
 
125
- def _get_by_key(x, y):
126
- return x if x is None else (
127
- x.get(y) if isinstance(x, dict) else list(map(lambda v: get_dict_key(v, y), x))
128
- )
129
-
130
-
131
- def get_dict_key(value: dict, key: str): return reduce(lambda x, y: _get_by_key(x, y), key.split('.'), value)
132
-
133
-
134
125
  def first_day_of_month(year: int, month: int):
135
126
  return datetime.date(int(year), int(month), 1)
136
127