hestia-earth-models 0.67.1__py3-none-any.whl → 0.68.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.
Files changed (147) hide show
  1. hestia_earth/models/aware/scarcityWeightedWaterUse.py +5 -6
  2. hestia_earth/models/blonkConsultants2016/ch4ToAirNaturalVegetationBurning.py +1 -1
  3. hestia_earth/models/blonkConsultants2016/co2ToAirAboveGroundBiomassStockChangeLandUseChange.py +1 -1
  4. hestia_earth/models/blonkConsultants2016/n2OToAirNaturalVegetationBurningDirect.py +1 -1
  5. hestia_earth/models/blonkConsultants2016/utils.py +9 -9
  6. hestia_earth/models/cache_sites.py +26 -14
  7. hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandOccupation.py +2 -2
  8. hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandTransformation.py +2 -2
  9. hestia_earth/models/chaudharyBrooks2018/utils.py +13 -8
  10. hestia_earth/models/cml2001Baseline/abioticResourceDepletionFossilFuels.py +2 -3
  11. hestia_earth/models/cml2001Baseline/abioticResourceDepletionMineralsAndMetals.py +1 -1
  12. hestia_earth/models/config/Cycle.json +15 -0
  13. hestia_earth/models/config/ImpactAssessment.json +14 -1
  14. hestia_earth/models/config/Site.json +8 -0
  15. hestia_earth/models/cycle/excretaKgMass.py +2 -2
  16. hestia_earth/models/cycle/materialAndSubstrate.py +3 -2
  17. hestia_earth/models/cycle/pastureGrass.py +3 -3
  18. hestia_earth/models/dammgen2009/noxToAirExcreta.py +1 -1
  19. hestia_earth/models/ecoinventV3AndEmberClimate/__init__.py +1 -1
  20. hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +2 -6
  21. hestia_earth/models/emissionNotRelevant/__init__.py +4 -4
  22. hestia_earth/models/environmentalFootprintV3_1/environmentalFootprintSingleOverallScore.py +30 -21
  23. hestia_earth/models/environmentalFootprintV3_1/photochemicalOzoneCreationPotentialHumanHealthNmvocEq.py +36 -0
  24. hestia_earth/models/environmentalFootprintV3_1/scarcityWeightedWaterUse.py +2 -2
  25. hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandOccupation.py +9 -8
  26. hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandTransformation.py +25 -22
  27. hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexTotalLandUseEffects.py +7 -6
  28. hestia_earth/models/faostat2018/coldCarcassWeightPerHead.py +2 -2
  29. hestia_earth/models/faostat2018/coldDressedCarcassWeightPerHead.py +2 -2
  30. hestia_earth/models/faostat2018/liveweightPerHead.py +7 -8
  31. hestia_earth/models/faostat2018/product/price.py +34 -28
  32. hestia_earth/models/faostat2018/readyToCookWeightPerHead.py +2 -2
  33. hestia_earth/models/faostat2018/utils.py +15 -27
  34. hestia_earth/models/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +16 -9
  35. hestia_earth/models/geospatialDatabase/altitude.py +60 -0
  36. hestia_earth/models/geospatialDatabase/croppingIntensity.py +1 -1
  37. hestia_earth/models/geospatialDatabase/ecoClimateZone.py +2 -2
  38. hestia_earth/models/geospatialDatabase/longFallowRatio.py +1 -1
  39. hestia_earth/models/geospatialDatabase/utils.py +4 -1
  40. hestia_earth/models/globalCropWaterModel2008/rootingDepth.py +2 -3
  41. hestia_earth/models/haversineFormula/transport/distance.py +3 -3
  42. hestia_earth/models/hestia/landCover.py +72 -45
  43. hestia_earth/models/hestia/seed_emissions.py +11 -7
  44. hestia_earth/models/impact_assessment/__init__.py +3 -3
  45. hestia_earth/models/ipcc2019/animal/fatContent.py +1 -1
  46. hestia_earth/models/ipcc2019/animal/hoursWorkedPerDay.py +1 -1
  47. hestia_earth/models/ipcc2019/animal/liveweightGain.py +1 -1
  48. hestia_earth/models/ipcc2019/animal/liveweightPerHead.py +1 -1
  49. hestia_earth/models/ipcc2019/animal/milkYieldPerAnimal.py +1 -1
  50. hestia_earth/models/ipcc2019/animal/pastureGrass.py +1 -1
  51. hestia_earth/models/ipcc2019/animal/pregnancyRateTotal.py +1 -1
  52. hestia_earth/models/ipcc2019/animal/trueProteinContent.py +1 -1
  53. hestia_earth/models/ipcc2019/animal/utils.py +5 -7
  54. hestia_earth/models/ipcc2019/animal/weightAtMaturity.py +1 -1
  55. hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +2 -2
  56. hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +6 -7
  57. hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +5 -3
  58. hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +1 -1
  59. hestia_earth/models/ipcc2019/croppingDuration.py +3 -6
  60. hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +947 -0
  61. hestia_earth/models/ipcc2019/pastureGrass.py +1 -1
  62. hestia_earth/models/koble2014/residueBurnt.py +5 -7
  63. hestia_earth/models/koble2014/residueRemoved.py +5 -7
  64. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthWaterStress.py +2 -2
  65. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
  66. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthWaterStress.py +2 -2
  67. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
  68. hestia_earth/models/log.py +1 -1
  69. hestia_earth/models/mocking/search-results.json +3413 -1113
  70. hestia_earth/models/site/management.py +1 -1
  71. hestia_earth/models/site/post_checks/__init__.py +3 -2
  72. hestia_earth/models/site/post_checks/country.py +9 -0
  73. hestia_earth/models/site/pre_checks/__init__.py +3 -2
  74. hestia_earth/models/site/pre_checks/country.py +9 -0
  75. hestia_earth/models/utils/__init__.py +1 -16
  76. hestia_earth/models/utils/blank_node.py +25 -25
  77. hestia_earth/models/utils/completeness.py +3 -2
  78. hestia_earth/models/utils/cycle.py +5 -4
  79. hestia_earth/models/utils/emission.py +5 -5
  80. hestia_earth/models/utils/feedipedia.py +6 -6
  81. hestia_earth/models/utils/impact_assessment.py +1 -2
  82. hestia_earth/models/utils/indicator.py +9 -7
  83. hestia_earth/models/utils/inorganicFertiliser.py +4 -6
  84. hestia_earth/models/utils/input.py +6 -5
  85. hestia_earth/models/utils/lookup.py +32 -100
  86. hestia_earth/models/utils/management.py +4 -4
  87. hestia_earth/models/utils/measurement.py +6 -7
  88. hestia_earth/models/utils/method.py +20 -0
  89. hestia_earth/models/utils/practice.py +4 -5
  90. hestia_earth/models/utils/product.py +4 -5
  91. hestia_earth/models/utils/property.py +12 -22
  92. hestia_earth/models/utils/site.py +14 -8
  93. hestia_earth/models/utils/term.py +27 -1
  94. hestia_earth/models/version.py +1 -1
  95. hestia_earth/orchestrator/log.py +0 -11
  96. hestia_earth/orchestrator/models/__init__.py +17 -4
  97. hestia_earth/orchestrator/strategies/run/add_blank_node_if_missing.py +2 -20
  98. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.0.dist-info}/METADATA +2 -2
  99. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.0.dist-info}/RECORD +145 -137
  100. tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +3 -3
  101. tests/models/cml2001Baseline/test_resourceUseEnergyDepletionDuringCycle.py +1 -1
  102. tests/models/cycle/test_coldCarcassWeightPerHead.py +1 -1
  103. tests/models/cycle/test_coldDressedCarcassWeightPerHead.py +1 -1
  104. tests/models/cycle/test_concentrateFeed.py +1 -1
  105. tests/models/cycle/test_energyContentLowerHeatingValue.py +1 -1
  106. tests/models/cycle/test_excretaKgMass.py +1 -1
  107. tests/models/cycle/test_feedConversionRatio.py +3 -3
  108. tests/models/cycle/test_pastureGrass.py +1 -1
  109. tests/models/cycle/test_readyToCookWeightPerHead.py +1 -1
  110. tests/models/environmentalFootprintV3_1/test_photochemicalOzoneCreationPotentialHumanHealthNmvocEq.py +30 -0
  111. tests/models/environmentalFootprintV3_1/test_soilQualityIndexTotalLandUseEffects.py +30 -7
  112. tests/models/faostat2018/product/test_price.py +27 -14
  113. tests/models/faostat2018/test_faostat_utils.py +4 -24
  114. tests/models/faostat2018/test_liveweightPerHead.py +9 -9
  115. tests/models/globalCropWaterModel2008/test_rootingDepth.py +7 -3
  116. tests/models/haversineFormula/transport/test_distance.py +1 -1
  117. tests/models/hestia/test_landCover.py +53 -5
  118. tests/models/ipcc2019/animal/test_pastureGrass.py +5 -3
  119. tests/models/ipcc2019/test_aboveGroundCropResidueTotal.py +4 -4
  120. tests/models/ipcc2019/test_belowGroundCropResidue.py +4 -4
  121. tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +10 -10
  122. tests/models/ipcc2019/test_croppingDuration.py +1 -1
  123. tests/models/ipcc2019/test_nonCo2EmissionsToAirNaturalVegetationBurning.py +83 -0
  124. tests/models/ipcc2019/test_organicCarbonPerHa.py +12 -12
  125. tests/models/ipcc2019/test_pastureGrass.py +5 -3
  126. tests/models/pooreNemecek2018/test_excretaKgN.py +5 -5
  127. tests/models/pooreNemecek2018/test_excretaKgVs.py +2 -2
  128. tests/models/site/post_checks/test_country.py +6 -0
  129. tests/models/site/pre_checks/test_cache_geospatialDatabase.py +1 -1
  130. tests/models/site/pre_checks/test_country.py +12 -0
  131. tests/models/test_ecoinventV3.py +7 -3
  132. tests/models/utils/test_blank_node.py +4 -12
  133. tests/models/utils/test_dataCompleteness.py +5 -5
  134. tests/models/utils/test_emission.py +2 -2
  135. tests/models/utils/test_indicator.py +2 -2
  136. tests/models/utils/test_input.py +2 -2
  137. tests/models/utils/test_measurement.py +2 -4
  138. tests/models/utils/test_practice.py +4 -2
  139. tests/models/utils/test_product.py +2 -2
  140. tests/models/utils/test_property.py +4 -2
  141. tests/models/utils/test_site.py +7 -0
  142. tests/orchestrator/strategies/run/test_add_blank_node_if_missing.py +4 -9
  143. hestia_earth/models/environmentalFootprintV3_1/utils.py +0 -17
  144. tests/models/utils/test_lookup.py +0 -10
  145. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.0.dist-info}/LICENSE +0 -0
  146. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.0.dist-info}/WHEEL +0 -0
  147. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.0.dist-info}/top_level.txt +0 -0
@@ -185,7 +185,7 @@ def _gap_filled_start_date(land_cover_id: str, end_date: str, cycle: dict) -> di
185
185
  cycle_duration = _get_cycle_duration(cycle, land_cover_id)
186
186
  return {
187
187
  "startDate": max(
188
- _gap_filled_date_obj(end_date) - timedelta(days=cycle_duration)
188
+ _gap_filled_date_obj(end_date) - timedelta(days=cycle_duration - 1)
189
189
  if cycle_duration else datetime.fromtimestamp(0),
190
190
  _gap_filled_date_obj(cycle.get("startDate"), mode=DatestrGapfillMode.START)
191
191
  if cycle.get("startDate") else datetime.fromtimestamp(0)
@@ -2,13 +2,14 @@ from os.path import dirname, abspath
2
2
  import sys
3
3
 
4
4
  from hestia_earth.models.utils import _run_in_serie
5
- from . import cache
5
+ from . import cache, country
6
6
 
7
7
  CURRENT_DIR = dirname(abspath(__file__)) + '/'
8
8
  sys.path.append(CURRENT_DIR)
9
9
 
10
10
  MODELS = [
11
- cache.run
11
+ cache.run,
12
+ country.run
12
13
  ]
13
14
 
14
15
 
@@ -0,0 +1,9 @@
1
+ """
2
+ Post Checks Country
3
+
4
+ Stores a simpler version of the country as originally set on the Site.
5
+ """
6
+ from hestia_earth.utils.model import linked_node
7
+
8
+
9
+ def run(site: dict): return site | {'country': linked_node(site.get('country'))}
@@ -2,7 +2,7 @@ from os.path import dirname, abspath
2
2
  import sys
3
3
 
4
4
  from hestia_earth.models.utils import _run_in_serie
5
- from . import cache_years, cache_geospatialDatabase, cache_sources
5
+ from . import cache_years, cache_geospatialDatabase, cache_sources, country
6
6
 
7
7
  CURRENT_DIR = dirname(abspath(__file__)) + '/'
8
8
  sys.path.append(CURRENT_DIR)
@@ -10,7 +10,8 @@ sys.path.append(CURRENT_DIR)
10
10
  MODELS = [
11
11
  cache_years.run,
12
12
  cache_geospatialDatabase.run,
13
- cache_sources.run
13
+ cache_sources.run,
14
+ country.run
14
15
  ]
15
16
 
16
17
 
@@ -0,0 +1,9 @@
1
+ """
2
+ Pre Checks Country
3
+
4
+ Load the complete country data from HESTIA to be able to use `subClassOf` for example.
5
+ """
6
+ from hestia_earth.utils.api import download_hestia
7
+
8
+
9
+ def run(site: dict): return site | {'country': download_hestia(site.get('country', {}).get('@id'))}
@@ -8,10 +8,9 @@ import datetime
8
8
  from functools import reduce
9
9
  import operator
10
10
  from pydash.objects import get
11
- from typing import Any, Callable, Union
11
+ from typing import Any, Callable
12
12
  from hestia_earth.schema import SchemaType
13
13
  from hestia_earth.utils.api import download_hestia
14
- from hestia_earth.utils.model import linked_node
15
14
  from hestia_earth.utils.tools import flatten, non_empty_list
16
15
  from hestia_earth.utils.date import is_in_days, is_in_months
17
16
 
@@ -44,20 +43,6 @@ def _omit(values: dict, keys: list) -> dict: return {k: v for k, v in values.ite
44
43
  def _include(value: dict, keys: list) -> dict: return {k: v for k, v in value.items() if k in keys}
45
44
 
46
45
 
47
- def _include_model(node: dict, term_id: str):
48
- term = download_hestia(term_id) or {}
49
- return {**node, **({} if term.get('@id') is None else {'model': linked_node(term)})}
50
-
51
-
52
- def _include_method(node: dict, term_id: Union[None, str, dict], key='method'):
53
- term = (download_hestia(term_id) or {}) if isinstance(term_id, str) else term_id
54
- return node | ({} if term is None or term.get('@id') is None else {key: linked_node(term)})
55
-
56
-
57
- def _include_methodModel(node: dict, term_id: str):
58
- return _include_method(node, term_id=term_id, key='methodModel')
59
-
60
-
61
46
  def _run_in_serie(data: dict, models: list): return reduce(lambda prev, model: model(prev), models, data)
62
47
 
63
48
 
@@ -15,7 +15,6 @@ from typing import (
15
15
  from dateutil import parser
16
16
  from dateutil.relativedelta import relativedelta
17
17
  from hestia_earth.schema import TermTermType
18
- from hestia_earth.utils.api import download_hestia
19
18
  from hestia_earth.utils.blank_node import ArrayTreatment, get_node_value
20
19
  from hestia_earth.utils.model import filter_list_term_type
21
20
  from hestia_earth.utils.tools import (
@@ -26,18 +25,21 @@ from hestia_earth.utils.tools import (
26
25
  safe_parse_float,
27
26
  non_empty_list
28
27
  )
29
-
30
- from . import is_from_model, _filter_list_term_unit, is_iterable, full_date_str
31
- from .constant import Units, get_atomic_conversion
32
- from .lookup import (
28
+ from hestia_earth.utils.lookup_utils import (
33
29
  is_model_siteType_allowed,
34
30
  is_siteType_allowed,
35
- is_product_id_allowed, is_product_termType_allowed,
36
- is_input_id_allowed, is_input_termType_allowed, _node_value
31
+ is_product_id_allowed,
32
+ is_product_termType_allowed,
33
+ is_input_id_allowed,
34
+ is_input_termType_allowed
37
35
  )
36
+
37
+ from hestia_earth.models.log import debugValues, log_as_table
38
+ from . import is_from_model, _filter_list_term_unit, is_iterable, full_date_str
39
+ from .constant import Units, get_atomic_conversion
40
+ from .lookup import _node_value
38
41
  from .property import get_node_property, get_node_property_value
39
- from .term import get_lookup_value
40
- from ..log import debugValues, log_as_table
42
+ from .term import get_lookup_value, download_term
41
43
 
42
44
  # TODO: verify those values
43
45
  MAX_DEPTH = 1000
@@ -122,29 +124,29 @@ def _module_term_id(term_id: str, module):
122
124
  return getattr(module, 'TERM_ID', term_id_str).split(',')[0]
123
125
 
124
126
 
125
- def _run_model_required(model: str, term: dict, data: dict):
126
- siteType_allowed = is_model_siteType_allowed(model, term, data)
127
+ def _run_model_required(model: str, term_id: str, data: dict):
128
+ siteType_allowed = is_model_siteType_allowed(model, term_id, data)
127
129
 
128
130
  run_required = all([siteType_allowed])
129
- debugValues(data, model=model, term=term.get('@id'),
131
+ debugValues(data, model=model, term=term_id,
130
132
  run_required=run_required,
131
133
  siteType_allowed=siteType_allowed)
132
134
  return run_required
133
135
 
134
136
 
135
- def _run_required(model: str, term: dict, data: dict):
136
- siteType_allowed = is_siteType_allowed(data, term)
137
- product_id_allowed = is_product_id_allowed(data, term)
138
- product_termType_allowed = is_product_termType_allowed(data, term)
139
- input_id_allowed = is_input_id_allowed(data, term)
140
- input_termType_allowed = is_input_termType_allowed(data, term)
137
+ def _run_required(model: str, term_id: str, data: dict):
138
+ siteType_allowed = is_siteType_allowed(data, term_id)
139
+ product_id_allowed = is_product_id_allowed(data, term_id)
140
+ product_termType_allowed = is_product_termType_allowed(data, term_id)
141
+ input_id_allowed = is_input_id_allowed(data, term_id)
142
+ input_termType_allowed = is_input_termType_allowed(data, term_id)
141
143
 
142
144
  run_required = all([
143
145
  siteType_allowed, product_id_allowed, product_termType_allowed, input_id_allowed, input_termType_allowed
144
146
  ])
145
147
  # model is only used for logs here, skip logs if model not provided
146
148
  if model:
147
- debugValues(data, model=model, term=term.get('@id'),
149
+ debugValues(data, model=model, term=term_id,
148
150
  siteType_allowed=siteType_allowed,
149
151
  product_id_allowed=product_id_allowed,
150
152
  product_termType_allowed=product_termType_allowed,
@@ -152,7 +154,7 @@ def _run_required(model: str, term: dict, data: dict):
152
154
  input_termType_allowed=input_termType_allowed)
153
155
  # logging this for the model would cause issues parsing statuses
154
156
  if model != 'emissionNotRelevant':
155
- debugValues(data, model=model, term=term.get('@id'), run_required=run_required)
157
+ debugValues(data, model=model, term=term_id, run_required=run_required)
156
158
  return run_required
157
159
 
158
160
 
@@ -174,10 +176,9 @@ def is_run_required(model: str, term_id: str, node: dict):
174
176
  bool
175
177
  True if the model is required to run.
176
178
  """
177
- term = download_hestia(term_id)
178
179
  return (
179
- (_run_model_required(model, term, node) if model else True) and _run_required(model, term, node)
180
- ) if term else True
180
+ (_run_model_required(model, term_id, node) if model else True) and _run_required(model, term_id, node)
181
+ ) if term_id else True
181
182
 
182
183
 
183
184
  def run_if_required(model: str, term_id: str, data: dict, module):
@@ -1279,7 +1280,7 @@ def get_inputs_from_properties(input: dict, term_types: Union[TermTermType, List
1279
1280
  properties = (
1280
1281
  input.get('properties') or
1281
1282
  input.get('term', {}).get('defaultProperties') or
1282
- download_hestia(input.get('term', {}).get('@id')).get('defaultProperties')
1283
+ download_term(input.get('term', {})).get('defaultProperties')
1283
1284
  )
1284
1285
  inputs = non_empty_list([
1285
1286
  {
@@ -1559,7 +1560,6 @@ def convert_unit_properties(node_value: Union[int, float], node: dict, dest_unit
1559
1560
  Convert a number `node_value` belonging to a term `node`, to unit `to_units` by chaining multiple unit conversions
1560
1561
  together.
1561
1562
  Uses terms properties for the conversion.
1562
- Uses cached calls to download_hestia() internally for speedup
1563
1563
  Returns None if no conversion possible.
1564
1564
  """
1565
1565
  src_unit = node.get("units") or node.get('term', {}).get('units', "")
@@ -1,6 +1,7 @@
1
1
  from typing import Union
2
2
  from hestia_earth.schema import Completeness, TermTermType
3
- from hestia_earth.utils.api import download_hestia
3
+
4
+ from .term import download_term
4
5
 
5
6
  completeness_fields = Completeness().required
6
7
 
@@ -12,7 +13,7 @@ def _completeness_term_type(cycle: dict, term: Union[str, dict, TermTermType]):
12
13
 
13
14
 
14
15
  def _get_term_type_completeness(cycle: dict, term: Union[str, dict]):
15
- term = download_hestia(term) if isinstance(term, str) else term
16
+ term = download_term(term) if isinstance(term, str) else term
16
17
  term_type = term.get('termType') if term else None
17
18
  return cycle.get('completeness', {}).get(term_type, False)
18
19
 
@@ -1,9 +1,10 @@
1
1
  from hestia_earth.schema import CycleFunctionalUnit, SiteSiteType, TermTermType, AnimalReferencePeriod
2
2
  from hestia_earth.utils.model import filter_list_term_type, find_term_match, find_primary_product
3
3
  from hestia_earth.utils.tools import list_sum, safe_parse_float, safe_parse_date, non_empty_list
4
+ from hestia_earth.utils.lookup_utils import is_siteType_allowed
4
5
 
5
6
  from ..log import logRequirements, debugValues
6
- from .lookup import all_factor_value, is_siteType_allowed
7
+ from .lookup import all_factor_value
7
8
  from .term import get_lookup_value
8
9
  from .property import get_node_property
9
10
  from .completeness import _is_term_type_complete
@@ -344,7 +345,7 @@ def is_organic(cycle: dict):
344
345
  `True` if the `Cycle` is organic, `False` otherwise.
345
346
  """
346
347
  practices = filter_list_term_type(cycle.get('practices', []), TermTermType.STANDARDSLABELS)
347
- return any([get_lookup_value(p.get('term', {}), 'isOrganic') == 'organic' for p in practices])
348
+ return next((get_lookup_value(p.get('term', {}), 'isOrganic') == 'organic' for p in practices), False)
348
349
 
349
350
 
350
351
  def is_irrigated(cycle: dict, **log_ars):
@@ -463,9 +464,9 @@ def get_animals_by_period(cycle: dict, period: AnimalReferencePeriod = AnimalRef
463
464
  ]
464
465
 
465
466
 
466
- def get_allowed_sites(model: str, term_id: str, termType: TermTermType, cycle: dict):
467
+ def get_allowed_sites(model: str, term_id: str, cycle: dict):
467
468
  sites = non_empty_list([cycle.get('site', None)]) + cycle.get('otherSites', [])
468
- allowed_sites = [s for s in sites if is_siteType_allowed(s, {'@id': term_id, 'termType': termType.value})]
469
+ allowed_sites = [s for s in sites if is_siteType_allowed(s, term_id)]
469
470
  allowed_site_ids = non_empty_list([s.get('@id', s.get('id')) for s in allowed_sites])
470
471
  debugValues(cycle, model=model, term=term_id, site_ids=';'.join(allowed_site_ids))
471
472
  return allowed_sites
@@ -1,22 +1,22 @@
1
1
  from collections.abc import Iterable
2
2
  from typing import Optional, Union
3
3
  from hestia_earth.schema import EmissionMethodTier, SchemaType, TermTermType
4
- from hestia_earth.utils.api import download_hestia
5
4
  from hestia_earth.utils.model import linked_node
6
5
 
7
6
 
8
- from . import _term_id, _include_methodModel, flatten_args
7
+ from . import flatten_args
8
+ from .term import download_term
9
9
  from .blank_node import find_terms_value
10
+ from .method import include_methodModel
10
11
  from .constant import Units, get_atomic_conversion
11
12
 
12
-
13
13
  EMISSION_METHOD_TIERS = [e.value for e in EmissionMethodTier]
14
14
 
15
15
 
16
16
  def _new_emission(term, model=None):
17
17
  node = {'@type': SchemaType.EMISSION.value}
18
- node['term'] = linked_node(term if isinstance(term, dict) else download_hestia(_term_id(term)))
19
- return _include_methodModel(node, model)
18
+ node['term'] = linked_node(term if isinstance(term, dict) else download_term(term, TermTermType.EMISSION))
19
+ return include_methodModel(node, model)
20
20
 
21
21
 
22
22
  def get_nh3_no3_nox_to_n(cycle: dict, nh3_term_id: str, no3_term_id: str, nox_term_id: str, allow_none: bool = False):
@@ -1,5 +1,5 @@
1
1
  from hestia_earth.utils.model import find_term_match
2
- from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name
2
+ from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name, lookup_term_ids
3
3
  from hestia_earth.utils.tools import non_empty_list, safe_parse_float
4
4
 
5
5
  from hestia_earth.models.log import logShouldRun
@@ -11,9 +11,9 @@ DRY_MATTER_TERM_ID = 'dryMatter'
11
11
 
12
12
  def get_feedipedia_properties():
13
13
  lookup = download_lookup('property.csv')
14
- term_ids = list(lookup.termid)
15
14
  term_ids = [
16
- term_id for term_id in term_ids if get_table_value(lookup, 'termid', term_id, column_name('feedipediaName'))
15
+ term_id for term_id in lookup_term_ids(lookup)
16
+ if get_table_value(lookup, 'termid', term_id, column_name('feedipediaName'))
17
17
  ]
18
18
  return term_ids
19
19
 
@@ -25,7 +25,6 @@ def _should_rescale_by_dm(property_id: str):
25
25
 
26
26
 
27
27
  def _dm_property(term_id: str, property_values: dict, dm_property_values: dict, dry_matter_property: dict):
28
- blank_node = _new_property(term_id)
29
28
  blank_node_data = {}
30
29
  for property_key in property_values.keys():
31
30
  new_dm_value = safe_parse_float(dry_matter_property.get(property_key))
@@ -37,7 +36,7 @@ def _dm_property(term_id: str, property_values: dict, dm_property_values: dict,
37
36
  2
38
37
  ) if _should_rescale_by_dm(term_id) else old_property_value
39
38
  blank_node_data[property_key] = new_value
40
- return (blank_node | blank_node_data) if blank_node_data else None
39
+ return (_new_property(term_id) | blank_node_data) if blank_node_data else None
41
40
 
42
41
 
43
42
  def _map_properties(lookup, term_id: str, column_prefix: str):
@@ -74,7 +73,8 @@ def rescale_properties_from_dryMatter(model: str, node: dict, blank_nodes: list)
74
73
  new_properties = non_empty_list([
75
74
  exec_property(blank_node, p, dry_matter_property) for p in properties if all([
76
75
  not find_term_match(all_properties, p),
77
- p != DRY_MATTER_TERM_ID
76
+ p != DRY_MATTER_TERM_ID,
77
+ dry_matter_property
78
78
  ])
79
79
  ])
80
80
  for prop in new_properties:
@@ -1,6 +1,5 @@
1
1
  from typing import Optional
2
2
  from hestia_earth.schema import TermTermType
3
- from hestia_earth.utils.lookup import download_lookup
4
3
  from hestia_earth.utils.model import find_term_match, filter_list_term_type
5
4
  from hestia_earth.utils.tools import list_sum, safe_parse_date
6
5
 
@@ -161,7 +160,7 @@ def impact_country_value(
161
160
  nodes = filter_list_term_type(impact.get('emissionsResourceUse', []), term_type)
162
161
 
163
162
  country_id = get_country_id(impact)
164
- country_id = fallback_country(country_id, [download_lookup(lookup)]) if country_fallback else country_id
163
+ country_id = fallback_country(country_id, [lookup]) if country_fallback else country_id
165
164
 
166
165
  values = list(map(_term_factor_value(model, term_id, lookup, country_id, group_key), nodes))
167
166
  debugValues(impact, model=model, term=term_id,
@@ -1,15 +1,17 @@
1
- from hestia_earth.schema import SchemaType
2
- from hestia_earth.utils.api import download_hestia
1
+ from hestia_earth.schema import SchemaType, TermTermType
3
2
  from hestia_earth.utils.model import linked_node
4
3
 
5
- from . import _term_id, _include_methodModel
4
+ from .method import include_methodModel
5
+ from .term import download_term
6
6
 
7
7
 
8
8
  def _new_indicator(term, model=None, land_cover_id: str = None, previous_land_cover_id: str = None):
9
9
  node = {'@type': SchemaType.INDICATOR.value}
10
- node['term'] = linked_node(term if isinstance(term, dict) else download_hestia(_term_id(term)))
10
+ node['term'] = linked_node(term if isinstance(term, dict) else download_term(
11
+ term, TermTermType.CHARACTERISEDINDICATOR)
12
+ )
11
13
  if land_cover_id:
12
- node['landCover'] = linked_node(download_hestia(land_cover_id))
14
+ node['landCover'] = linked_node(download_term(land_cover_id, TermTermType.LANDCOVER))
13
15
  if previous_land_cover_id:
14
- node['previousLandCover'] = linked_node(download_hestia(previous_land_cover_id))
15
- return _include_methodModel(node, model)
16
+ node['previousLandCover'] = linked_node(download_term(previous_land_cover_id, TermTermType.LANDCOVER))
17
+ return include_methodModel(node, model)
@@ -1,18 +1,18 @@
1
1
  from hestia_earth.schema import TermTermType
2
- from hestia_earth.utils.lookup import column_name, download_lookup, get_table_value, extract_grouped_data
2
+ from hestia_earth.utils.lookup import download_lookup, extract_grouped_data, lookup_term_ids
3
3
  from hestia_earth.utils.tools import safe_parse_float
4
4
  from hestia_earth.utils.model import filter_list_term_type
5
5
 
6
- from ..log import debugMissingLookup
7
6
  from .term import get_lookup_value
8
7
  from .fertiliser import get_fertilisers_from_inputs
8
+ from .lookup import get_region_lookup_value
9
9
 
10
10
  BREAKDOWN_LOOKUP = 'region-inorganicFertiliser-fertGroupingNitrogen-breakdown.csv'
11
11
 
12
12
 
13
13
  def get_terms():
14
14
  lookup = download_lookup('inorganicFertiliser.csv', True)
15
- return list(lookup.termid)
15
+ return lookup_term_ids(lookup)
16
16
 
17
17
 
18
18
  def get_term_lookup(term_id: str, col_name: str):
@@ -35,9 +35,7 @@ def get_NH3_emission_factor(term_id: str, soilPh: float, temperature: float):
35
35
 
36
36
 
37
37
  def get_country_breakdown(model: str, term_id: str, country_id: str, col_name: str):
38
- lookup = download_lookup(BREAKDOWN_LOOKUP)
39
- value = get_table_value(lookup, 'termid', country_id, column_name(col_name))
40
- debugMissingLookup(BREAKDOWN_LOOKUP, 'termid', country_id, col_name, value, model=model, term=term_id)
38
+ value = get_region_lookup_value(BREAKDOWN_LOOKUP, country_id, col_name, model=model, term=term_id)
41
39
  return safe_parse_float(value, None)
42
40
 
43
41
 
@@ -1,19 +1,20 @@
1
1
  from hestia_earth.schema import SchemaType, TermTermType
2
- from hestia_earth.utils.api import download_hestia
3
2
  from hestia_earth.utils.model import find_term_match, linked_node, filter_list_term_type
4
3
  from hestia_earth.utils.tools import list_sum, non_empty_list, list_average, flatten
5
4
  from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name
6
5
 
7
- from ..log import logger
8
- from . import _term_id, _include_model, _filter_list_term_unit, _load_calculated_node
6
+ from hestia_earth.models.log import logger
7
+ from . import _filter_list_term_unit, _load_calculated_node
9
8
  from .constant import Units
10
9
  from .blank_node import get_total_value, get_total_value_converted, get_lookup_value
10
+ from .term import download_term
11
+ from .method import include_model
11
12
 
12
13
 
13
14
  def _new_input(term, model=None):
14
15
  node = {'@type': SchemaType.INPUT.value}
15
- node['term'] = linked_node(term if isinstance(term, dict) else download_hestia(_term_id(term)))
16
- return _include_model(node, model)
16
+ node['term'] = linked_node(term if isinstance(term, dict) else download_term(term))
17
+ return include_model(node, model)
17
18
 
18
19
 
19
20
  def load_impacts(inputs: list):
@@ -1,10 +1,13 @@
1
1
  from typing import Optional, List
2
- from numpy import recarray
3
- from hestia_earth.schema import SchemaType
4
2
  from hestia_earth.utils.lookup import (
5
- download_lookup, get_table_value, column_name, extract_grouped_data, _get_single_table_value
3
+ download_lookup,
4
+ get_table_value,
5
+ column_name,
6
+ extract_grouped_data,
7
+ _get_single_table_value,
8
+ lookup_term_ids
6
9
  )
7
- from hestia_earth.utils.tools import list_sum, safe_parse_float, non_empty_list
10
+ from hestia_earth.utils.tools import list_sum, safe_parse_float
8
11
 
9
12
  from ..log import debugValues, log_as_table, debugMissingLookup
10
13
 
@@ -15,13 +18,11 @@ def _node_value(node):
15
18
 
16
19
 
17
20
  def _factor_value(model: str, term_id: str, lookup_name: str, lookup_col: str, grouped_key: Optional[str] = None):
18
- lookup = download_lookup(lookup_name)
19
-
20
21
  def get_value(data: dict):
21
22
  node_term_id = data.get('term', {}).get('@id')
22
23
  grouped_data_key = grouped_key or data.get('methodModel', {}).get('@id')
23
24
  value = _node_value(data)
24
- coefficient = get_table_value(lookup, 'termid', node_term_id, column_name(lookup_col))
25
+ coefficient = get_region_lookup_value(lookup_name, node_term_id, lookup_col, model=model, term=term_id)
25
26
  # value is either a number or matching between a model and a value (restrict value to specific model only)
26
27
  coefficient = safe_parse_float(
27
28
  extract_grouped_data(coefficient, grouped_data_key), None
@@ -69,12 +70,10 @@ def all_factor_value(
69
70
 
70
71
 
71
72
  def _term_factor_value(model: str, term_id: str, lookup_name: str, lookup_term_id: str, group_key: str = None):
72
- lookup = download_lookup(lookup_name, False) # avoid saving in memory as there could be many different files used
73
-
74
73
  def get_value(data: dict):
75
74
  node_term_id = data.get('term', {}).get('@id')
76
75
  value = _node_value(data)
77
- coefficient = get_table_value(lookup, 'termid', lookup_term_id, column_name(node_term_id))
76
+ coefficient = get_region_lookup_value(lookup_name, lookup_term_id, node_term_id, model=model, term=term_id)
78
77
  coefficient = safe_parse_float(extract_grouped_data(coefficient, group_key) if group_key else coefficient)
79
78
  if value is not None and coefficient is not None:
80
79
  debugValues(data, model=model, term=term_id,
@@ -107,98 +106,31 @@ def _aware_factor_value(model: str, term_id: str, lookup_name: str, aware_id: st
107
106
  return get_value
108
107
 
109
108
 
110
- _ALLOW_ALL = 'all'
111
-
112
-
113
- def _is_site(site: dict):
114
- return site.get('@type', site.get('type')) == SchemaType.SITE.value if site else None
115
-
116
-
117
- def _get_sites(node: dict):
118
- site = node.get('site', node.get('cycle', {}).get('site'))
119
- other_sites = node.get('otherSites', node.get('cycle', {}).get('otherSites', []))
120
- return non_empty_list([site] + other_sites)
121
-
122
-
123
- def _get_site_types(node: dict):
124
- sites = [node] if _is_site(node) else _get_sites(node)
125
- return non_empty_list([site.get('siteType') for site in sites])
126
-
127
-
128
- def _model_lookup_values(model: str, term: dict, restriction: str):
129
- lookup = download_lookup(f"{term.get('termType')}-model-{restriction}.csv")
130
- values = get_table_value(lookup, 'termid', term.get('@id'), column_name(model))
131
- return (values or _ALLOW_ALL).split(';') if isinstance(values, str) else _ALLOW_ALL
132
-
133
-
134
- def is_model_siteType_allowed(model: str, term: dict, data: dict):
135
- site_types = _get_site_types(data)
136
- allowed_values = _model_lookup_values(model, term, 'siteTypesAllowed')
137
- return True if _ALLOW_ALL in allowed_values or not site_types else any([
138
- (site_type in allowed_values) for site_type in site_types
139
- ])
140
-
141
-
142
- def _lookup_values(term: dict, column: str):
143
- lookup = download_lookup(f"{term.get('termType')}.csv")
144
- values = get_table_value(lookup, 'termid', term.get('@id'), column_name(column))
145
- return (values or _ALLOW_ALL).split(';') if isinstance(values, str) else _ALLOW_ALL
146
-
147
-
148
- def is_siteType_allowed(data: dict, term: dict):
149
- site_types = _get_site_types(data)
150
- allowed_values = _lookup_values(term, 'siteTypesAllowed')
151
- return True if _ALLOW_ALL in allowed_values or not site_types else any([
152
- (site_type in allowed_values) for site_type in site_types
153
- ])
154
-
155
-
156
- def is_product_termType_allowed(data: dict, term: dict):
157
- products = data.get('products', [])
158
- values = non_empty_list([p.get('term', {}).get('termType') for p in products])
159
- allowed_values = _lookup_values(term, 'productTermTypesAllowed')
160
- return True if any([
161
- _ALLOW_ALL in allowed_values,
162
- len(values) == 0
163
- ]) else any([value in allowed_values for value in values])
164
-
165
-
166
- def is_product_id_allowed(data: dict, term: dict):
167
- products = data.get('products', [])
168
- values = non_empty_list([p.get('term', {}).get('@id') for p in products])
169
- allowed_values = _lookup_values(term, 'productTermIdsAllowed')
170
- return True if any([
171
- _ALLOW_ALL in allowed_values,
172
- len(values) == 0
173
- ]) else any([value in allowed_values for value in values])
174
-
175
-
176
- def is_input_termType_allowed(data: dict, term: dict):
177
- inputs = data.get('inputs', [])
178
- values = non_empty_list([p.get('term', {}).get('termType') for p in inputs])
179
- allowed_values = _lookup_values(term, 'inputTermTypesAllowed')
180
- return True if any([
181
- _ALLOW_ALL in allowed_values,
182
- len(values) == 0
183
- ]) else any([value in allowed_values for value in values])
184
-
185
-
186
- def is_input_id_allowed(data: dict, term: dict):
187
- inputs = data.get('inputs', [])
188
- values = non_empty_list([p.get('term', {}).get('@id') for p in inputs])
189
- allowed_values = _lookup_values(term, 'inputTermIdsAllowed')
190
- return True if any([
191
- _ALLOW_ALL in allowed_values,
192
- len(values) == 0
193
- ]) else any([value in allowed_values for value in values])
109
+ def _country_in_lookup(country_id: str):
110
+ def in_lookup(lookup_name: str):
111
+ return (
112
+ download_lookup(lookup_name.replace('region', country_id)) is not None or
113
+ country_id in lookup_term_ids(download_lookup(lookup_name))
114
+ )
115
+ return in_lookup
194
116
 
195
117
 
196
- def fallback_country(country_id: str, lookup_arrays: List[recarray]) -> str:
118
+ def fallback_country(country_id: str, lookups: List[str]) -> str:
197
119
  """
198
- Given a site dict with 'country_id' location term, and lookup table,
199
- checks if a location can be used in lookup file
200
- else fallback to the default "region-world"
120
+ Given a country `@id`, and lookup tables, checks if a location can be used in lookup file
121
+ else fallback to the default "region-world".
201
122
  """
202
- is_in_lookup = lambda v: all(v in array['termid'] for array in lookup_arrays) # noqa: E731
123
+ is_in_lookup = lambda v: all(map(_country_in_lookup(v), lookups)) # noqa: E731
203
124
  fallback_id = 'region-world'
204
- return country_id if is_in_lookup(country_id) else fallback_id if is_in_lookup(fallback_id) else None
125
+ return country_id if country_id and is_in_lookup(country_id) else fallback_id if is_in_lookup(fallback_id) else None
126
+
127
+
128
+ def get_region_lookup_value(lookup_name: str, term_id: str, column: str, **log_args):
129
+ # for performance, try to load the region specific lookup if exists
130
+ lookup = (
131
+ download_lookup(lookup_name.replace('region-', f"{term_id}-"))
132
+ if lookup_name and lookup_name.startswith('region-') else None
133
+ ) or download_lookup(lookup_name)
134
+ value = get_table_value(lookup, 'termid', term_id, column_name(column))
135
+ debugMissingLookup(lookup_name, 'termid', term_id, column, value, **log_args)
136
+ return value
@@ -1,11 +1,11 @@
1
1
  from hestia_earth.schema import SchemaType
2
2
  from hestia_earth.utils.model import linked_node
3
- from hestia_earth.utils.api import download_hestia
4
3
 
5
- from . import _term_id, _include_model
4
+ from .term import download_term
5
+ from .method import include_model
6
6
 
7
7
 
8
8
  def _new_management(term, model=None):
9
9
  node = {'@type': SchemaType.MANAGEMENT.value}
10
- node['term'] = linked_node(term if isinstance(term, dict) else download_hestia(_term_id(term)))
11
- return _include_model(node, model)
10
+ node['term'] = linked_node(term if isinstance(term, dict) else download_term(term))
11
+ return include_model(node, model)