hestia-earth-models 0.67.1__py3-none-any.whl → 0.68.1__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 (148) 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 +44 -23
  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 +3397 -1097
  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/site/soilMeasurement.py +2 -0
  76. hestia_earth/models/utils/__init__.py +1 -16
  77. hestia_earth/models/utils/blank_node.py +25 -25
  78. hestia_earth/models/utils/completeness.py +3 -2
  79. hestia_earth/models/utils/cycle.py +5 -4
  80. hestia_earth/models/utils/emission.py +5 -5
  81. hestia_earth/models/utils/feedipedia.py +6 -6
  82. hestia_earth/models/utils/impact_assessment.py +1 -2
  83. hestia_earth/models/utils/indicator.py +9 -7
  84. hestia_earth/models/utils/inorganicFertiliser.py +4 -6
  85. hestia_earth/models/utils/input.py +6 -5
  86. hestia_earth/models/utils/lookup.py +32 -100
  87. hestia_earth/models/utils/management.py +4 -4
  88. hestia_earth/models/utils/measurement.py +7 -8
  89. hestia_earth/models/utils/method.py +20 -0
  90. hestia_earth/models/utils/practice.py +4 -5
  91. hestia_earth/models/utils/product.py +4 -5
  92. hestia_earth/models/utils/property.py +12 -22
  93. hestia_earth/models/utils/site.py +14 -8
  94. hestia_earth/models/utils/term.py +27 -1
  95. hestia_earth/models/version.py +1 -1
  96. hestia_earth/orchestrator/log.py +0 -11
  97. hestia_earth/orchestrator/models/__init__.py +17 -4
  98. hestia_earth/orchestrator/strategies/run/add_blank_node_if_missing.py +2 -20
  99. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.1.dist-info}/METADATA +2 -2
  100. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.1.dist-info}/RECORD +146 -138
  101. tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +3 -3
  102. tests/models/cml2001Baseline/test_resourceUseEnergyDepletionDuringCycle.py +1 -1
  103. tests/models/cycle/test_coldCarcassWeightPerHead.py +1 -1
  104. tests/models/cycle/test_coldDressedCarcassWeightPerHead.py +1 -1
  105. tests/models/cycle/test_concentrateFeed.py +1 -1
  106. tests/models/cycle/test_energyContentLowerHeatingValue.py +1 -1
  107. tests/models/cycle/test_excretaKgMass.py +1 -1
  108. tests/models/cycle/test_feedConversionRatio.py +3 -3
  109. tests/models/cycle/test_pastureGrass.py +1 -1
  110. tests/models/cycle/test_readyToCookWeightPerHead.py +1 -1
  111. tests/models/environmentalFootprintV3_1/test_photochemicalOzoneCreationPotentialHumanHealthNmvocEq.py +30 -0
  112. tests/models/environmentalFootprintV3_1/test_soilQualityIndexTotalLandUseEffects.py +30 -7
  113. tests/models/faostat2018/product/test_price.py +27 -14
  114. tests/models/faostat2018/test_faostat_utils.py +4 -24
  115. tests/models/faostat2018/test_liveweightPerHead.py +9 -9
  116. tests/models/globalCropWaterModel2008/test_rootingDepth.py +7 -3
  117. tests/models/haversineFormula/transport/test_distance.py +1 -1
  118. tests/models/hestia/test_landCover.py +53 -5
  119. tests/models/ipcc2019/animal/test_pastureGrass.py +5 -3
  120. tests/models/ipcc2019/test_aboveGroundCropResidueTotal.py +4 -4
  121. tests/models/ipcc2019/test_belowGroundCropResidue.py +4 -4
  122. tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +10 -10
  123. tests/models/ipcc2019/test_croppingDuration.py +1 -1
  124. tests/models/ipcc2019/test_nonCo2EmissionsToAirNaturalVegetationBurning.py +83 -0
  125. tests/models/ipcc2019/test_organicCarbonPerHa.py +12 -12
  126. tests/models/ipcc2019/test_pastureGrass.py +5 -3
  127. tests/models/pooreNemecek2018/test_excretaKgN.py +5 -5
  128. tests/models/pooreNemecek2018/test_excretaKgVs.py +2 -2
  129. tests/models/site/post_checks/test_country.py +6 -0
  130. tests/models/site/pre_checks/test_cache_geospatialDatabase.py +1 -1
  131. tests/models/site/pre_checks/test_country.py +12 -0
  132. tests/models/test_ecoinventV3.py +7 -3
  133. tests/models/utils/test_blank_node.py +4 -12
  134. tests/models/utils/test_dataCompleteness.py +5 -5
  135. tests/models/utils/test_emission.py +2 -2
  136. tests/models/utils/test_indicator.py +2 -2
  137. tests/models/utils/test_input.py +2 -2
  138. tests/models/utils/test_measurement.py +2 -4
  139. tests/models/utils/test_practice.py +4 -2
  140. tests/models/utils/test_product.py +2 -2
  141. tests/models/utils/test_property.py +4 -2
  142. tests/models/utils/test_site.py +7 -0
  143. tests/orchestrator/strategies/run/test_add_blank_node_if_missing.py +4 -9
  144. hestia_earth/models/environmentalFootprintV3_1/utils.py +0 -17
  145. tests/models/utils/test_lookup.py +0 -10
  146. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.1.dist-info}/LICENSE +0 -0
  147. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.1.dist-info}/WHEEL +0 -0
  148. {hestia_earth_models-0.67.1.dist-info → hestia_earth_models-0.68.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,36 @@
1
+ from hestia_earth.models.log import logRequirements, logShouldRun
2
+ from hestia_earth.models.utils.impact_assessment import impact_emission_lookup_value
3
+ from hestia_earth.models.utils.indicator import _new_indicator
4
+ from . import MODEL
5
+
6
+ REQUIREMENTS = {
7
+ "ImpactAssessment": {
8
+ "emissionsResourceUse": [
9
+ {"@type": "Indicator", "value": "", "term.termType": "emission"}
10
+ ]
11
+ }
12
+ }
13
+
14
+ RETURNS = {
15
+ "Indicator": {
16
+ "value": ""
17
+ }
18
+ }
19
+
20
+ LOOKUPS = {
21
+ "emission": "nmvocEqPhotochemicalOzoneFormationEnvironmentalFootprintV3-1"
22
+ }
23
+ TERM_ID = 'photochemicalOzoneCreationPotentialHumanHealthNmvocEq'
24
+
25
+
26
+ def _indicator(value: float):
27
+ indicator = _new_indicator(TERM_ID, MODEL)
28
+ indicator["value"] = value
29
+ return indicator
30
+
31
+
32
+ def run(impact_assessment: dict):
33
+ value = impact_emission_lookup_value(MODEL, TERM_ID, impact_assessment, LOOKUPS["emission"])
34
+ logRequirements(impact_assessment, model=MODEL, term=TERM_ID, value=value)
35
+ logShouldRun(impact_assessment, MODEL, TERM_ID, value is not None)
36
+ return _indicator(value) if value is not None else None
@@ -1,7 +1,7 @@
1
1
  from hestia_earth.models.log import logRequirements, logShouldRun
2
+ from hestia_earth.models.utils.impact_assessment import impact_country_value
3
+ from hestia_earth.models.utils.indicator import _new_indicator
2
4
  from . import MODEL
3
- from ..utils.impact_assessment import impact_country_value
4
- from ..utils.indicator import _new_indicator
5
5
 
6
6
  REQUIREMENTS = {
7
7
  "ImpactAssessment": {
@@ -7,16 +7,14 @@ Factors version 2.5 (Horn and Meier, 2018).
7
7
  from typing import Tuple
8
8
 
9
9
  from hestia_earth.schema import TermTermType
10
- from hestia_earth.utils.lookup import download_lookup
11
10
  from hestia_earth.utils.model import filter_list_term_type
12
11
  from hestia_earth.utils.tools import list_sum
13
12
 
14
13
  from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
15
14
  from hestia_earth.models.utils.indicator import _new_indicator
16
15
  from hestia_earth.models.utils.landCover import get_pef_grouping
17
- from hestia_earth.models.utils.lookup import fallback_country, _node_value
16
+ from hestia_earth.models.utils.lookup import fallback_country, _node_value, get_region_lookup_value
18
17
  from . import MODEL
19
- from .utils import get_coefficient_factor
20
18
  from ..utils.impact_assessment import get_country_id
21
19
 
22
20
  REQUIREMENTS = {
@@ -75,16 +73,19 @@ def _should_run(impact_assessment: dict) -> Tuple[bool, list]:
75
73
  'area-by-year-is-valid': _node_value(land_occupation_indicator) is not None and _node_value(
76
74
  land_occupation_indicator) > 0,
77
75
  'area-unit-is-valid': land_occupation_indicator.get('term', {}).get("units") == "m2*year",
78
- 'used-country': fallback_country(get_country_id(impact_assessment), [download_lookup(LOOKUP)]),
76
+ 'used-country': fallback_country(get_country_id(impact_assessment), [LOOKUP]),
77
+ 'pef-grouping': get_pef_grouping(land_occupation_indicator.get('landCover', {}).get("@id"))
79
78
 
80
79
  } for land_occupation_indicator in land_occupation_indicators]
81
80
 
82
81
  found_indicators_with_coefficient = [
83
82
  indicator | {
84
- 'coefficient': get_coefficient_factor(
85
- LOOKUP, indicator['used-country'],
86
- get_pef_grouping(indicator['land-cover-id']),
87
- term_id=TERM_ID
83
+ 'coefficient': get_region_lookup_value(
84
+ model=MODEL,
85
+ term=TERM_ID,
86
+ lookup_name=LOOKUP,
87
+ term_id=indicator['used-country'],
88
+ column=indicator['pef-grouping']
88
89
  ),
89
90
  "using-fallback-country-region-world-CFs": indicator['used-country'] != indicator['country-id']
90
91
  } for indicator in found_land_occupation_indicators
@@ -7,17 +7,15 @@ Factors version 2.5 (Horn and Meier, 2018).
7
7
  from typing import List, Tuple
8
8
 
9
9
  from hestia_earth.schema import TermTermType
10
- from hestia_earth.utils.lookup import download_lookup
11
10
  from hestia_earth.utils.model import filter_list_term_type, find_term_match
12
11
  from hestia_earth.utils.tools import list_sum
13
12
 
14
13
  from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
14
+ from hestia_earth.models.utils.impact_assessment import get_country_id
15
+ from hestia_earth.models.utils.indicator import _new_indicator
16
+ from hestia_earth.models.utils.landCover import get_pef_grouping
17
+ from hestia_earth.models.utils.lookup import fallback_country, _node_value, get_region_lookup_value
15
18
  from . import MODEL
16
- from .utils import get_coefficient_factor
17
- from ..utils.impact_assessment import get_country_id
18
- from ..utils.indicator import _new_indicator
19
- from ..utils.landCover import get_pef_grouping
20
- from ..utils.lookup import fallback_country, _node_value
21
19
 
22
20
  REQUIREMENTS = {
23
21
  "ImpactAssessment": {
@@ -50,8 +48,8 @@ REQUIREMENTS = {
50
48
  # Note: CFs in `region-pefTermGrouping-landTransformation-from.csv` appear to be the opposite values as those in
51
49
  # `region-pefTermGrouping-landTransformation-to.csv` but can be different in some cases.
52
50
  LOOKUPS = {
53
- "region-pefTermGrouping-landTransformation-from": "using country and `pefTermGrouping` from `landCover`",
54
- "region-pefTermGrouping-landTransformation-to": "using country and `pefTermGrouping` from `landCover`",
51
+ "region-pefTermGrouping-landTransformation-from": "",
52
+ "region-pefTermGrouping-landTransformation-to": "",
55
53
  "landCover": "pefTermGrouping"
56
54
  }
57
55
 
@@ -104,30 +102,35 @@ def _should_run(impact_assessment: dict) -> Tuple[bool, list]:
104
102
  'land-cover-id-from': transformation_indicator.get('previousLandCover', {}).get("@id"),
105
103
  'land-cover-id-to': transformation_indicator.get('landCover', {}).get("@id"),
106
104
  'indicator-id': transformation_indicator.get('term', {}).get('@id', ''),
107
- 'good-land-cover-term': all([bool(transformation_indicator.get('landCover')),
108
- bool(transformation_indicator.get('previousLandCover'))]),
105
+ 'good-land-cover-term': all([
106
+ bool(transformation_indicator.get('landCover')),
107
+ bool(transformation_indicator.get('previousLandCover'))
108
+ ]),
109
109
  'country-id': get_country_id(impact_assessment),
110
- 'value-is-valid': (_node_value(transformation_indicator) is not None and
111
- _node_value(transformation_indicator) >= 0),
112
- 'lookup-country': fallback_country(get_country_id(impact_assessment),
113
- [download_lookup(from_lookup_file), download_lookup(to_lookup_file)]),
110
+ 'value-is-valid': (
111
+ _node_value(transformation_indicator) is not None and
112
+ _node_value(transformation_indicator) >= 0
113
+ ),
114
+ 'lookup-country': fallback_country(get_country_id(impact_assessment), [from_lookup_file, to_lookup_file]),
114
115
  } for transformation_indicator in resource_uses
115
116
  ]
116
117
 
117
118
  found_transformations_with_coefficient = [
118
119
  transformation | {
119
120
  'using-fallback-country-region-world-CFs': transformation['lookup-country'] != transformation['country-id'],
120
- 'factor-from': get_coefficient_factor(
121
+ 'factor-from': get_region_lookup_value(
122
+ model=MODEL,
123
+ term=TERM_ID,
121
124
  lookup_name=from_lookup_file,
122
- country_id=transformation['lookup-country'],
123
- term_id=TERM_ID,
124
- occupation_type=get_pef_grouping(transformation['land-cover-id-from'])) if
125
+ term_id=transformation['lookup-country'],
126
+ column=get_pef_grouping(transformation['land-cover-id-from'])) if
125
127
  transformation['land-cover-id-from'] else None,
126
- 'factor-to': get_coefficient_factor(
128
+ 'factor-to': get_region_lookup_value(
129
+ model=MODEL,
130
+ term=TERM_ID,
127
131
  lookup_name=to_lookup_file,
128
- country_id=transformation['lookup-country'],
129
- term_id=TERM_ID,
130
- occupation_type=get_pef_grouping(transformation['land-cover-id-to'])) if
132
+ term_id=transformation['lookup-country'],
133
+ column=get_pef_grouping(transformation['land-cover-id-to'])) if
131
134
  transformation['land-cover-id-to'] else None
132
135
  } for transformation in found_transformations
133
136
  ]
@@ -4,7 +4,8 @@ based on an updated [LANCA model (De Laurentiis et al. 2019)](
4
4
  http://publications.jrc.ec.europa.eu/repository/handle/JRC113865) and on the LANCA (Regionalised) Characterisation
5
5
  Factors version 2.5 (Horn and Meier, 2018).
6
6
  """
7
- from hestia_earth.utils.model import find_term_match
7
+ from hestia_earth.schema import TermTermType
8
+ from hestia_earth.utils.model import find_term_match, filter_list_term_type
8
9
  from hestia_earth.utils.tools import list_sum
9
10
 
10
11
  from hestia_earth.models.log import logRequirements, logShouldRun
@@ -13,7 +14,7 @@ from ..utils.indicator import _new_indicator
13
14
 
14
15
  REQUIREMENTS = {
15
16
  "ImpactAssessment": {
16
- "emissionsResourceUse": [
17
+ "impacts": [
17
18
  {"@type": "Indicator", "value": "", "term.@id": "soilQualityIndexLandOccupation"},
18
19
  {"@type": "Indicator", "value": "", "term.@id": "soilQualityIndexLandTransformation"}
19
20
  ]
@@ -32,19 +33,19 @@ TERM_ID = 'soilQualityIndexTotalLandUseEffects'
32
33
 
33
34
  def _indicator(value: float):
34
35
  indicator = _new_indicator(TERM_ID, MODEL)
35
- indicator['value'] = value
36
+ indicator["value"] = value
36
37
  return indicator
37
38
 
38
39
 
39
40
  def _run(indicators: list):
40
- values = [indicator['value'] for indicator in indicators]
41
+ values = [indicator["value"] for indicator in indicators]
41
42
  return _indicator(list_sum(values))
42
43
 
43
44
 
44
45
  def _should_run(impactassessment: dict) -> tuple[bool, list]:
45
46
  soil_quality_indicators = [
46
- i for i in impactassessment.get('emissionsResourceUse', []) if
47
- i.get('term', {}).get('@id', '') in ['soilQualityIndexLandOccupation', 'soilQualityIndexLandTransformation']
47
+ i for i in filter_list_term_type(impactassessment.get("impacts", []), TermTermType.CHARACTERISEDINDICATOR) if
48
+ i.get("term", {}).get("@id", "") in ["soilQualityIndexLandOccupation", "soilQualityIndexLandTransformation"]
48
49
  ]
49
50
  has_soil_quality_indicators = bool(soil_quality_indicators)
50
51
 
@@ -22,8 +22,8 @@ REQUIREMENTS = {
22
22
  }
23
23
  }
24
24
  LOOKUPS = {
25
- "region-animalProduct-animalProductGroupingFAO-productionQuantity": "production quantity",
26
- "region-animalProduct-animalProductGroupingFAO-head": "number of heads"
25
+ "region-animalProduct-animalProductGroupingFAO-productionQuantity": "",
26
+ "region-animalProduct-animalProductGroupingFAO-head": ""
27
27
  }
28
28
  RETURNS = {
29
29
  "Product": [{
@@ -25,8 +25,8 @@ REQUIREMENTS = {
25
25
  }
26
26
  }
27
27
  LOOKUPS = {
28
- "region-animalProduct-animalProductGroupingFAO-productionQuantity": "production quantity",
29
- "region-animalProduct-animalProductGroupingFAO-head": "number of heads"
28
+ "region-animalProduct-animalProductGroupingFAO-productionQuantity": "",
29
+ "region-animalProduct-animalProductGroupingFAO-head": ""
30
30
  }
31
31
  RETURNS = {
32
32
  "Product": [{
@@ -1,14 +1,15 @@
1
1
  from hestia_earth.schema import TermTermType
2
- from hestia_earth.utils.api import download_hestia
3
- from hestia_earth.utils.lookup import get_table_value, column_name, download_lookup, extract_grouped_data_closest_date
2
+ from hestia_earth.utils.lookup import extract_grouped_data_closest_date
4
3
  from hestia_earth.utils.model import filter_list_term_type
5
4
  from hestia_earth.utils.tools import non_empty_list, safe_parse_date, safe_parse_float
6
5
 
7
- from hestia_earth.models.log import logRequirements, logShouldRun, debugMissingLookup
6
+ from hestia_earth.models.log import logRequirements, logShouldRun
8
7
  from hestia_earth.models.utils.constant import Units
8
+ from hestia_earth.models.utils.term import download_term
9
9
  from hestia_earth.models.utils.property import _new_property, node_has_no_property
10
10
  from hestia_earth.models.utils.product import convert_product_to_unit
11
11
  from hestia_earth.models.utils.animalProduct import FAO_LOOKUP_COLUMN, get_animalProduct_lookup_value
12
+ from hestia_earth.models.utils.lookup import get_region_lookup_value
12
13
  from .utils import get_liveAnimal_to_animalProduct_id
13
14
  from . import MODEL
14
15
 
@@ -29,7 +30,7 @@ REQUIREMENTS = {
29
30
  LOOKUPS = {
30
31
  "liveAnimal": ["primaryMeatProductFaoProductionTermId"],
31
32
  "animalProduct": ["animalProductGroupingFAOEquivalent", "animalProductGroupingFAO"],
32
- "region-animalProduct-animalProductGroupingFAO-averageColdCarcassWeight": "use value from above"
33
+ "region-animalProduct-animalProductGroupingFAO-averageColdCarcassWeight": ""
33
34
  }
34
35
  RETURNS = {
35
36
  "Product": [{
@@ -53,9 +54,7 @@ def _product_value(product: dict, year: int, country_id: str):
53
54
  product_id = product.get('term', {}).get('@id')
54
55
  groupingFAO = get_animalProduct_lookup_value(MODEL, product_id, FAO_LOOKUP_COLUMN)
55
56
 
56
- lookup = download_lookup(LOOKUP_WEIGHT)
57
- data = get_table_value(lookup, 'termid', country_id, column_name(groupingFAO))
58
- debugMissingLookup(LOOKUP_WEIGHT, 'termid', country_id, groupingFAO, data, model=MODEL, term=TERM_ID)
57
+ data = get_region_lookup_value(LOOKUP_WEIGHT, country_id, groupingFAO, model=MODEL, term=TERM_ID)
59
58
  average_carcass_weight = safe_parse_float(extract_grouped_data_closest_date(data, year), None)
60
59
  # average_carcass_weight is in hg, divide by 10 to go back to kg
61
60
  kg_carcass_weight = average_carcass_weight / 10 if average_carcass_weight else None
@@ -77,7 +76,7 @@ def _run_liveAnimal(cycle: dict, product: dict, year: int, country_id: str):
77
76
  product_id = product.get('term', {}).get('@id')
78
77
  animal_product_id = get_liveAnimal_to_animalProduct_id(product_id, LOOKUPS['liveAnimal'][0], term=TERM_ID)
79
78
 
80
- animal_product_term = download_hestia(animal_product_id) if animal_product_id else {}
79
+ animal_product_term = download_term(animal_product_id, TermTermType.ANIMALPRODUCT) if animal_product_id else {}
81
80
  kg_liveweight, groupingFAO = _product_value({**product, 'term': animal_product_term}, year, country_id)
82
81
 
83
82
  logRequirements(cycle, model=MODEL, term=product_id, property=TERM_ID,
@@ -4,16 +4,17 @@ Product Price
4
4
  Calculates the price of `crop` and `liveAnimal` using FAOSTAT data.
5
5
  """
6
6
  from hestia_earth.schema import TermTermType
7
- from hestia_earth.utils.api import download_hestia
8
- from hestia_earth.utils.lookup import get_table_value, column_name, download_lookup, extract_grouped_data
7
+ from hestia_earth.utils.lookup import extract_grouped_data
9
8
  from hestia_earth.utils.tools import non_empty_list, safe_parse_float, safe_parse_date
10
9
 
11
- from hestia_earth.models.log import debugMissingLookup, debugValues, logRequirements, logShouldRun
10
+ from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
12
11
  from hestia_earth.models.utils.constant import Units
12
+ from hestia_earth.models.utils.term import download_term
13
13
  from hestia_earth.models.utils.currency import DEFAULT_CURRENCY
14
14
  from hestia_earth.models.utils.crop import FAOSTAT_PRODUCTION_LOOKUP_COLUMN, get_crop_grouping_faostat_production
15
15
  from hestia_earth.models.utils.animalProduct import FAO_LOOKUP_COLUMN, get_animalProduct_grouping_fao
16
16
  from hestia_earth.models.utils.product import convert_product_to_unit
17
+ from hestia_earth.models.utils.lookup import get_region_lookup_value
17
18
  from ..utils import get_liveAnimal_to_animalProduct_id
18
19
  from .. import MODEL
19
20
 
@@ -37,12 +38,12 @@ RETURNS = {
37
38
  LOOKUPS = {
38
39
  "@doc": "Depending on the primary product [termType](https://hestia.earth/schema/Product#term)",
39
40
  "crop": "cropGroupingFaostatProduction",
40
- "region-crop-cropGroupingFaostatProduction-price": "use value from above",
41
+ "region-crop-cropGroupingFaostatProduction-price": "",
41
42
  "liveAnimal": ["primaryMeatProductFaoPriceTermId"],
42
43
  "animalProduct": ["animalProductGroupingFAOEquivalent", "animalProductGroupingFAO"],
43
- "region-animalProduct-animalProductGroupingFAO-price": "use value from above",
44
- "region-animalProduct-animalProductGroupingFAO-averageColdCarcassWeight": "use value from above",
45
- "region-animalProduct-animalProductGroupingFAO-weightPerItem": "use value from above"
44
+ "region-animalProduct-animalProductGroupingFAO-price": "",
45
+ "region-animalProduct-animalProductGroupingFAO-averageColdCarcassWeight": "",
46
+ "region-animalProduct-animalProductGroupingFAO-weightPerItem": ""
46
47
  }
47
48
  MODEL_KEY = 'price'
48
49
  LOOKUP_NAME = {
@@ -62,14 +63,19 @@ def _term_grouping(term: dict): return LOOKUP_GROUPING.get(term.get('termType'),
62
63
 
63
64
 
64
65
  def _lookup_data(
65
- term_id: str, grouping: str, country_id: str, year: int, term_type: str = None, lookup_name: str = None
66
+ term_id: str, grouping: str, country: dict, year: int, term_type: str = None, lookup_name: str = None
66
67
  ):
67
- lookup_name = lookup_name or LOOKUP_NAME.get(term_type)
68
- lookup = download_lookup(lookup_name)
69
- data = get_table_value(lookup, 'termid', country_id, column_name(grouping))
70
- debugMissingLookup(lookup_name, 'termid', country_id, grouping, data, model=MODEL, term=term_id, key=MODEL_KEY)
71
- price = extract_grouped_data(data, str(year)) or extract_grouped_data(data, 'Average_price_per_tonne')
72
- return safe_parse_float(price, None)
68
+ lookup_name = lookup_name or LOOKUP_NAME.get(term_type, '')
69
+
70
+ def get_data(country_id):
71
+ data = get_region_lookup_value(lookup_name, country_id, grouping, model=MODEL, term=term_id, key=MODEL_KEY)
72
+ price = extract_grouped_data(data, str(year)) or extract_grouped_data(data, 'Average_price_per_tonne')
73
+ return safe_parse_float(price, None)
74
+
75
+ # try get country data first, falls back to region data
76
+ country_id = country.get('@id')
77
+ region_id = (country.get('subClassOf') or [{}])[0].get('@id')
78
+ return get_data(country_id) or (get_data(region_id) if region_id else None)
73
79
 
74
80
 
75
81
  def _product(product: dict, value: float):
@@ -77,7 +83,7 @@ def _product(product: dict, value: float):
77
83
  return product | {'currency': DEFAULT_CURRENCY, MODEL_KEY: round(value, 4)}
78
84
 
79
85
 
80
- def _get_liveAnimal_lookup_values(cycle: dict, product: dict, country_id: str, year: int = None):
86
+ def _get_liveAnimal_lookup_values(cycle: dict, product: dict, country: dict, year: int = None):
81
87
  term_id = product.get('term', {}).get('@id')
82
88
  animal_product = get_liveAnimal_to_animalProduct_id(term_id, LOOKUPS['liveAnimal'][0], key=MODEL_KEY)
83
89
  groupingFAO = _term_grouping({'termType': TermTermType.ANIMALPRODUCT.value, '@id': animal_product})
@@ -85,7 +91,7 @@ def _get_liveAnimal_lookup_values(cycle: dict, product: dict, country_id: str, y
85
91
  # one live animal can be linked to many animal product, hence go one by one until we have a match
86
92
  if groupingFAO:
87
93
  price_per_ton_liveweight = _lookup_data(
88
- term_id, groupingFAO, country_id, year, term_type=TermTermType.ANIMALPRODUCT.value
94
+ term_id, groupingFAO, country, year, term_type=TermTermType.ANIMALPRODUCT.value
89
95
  )
90
96
  debugValues(cycle, model=MODEL, term=term_id, key=MODEL_KEY, by='liveAnimal',
91
97
  animal_product=animal_product,
@@ -97,11 +103,11 @@ def _get_liveAnimal_lookup_values(cycle: dict, product: dict, country_id: str, y
97
103
  return (None, None)
98
104
 
99
105
 
100
- def _run_by_liveAnimal(cycle: dict, product: dict, country_id: str, year: int = None):
106
+ def _run_by_liveAnimal(cycle: dict, product: dict, country: dict, year: int = None):
101
107
  term_id = product.get('term', {}).get('@id')
102
- animal_product_id, price_per_kg_liveweight = _get_liveAnimal_lookup_values(cycle, product, country_id, year)
108
+ animal_product_id, price_per_kg_liveweight = _get_liveAnimal_lookup_values(cycle, product, country, year)
103
109
 
104
- animal_product = download_hestia(animal_product_id)
110
+ animal_product = download_term(animal_product_id, TermTermType.ANIMALPRODUCT)
105
111
  price_per_head = convert_product_to_unit({
106
112
  **product,
107
113
  'term': animal_product,
@@ -123,7 +129,7 @@ def _should_run_liveAnimal(product: dict):
123
129
  return product.get('term', {}).get('termType') == TermTermType.LIVEANIMAL.value
124
130
 
125
131
 
126
- def _run_by_country(cycle: dict, product: dict, country_id: str, year: int = None):
132
+ def _run_by_country(cycle: dict, product: dict, country: dict, year: int = None):
127
133
  product_term = product.get('term', {})
128
134
  term_id = product_term.get('@id')
129
135
  term_type = product_term.get('termType')
@@ -136,12 +142,12 @@ def _run_by_country(cycle: dict, product: dict, country_id: str, year: int = Non
136
142
  grouping = _term_grouping(product_term) or None
137
143
 
138
144
  should_run = all([not_already_set, has_yield, grouping])
139
- value = _lookup_data(term_id, grouping, country_id, year, term_type=term_type) if should_run else None
145
+ value = _lookup_data(term_id, grouping, country, year, term_type=term_type) if should_run else None
140
146
 
141
147
  # if units is number instead of kg, need to convert to number first
142
- conversion_to_number = safe_parse_float(get_table_value(
143
- download_lookup(LOOKUP_UNITS_NUMBER.get(term_type)), 'termid', country_id, column_name(grouping)
144
- ), 1) if term_units == Units.NUMBER.value else 1
148
+ conversion_to_number = safe_parse_float(
149
+ get_region_lookup_value(LOOKUP_UNITS_NUMBER.get(term_type), country.get('@id'), grouping), 1
150
+ ) if term_units == Units.NUMBER.value else 1
145
151
 
146
152
  logRequirements(cycle, model=MODEL, term=term_id, key=MODEL_KEY, by='country',
147
153
  has_yield=has_yield,
@@ -161,7 +167,7 @@ def _should_run_product(product: dict): return product.get(MODEL_KEY) is None
161
167
 
162
168
 
163
169
  def run(cycle: dict):
164
- country_id = cycle.get('site', {}).get('country', {}).get('@id')
170
+ country = cycle.get('site', {}).get('country', {})
165
171
  end_date = safe_parse_date(cycle.get('endDate'))
166
172
  year = end_date.year if end_date else None
167
173
 
@@ -169,8 +175,8 @@ def run(cycle: dict):
169
175
  return non_empty_list([
170
176
  (
171
177
  (
172
- (_run_by_liveAnimal(cycle, p, country_id, year) if _should_run_liveAnimal(p) else None)
173
- or _run_by_country(cycle, p, country_id, year)
174
- ) if country_id else None
178
+ (_run_by_liveAnimal(cycle, p, country, year) if _should_run_liveAnimal(p) else None)
179
+ or _run_by_country(cycle, p, country, year)
180
+ ) if country else None
175
181
  ) for p in products
176
182
  ])
@@ -22,8 +22,8 @@ REQUIREMENTS = {
22
22
  }
23
23
  }
24
24
  LOOKUPS = {
25
- "region-animalProduct-animalProductGroupingFAO-productionQuantity": "production quantity",
26
- "region-animalProduct-animalProductGroupingFAO-head": "number of heads"
25
+ "region-animalProduct-animalProductGroupingFAO-productionQuantity": "",
26
+ "region-animalProduct-animalProductGroupingFAO-head": ""
27
27
  }
28
28
  RETURNS = {
29
29
  "Product": [{
@@ -1,4 +1,3 @@
1
- from numpy import recarray
2
1
  from hestia_earth.schema import TermTermType
3
2
  from hestia_earth.utils.api import download_hestia
4
3
  from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name, extract_grouped_data_closest_date
@@ -11,9 +10,11 @@ from hestia_earth.models.utils.animalProduct import (
11
10
  from hestia_earth.models.utils.product import convert_product_to_unit
12
11
  from hestia_earth.models.utils.impact_assessment import get_country_id, impact_end_year
13
12
  from hestia_earth.models.utils.indicator import _new_indicator
13
+ from hestia_earth.models.utils.lookup import get_region_lookup_value
14
14
  from . import MODEL
15
15
 
16
16
  LOOKUP_PREFIX = f"{TermTermType.REGION.value}-{TermTermType.ANIMALPRODUCT.value}-{FAO_LOOKUP_COLUMN}"
17
+ FAOSTAT_AREA_LOOKUP = 'region-faostatArea.csv'
17
18
 
18
19
 
19
20
  def get_liveAnimal_to_animalProduct_id(product_term_id: str, column: str, **log_args):
@@ -32,12 +33,10 @@ def product_equivalent_value(product: dict, year: int, country: str):
32
33
  if not grouping or not fao_product_id:
33
34
  return None
34
35
 
35
- lookup = download_lookup(f"{LOOKUP_PREFIX}-productionQuantity.csv")
36
- quantity_values = get_table_value(lookup, 'termid', country, column_name(grouping))
36
+ quantity_values = get_region_lookup_value(f"{LOOKUP_PREFIX}-productionQuantity.csv", country, grouping)
37
37
  quantity = safe_parse_float(extract_grouped_data_closest_date(quantity_values, year))
38
38
 
39
- lookup = download_lookup(f"{LOOKUP_PREFIX}-head.csv")
40
- head_values = get_table_value(lookup, 'termid', country, column_name(grouping))
39
+ head_values = get_region_lookup_value(f"{LOOKUP_PREFIX}-head.csv", country, grouping)
41
40
  head = safe_parse_float(extract_grouped_data_closest_date(head_values, year))
42
41
 
43
42
  # quantity is in Tonnes
@@ -64,11 +63,11 @@ def _split_delta(table_value: str, start_year: int, end_year: int):
64
63
  ]) else None
65
64
 
66
65
 
67
- def get_sum_of_columns(lookup: recarray, country: str, year: int, columns_list: list) -> float:
66
+ def get_sum_of_columns(country: str, year: int, columns_list: list) -> float:
68
67
  return sum(
69
68
  [safe_parse_float(
70
69
  extract_grouped_data_closest_date(
71
- data=get_table_value(lookup, 'termid', country, column_name(col)),
70
+ data=get_region_lookup_value(FAOSTAT_AREA_LOOKUP, country, col, model=MODEL),
72
71
  year=year
73
72
  )
74
73
  ) for col in columns_list]
@@ -76,9 +75,8 @@ def get_sum_of_columns(lookup: recarray, country: str, year: int, columns_list:
76
75
 
77
76
 
78
77
  def get_single_delta(country: str, start_year: int, end_year: int, column: str):
79
- lookup = download_lookup('region-faostatArea.csv')
80
78
  return _split_delta(
81
- get_table_value(lookup, 'termid', country, column_name(column)), start_year, end_year
79
+ get_region_lookup_value(FAOSTAT_AREA_LOOKUP, country, column, model=MODEL), start_year, end_year
82
80
  )
83
81
 
84
82
 
@@ -88,27 +86,24 @@ def get_land_ratio(
88
86
  """
89
87
  total_column is optional. Assumes that, if missing, total is the sum of values from first and second.
90
88
  """
91
- lookup = download_lookup('region-faostatArea.csv')
92
89
  first_delta = _split_delta(
93
- get_table_value(lookup, 'termid', country, column_name(first_column)), start_year, end_year
90
+ get_region_lookup_value(FAOSTAT_AREA_LOOKUP, country, first_column, model=MODEL), start_year, end_year
94
91
  )
95
92
  second_delta = _split_delta(
96
- get_table_value(lookup, 'termid', country, column_name(second_column)), start_year, end_year
93
+ get_region_lookup_value(FAOSTAT_AREA_LOOKUP, country, second_column, model=MODEL), start_year, end_year
97
94
  )
98
95
  total_delta = (
99
96
  get_sum_of_columns(
100
- lookup=lookup,
101
97
  country=country,
102
98
  year=end_year,
103
99
  columns_list=[first_column, second_column]
104
100
  ) - get_sum_of_columns(
105
- lookup=lookup,
106
101
  country=country,
107
102
  year=start_year,
108
103
  columns_list=[first_column, second_column]
109
104
  )
110
105
  ) if total_column is None else _split_delta(
111
- get_table_value(lookup, 'termid', country, column_name(total_column)), start_year, end_year
106
+ get_region_lookup_value(FAOSTAT_AREA_LOOKUP, country, total_column, model=MODEL), start_year, end_year
112
107
  )
113
108
 
114
109
  return (None, None, None) if any([
@@ -130,18 +125,11 @@ def get_cropland_ratio(country: str, start_year: int, end_year: int):
130
125
 
131
126
 
132
127
  def get_change_in_harvested_area_for_crop(country_id: str, crop_name: str, start_year: int, end_year: int = 0):
133
- lookup = download_lookup('region-crop-cropGroupingFaostatProduction-areaHarvested.csv')
134
- if end_year == 0 or end_year == start_year:
135
- return safe_parse_float(
136
- extract_grouped_data_closest_date(
137
- data=get_table_value(lookup, 'termid', country_id, column_name(crop_name)),
138
- year=start_year
139
- )
140
- )
141
- else:
142
- return _split_delta(
143
- get_table_value(lookup, 'termid', country_id, column_name(crop_name)), start_year, end_year
144
- )
128
+ lookup_name = 'region-crop-cropGroupingFaostatProduction-areaHarvested.csv'
129
+ value = get_region_lookup_value(lookup_name, country_id, crop_name)
130
+ return safe_parse_float(
131
+ extract_grouped_data_closest_date(value, start_year)
132
+ ) if end_year == 0 or end_year == start_year else _split_delta(value, start_year, end_year)
145
133
 
146
134
 
147
135
  def should_run_landTransformationFromCropland(term_id: str, impact: dict):
@@ -63,9 +63,11 @@ def _run(emissions: list):
63
63
 
64
64
 
65
65
  def _should_run(impact_assessment: dict):
66
- emissions = [emission for emission in filter_list_term_type(impact_assessment.get('emissionsResourceUse', []),
67
- TermTermType.EMISSION)
68
- if emission.get('term', {}).get('@id', '') in LOOKUPS[TermTermType.WASTE.value]]
66
+ emissions = [
67
+ emission
68
+ for emission in filter_list_term_type(impact_assessment.get('emissionsResourceUse', []), TermTermType.EMISSION)
69
+ if emission.get('term', {}).get('@id', '') in LOOKUPS[TermTermType.WASTE.value]
70
+ ]
69
71
 
70
72
  has_emissions = bool(emissions)
71
73
 
@@ -80,7 +82,7 @@ def _should_run(impact_assessment: dict):
80
82
  "input": input,
81
83
  "indicator-input-is-valid": _valid_waste(input),
82
84
  "value": _node_value(emission),
83
- "coefficient": get_table_value(array=download_lookup(filename="waste.csv"),
85
+ "coefficient": get_table_value(lookup=download_lookup(filename="waste.csv"),
84
86
  col_match='termid',
85
87
  col_match_with=input.get('@id'),
86
88
  col_val=column_name(emission['term']['@id'])) if input else None
@@ -89,9 +91,13 @@ def _should_run(impact_assessment: dict):
89
91
  ]
90
92
  )
91
93
 
92
- valid_emission_with_cf = [em for em in emissions_unpacked if em['coefficient'] is not None
93
- and em['indicator-is-valid'] is True
94
- and em['indicator-input-is-valid'] is True]
94
+ valid_emission_with_cf = [
95
+ em for em in emissions_unpacked if all([
96
+ em['coefficient'] is not None,
97
+ em['indicator-is-valid'] is True,
98
+ em['indicator-input-is-valid'] is True
99
+ ])
100
+ ]
95
101
 
96
102
  valid_input_requirements = all([
97
103
  all([
@@ -101,8 +107,9 @@ def _should_run(impact_assessment: dict):
101
107
  for em in emissions_unpacked
102
108
  ])
103
109
 
104
- all_emissions_have_known_cf = all([em['coefficient'] is not None for em in emissions_unpacked]) and bool(
105
- emissions_unpacked)
110
+ all_emissions_have_known_cf = all([
111
+ em['coefficient'] is not None for em in emissions_unpacked
112
+ ]) and bool(emissions_unpacked)
106
113
 
107
114
  logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
108
115
  has_emissions=has_emissions,