hestia-earth-models 0.67.0__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 (161) 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/cml2001Baseline/resourceUseEnergyDepletionDuringCycle.py +5 -10
  13. hestia_earth/models/config/Cycle.json +15 -0
  14. hestia_earth/models/config/ImpactAssessment.json +14 -1
  15. hestia_earth/models/config/Site.json +8 -0
  16. hestia_earth/models/cycle/completeness/freshForage.py +7 -3
  17. hestia_earth/models/cycle/excretaKgMass.py +2 -2
  18. hestia_earth/models/cycle/inorganicFertiliser.py +67 -17
  19. hestia_earth/models/cycle/materialAndSubstrate.py +3 -2
  20. hestia_earth/models/cycle/pastureGrass.py +3 -3
  21. hestia_earth/models/dammgen2009/noxToAirExcreta.py +1 -1
  22. hestia_earth/models/ecoinventV3AndEmberClimate/__init__.py +1 -1
  23. hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +2 -6
  24. hestia_earth/models/emissionNotRelevant/__init__.py +4 -4
  25. hestia_earth/models/environmentalFootprintV3_1/environmentalFootprintSingleOverallScore.py +60 -46
  26. hestia_earth/models/environmentalFootprintV3_1/photochemicalOzoneCreationPotentialHumanHealthNmvocEq.py +36 -0
  27. hestia_earth/models/environmentalFootprintV3_1/scarcityWeightedWaterUse.py +2 -2
  28. hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandOccupation.py +9 -8
  29. hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandTransformation.py +45 -34
  30. hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexTotalLandUseEffects.py +24 -21
  31. hestia_earth/models/faostat2018/coldCarcassWeightPerHead.py +2 -2
  32. hestia_earth/models/faostat2018/coldDressedCarcassWeightPerHead.py +2 -2
  33. hestia_earth/models/faostat2018/liveweightPerHead.py +7 -8
  34. hestia_earth/models/faostat2018/product/price.py +34 -28
  35. hestia_earth/models/faostat2018/readyToCookWeightPerHead.py +2 -2
  36. hestia_earth/models/faostat2018/utils.py +15 -27
  37. hestia_earth/models/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +16 -9
  38. hestia_earth/models/geospatialDatabase/altitude.py +60 -0
  39. hestia_earth/models/geospatialDatabase/croppingIntensity.py +1 -1
  40. hestia_earth/models/geospatialDatabase/ecoClimateZone.py +2 -2
  41. hestia_earth/models/geospatialDatabase/longFallowRatio.py +1 -1
  42. hestia_earth/models/geospatialDatabase/utils.py +4 -1
  43. hestia_earth/models/globalCropWaterModel2008/rootingDepth.py +2 -3
  44. hestia_earth/models/haversineFormula/transport/distance.py +3 -3
  45. hestia_earth/models/hestia/landCover.py +72 -45
  46. hestia_earth/models/hestia/landTransformation100YearAverageDuringCycle.py +1 -1
  47. hestia_earth/models/hestia/landTransformation20YearAverageDuringCycle.py +1 -1
  48. hestia_earth/models/hestia/seed_emissions.py +11 -7
  49. hestia_earth/models/impact_assessment/__init__.py +3 -3
  50. hestia_earth/models/ipcc2019/aboveGroundBiomass.py +1 -1
  51. hestia_earth/models/ipcc2019/animal/fatContent.py +1 -1
  52. hestia_earth/models/ipcc2019/animal/hoursWorkedPerDay.py +1 -1
  53. hestia_earth/models/ipcc2019/animal/liveweightGain.py +1 -1
  54. hestia_earth/models/ipcc2019/animal/liveweightPerHead.py +1 -1
  55. hestia_earth/models/ipcc2019/animal/milkYieldPerAnimal.py +1 -1
  56. hestia_earth/models/ipcc2019/animal/pastureGrass.py +1 -1
  57. hestia_earth/models/ipcc2019/animal/pregnancyRateTotal.py +1 -1
  58. hestia_earth/models/ipcc2019/animal/trueProteinContent.py +1 -1
  59. hestia_earth/models/ipcc2019/animal/utils.py +5 -7
  60. hestia_earth/models/ipcc2019/animal/weightAtMaturity.py +1 -1
  61. hestia_earth/models/ipcc2019/belowGroundBiomass.py +1 -1
  62. hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +2 -2
  63. hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +6 -7
  64. hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +5 -3
  65. hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +1 -1
  66. hestia_earth/models/ipcc2019/croppingDuration.py +3 -6
  67. hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +947 -0
  68. hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1_utils.py +4 -4
  69. hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2_utils.py +1 -1
  70. hestia_earth/models/ipcc2019/pastureGrass.py +1 -1
  71. hestia_earth/models/koble2014/residueBurnt.py +5 -7
  72. hestia_earth/models/koble2014/residueRemoved.py +5 -7
  73. hestia_earth/models/lcImpactAllEffects100Years/damageToHumanHealthWaterStress.py +2 -2
  74. hestia_earth/models/lcImpactAllEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
  75. hestia_earth/models/lcImpactCertainEffects100Years/damageToHumanHealthWaterStress.py +2 -2
  76. hestia_earth/models/lcImpactCertainEffectsInfinite/damageToHumanHealthWaterStress.py +2 -2
  77. hestia_earth/models/log.py +1 -1
  78. hestia_earth/models/mocking/search-results.json +3477 -1045
  79. hestia_earth/models/site/management.py +1 -1
  80. hestia_earth/models/site/post_checks/__init__.py +3 -2
  81. hestia_earth/models/site/post_checks/country.py +9 -0
  82. hestia_earth/models/site/pre_checks/__init__.py +3 -2
  83. hestia_earth/models/site/pre_checks/country.py +9 -0
  84. hestia_earth/models/utils/__init__.py +1 -16
  85. hestia_earth/models/utils/blank_node.py +89 -36
  86. hestia_earth/models/utils/completeness.py +3 -2
  87. hestia_earth/models/utils/cycle.py +5 -4
  88. hestia_earth/models/utils/ecoClimateZone.py +2 -2
  89. hestia_earth/models/utils/emission.py +5 -5
  90. hestia_earth/models/utils/feedipedia.py +6 -6
  91. hestia_earth/models/utils/impact_assessment.py +6 -6
  92. hestia_earth/models/utils/indicator.py +9 -7
  93. hestia_earth/models/utils/inorganicFertiliser.py +4 -6
  94. hestia_earth/models/utils/input.py +6 -5
  95. hestia_earth/models/utils/lookup.py +35 -105
  96. hestia_earth/models/utils/management.py +4 -4
  97. hestia_earth/models/utils/measurement.py +6 -7
  98. hestia_earth/models/utils/method.py +20 -0
  99. hestia_earth/models/utils/practice.py +4 -5
  100. hestia_earth/models/utils/product.py +4 -5
  101. hestia_earth/models/utils/property.py +12 -22
  102. hestia_earth/models/utils/site.py +14 -8
  103. hestia_earth/models/utils/term.py +27 -1
  104. hestia_earth/models/version.py +1 -1
  105. hestia_earth/orchestrator/log.py +0 -11
  106. hestia_earth/orchestrator/models/__init__.py +17 -4
  107. hestia_earth/orchestrator/strategies/run/add_blank_node_if_missing.py +2 -20
  108. {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/METADATA +2 -2
  109. {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/RECORD +159 -151
  110. tests/models/cml2001Baseline/test_abioticResourceDepletionFossilFuels.py +3 -3
  111. tests/models/cml2001Baseline/test_resourceUseEnergyDepletionDuringCycle.py +68 -35
  112. tests/models/cycle/test_coldCarcassWeightPerHead.py +1 -1
  113. tests/models/cycle/test_coldDressedCarcassWeightPerHead.py +1 -1
  114. tests/models/cycle/test_concentrateFeed.py +1 -1
  115. tests/models/cycle/test_energyContentLowerHeatingValue.py +1 -1
  116. tests/models/cycle/test_excretaKgMass.py +1 -1
  117. tests/models/cycle/test_feedConversionRatio.py +3 -3
  118. tests/models/cycle/test_pastureGrass.py +1 -1
  119. tests/models/cycle/test_readyToCookWeightPerHead.py +1 -1
  120. tests/models/environmentalFootprintV3_1/test_environmentalFootprintSingleOverallScore.py +38 -8
  121. tests/models/environmentalFootprintV3_1/test_photochemicalOzoneCreationPotentialHumanHealthNmvocEq.py +30 -0
  122. tests/models/environmentalFootprintV3_1/test_soilQualityIndexLandTransformation.py +65 -36
  123. tests/models/environmentalFootprintV3_1/test_soilQualityIndexTotalLandUseEffects.py +30 -7
  124. tests/models/faostat2018/product/test_price.py +27 -14
  125. tests/models/faostat2018/test_faostat_utils.py +4 -24
  126. tests/models/faostat2018/test_liveweightPerHead.py +9 -9
  127. tests/models/globalCropWaterModel2008/test_rootingDepth.py +7 -3
  128. tests/models/haversineFormula/transport/test_distance.py +1 -1
  129. tests/models/hestia/test_landCover.py +53 -5
  130. tests/models/ipcc2019/animal/test_pastureGrass.py +5 -3
  131. tests/models/ipcc2019/test_aboveGroundCropResidueTotal.py +4 -4
  132. tests/models/ipcc2019/test_belowGroundCropResidue.py +4 -4
  133. tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +10 -10
  134. tests/models/ipcc2019/test_croppingDuration.py +1 -1
  135. tests/models/ipcc2019/test_nonCo2EmissionsToAirNaturalVegetationBurning.py +83 -0
  136. tests/models/ipcc2019/test_organicCarbonPerHa.py +12 -12
  137. tests/models/ipcc2019/test_pastureGrass.py +5 -3
  138. tests/models/pooreNemecek2018/test_excretaKgN.py +5 -5
  139. tests/models/pooreNemecek2018/test_excretaKgVs.py +2 -2
  140. tests/models/site/post_checks/test_country.py +6 -0
  141. tests/models/site/pre_checks/test_cache_geospatialDatabase.py +1 -1
  142. tests/models/site/pre_checks/test_country.py +12 -0
  143. tests/models/site/test_management.py +1 -4
  144. tests/models/test_ecoinventV3.py +7 -3
  145. tests/models/utils/test_blank_node.py +17 -177
  146. tests/models/utils/test_dataCompleteness.py +5 -5
  147. tests/models/utils/test_emission.py +2 -2
  148. tests/models/utils/test_indicator.py +2 -2
  149. tests/models/utils/test_input.py +2 -2
  150. tests/models/utils/test_measurement.py +2 -4
  151. tests/models/utils/test_practice.py +4 -2
  152. tests/models/utils/test_product.py +2 -2
  153. tests/models/utils/test_property.py +4 -2
  154. tests/models/utils/test_site.py +7 -0
  155. tests/orchestrator/models/test_transformations.py +4 -1
  156. tests/orchestrator/strategies/run/test_add_blank_node_if_missing.py +4 -9
  157. hestia_earth/models/environmentalFootprintV3_1/utils.py +0 -17
  158. tests/models/utils/test_lookup.py +0 -10
  159. {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/LICENSE +0 -0
  160. {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/WHEEL +0 -0
  161. {hestia_earth_models-0.67.0.dist-info → hestia_earth_models-0.68.0.dist-info}/top_level.txt +0 -0
@@ -64,7 +64,7 @@ RETURNS = {
64
64
  }
65
65
  LOOKUPS = {
66
66
  "electricity": "ecoinventMapping",
67
- "region-ember-energySources": "using `country`",
67
+ "region-ember-energySources": "",
68
68
  "ember-ecoinvent-mapping": ["ember", "ecoinventId", "ecoinventName"]
69
69
  }
70
70
 
@@ -1,8 +1,8 @@
1
1
  from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name, extract_grouped_data
2
2
  from hestia_earth.utils.tools import safe_parse_float
3
3
 
4
- from hestia_earth.models.log import debugMissingLookup
5
4
  from hestia_earth.models.utils.cycle import cycle_end_year
5
+ from hestia_earth.models.utils.lookup import get_region_lookup_value
6
6
 
7
7
  EMBER_ECOINVENT_LOOKUP_NAME = "ember-ecoinvent-mapping.csv"
8
8
  REGION_EMBER_SOURCES_LOOKUP_NAME = "region-ember-energySources.csv"
@@ -17,10 +17,6 @@ def get_input_coefficient(model: str, cycle: dict, country_id: str, ecoinventNam
17
17
  source_name = get_table_value(ember_ecoinvent_lookup, column_name('ecoinventName'), ecoinventName, 'ember')
18
18
 
19
19
  # find the ratio for the country / year
20
- region_ember_sources_lookup = download_lookup(REGION_EMBER_SOURCES_LOOKUP_NAME)
21
- data = get_table_value(region_ember_sources_lookup, 'termid', country_id, column_name(source_name))
20
+ data = get_region_lookup_value(REGION_EMBER_SOURCES_LOOKUP_NAME, country_id, source_name, model=model)
22
21
  percentage = extract_grouped_data(data, str(year))
23
- debugMissingLookup(REGION_EMBER_SOURCES_LOOKUP_NAME,
24
- 'termid', country_id, source_name, percentage, year=year, model=model)
25
-
26
22
  return safe_parse_float(percentage, 0) / 100
@@ -3,8 +3,8 @@ Emission not relevant
3
3
 
4
4
  The emission is not relevant for this Site, Cycle, or Product.
5
5
  """
6
- from hestia_earth.schema import NodeType, TermTermType, EmissionMethodTier
7
- from hestia_earth.utils.emission import emission_is_in_system_boundary
6
+ from hestia_earth.schema import NodeType, EmissionMethodTier
7
+ from hestia_earth.utils.lookup_utils import is_in_system_boundary
8
8
 
9
9
  from hestia_earth.models.log import logRequirements, logShouldRun
10
10
  from hestia_earth.models.utils.emission import _new_emission
@@ -38,8 +38,8 @@ def _emission(term_id: str):
38
38
 
39
39
  def _should_run_emission(cycle: dict):
40
40
  def run(term_id: str):
41
- is_not_relevant = not _run_required(MODEL, {'@id': term_id, 'termType': TermTermType.EMISSION.value}, cycle)
42
- in_system_boundary = emission_is_in_system_boundary(term_id)
41
+ is_not_relevant = not _run_required(MODEL, term_id, cycle)
42
+ in_system_boundary = is_in_system_boundary(term_id)
43
43
 
44
44
  should_run = all([is_not_relevant, in_system_boundary])
45
45
  if should_run:
@@ -10,30 +10,32 @@ in EF3.0 and EF3.1.
10
10
  from typing import List, Optional, Tuple
11
11
 
12
12
  from hestia_earth.schema import TermTermType
13
- from hestia_earth.utils.lookup import get_table_value, download_lookup, column_name
14
13
  from hestia_earth.utils.model import filter_list_term_type
15
14
  from hestia_earth.utils.tools import list_sum
16
15
 
17
- from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table, debugMissingLookup
16
+ from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table, debugValues
17
+ from hestia_earth.models.utils.blank_node import get_lookup_value
18
18
  from hestia_earth.models.utils.indicator import _new_indicator
19
19
  from hestia_earth.models.utils.lookup import _node_value
20
20
  from . import MODEL
21
21
 
22
22
  REQUIREMENTS = {
23
23
  "ImpactAssessment": {
24
- "impacts": [
25
- {
26
- "@type": "Indicator",
27
- "value": "",
28
- "term.name": "PEF indicators only"
29
- }
30
- ]
24
+ "impacts": [{
25
+ "@type": "Indicator",
26
+ "value": "",
27
+ "term.name": "PEF indicators only"
28
+ }]
31
29
  }
32
30
  }
33
31
 
34
32
  LOOKUPS = {
35
33
  "@doc": "Normalisation factors in PEF v3.1 are calculated using a Global population number of 6,895,889,018",
36
- "characterisedIndicator": ["pefTerm-normalisation-v3_1", "pefTerm-weighing-v3_1"]
34
+ "characterisedIndicator": [
35
+ "pefTerm-normalisation-v3_1",
36
+ "pefTerm-weighing-v3_1",
37
+ "pefTerm-methodModel-whiteList-v3-1"
38
+ ]
37
39
  }
38
40
 
39
41
  RETURNS = {
@@ -46,32 +48,54 @@ TERM_ID = 'environmentalFootprintSingleOverallScore'
46
48
 
47
49
  normalisation_column = LOOKUPS['characterisedIndicator'][0]
48
50
  weighing_column = LOOKUPS['characterisedIndicator'][1]
51
+ method_model_colum = LOOKUPS['characterisedIndicator'][2]
49
52
 
50
53
 
51
- def _is_a_PEF_indicator(indicator_id) -> bool:
52
- return (_get_factor(indicator_id, normalisation_column) not in [None, 0, 0.0] and
53
- _get_factor(indicator_id, weighing_column) not in [None, 0, 0.0])
54
+ def _is_a_PEF_indicator(indicator: dict) -> bool:
55
+ term = indicator.get('term', {})
56
+ indicator_method_model = indicator.get('methodModel', {}).get("@id")
57
+ return all([
58
+ indicator_method_model,
59
+ indicator_method_model in _get_pef_method_model(term),
60
+ _get_factor(term, normalisation_column) is not None,
61
+ _get_factor(term, weighing_column) is not None
62
+ ])
54
63
 
55
64
 
56
- def _get_factor(indicator_id: str, column) -> Optional[float]:
57
- factor = get_table_value(download_lookup(f"{list(LOOKUPS.keys())[1]}.csv", keep_in_memory=True),
58
- 'termid', indicator_id, column_name(column))
59
- if factor is None:
60
- debugMissingLookup(f"{list(LOOKUPS.keys())[1]}.csv", 'termid', indicator_id, column, None, model=MODEL,
61
- term=TERM_ID)
65
+ def _get_factor(term: dict, column: str) -> Optional[float]:
66
+ factor = get_lookup_value(term, column, model=MODEL, term=TERM_ID)
62
67
  return float(factor) if factor is not None else None
63
68
 
64
69
 
65
- def _normalise(indicator: dict) -> Optional[float]:
66
- return (_node_value(indicator) / _get_factor(indicator['term']['@id'], normalisation_column)) \
67
- if (_node_value(indicator) is not None and
68
- _get_factor(indicator['term']['@id'], normalisation_column) not in [None, 0, 0.0]) else None
69
-
70
-
71
- def _weighted_normalise(indicator: dict) -> Optional[float]:
72
- return (_normalise(indicator) * (_get_factor(indicator['term']['@id'], weighing_column) / 100)
73
- ) if (_normalise(indicator) is not None and
74
- _get_factor(indicator['term']['@id'], weighing_column) not in [None, 0, 0.0]) else None
70
+ def _get_pef_method_model(term: dict) -> List[str]:
71
+ entries = get_lookup_value(term, method_model_colum, model=MODEL, term=TERM_ID) or ''
72
+ return entries.split(";")
73
+
74
+
75
+ def _indicator_factors(impact_assessment: dict, indicator: dict):
76
+ value = _node_value(indicator)
77
+ normalisation_factor = _get_factor(indicator.get('term', {}), normalisation_column)
78
+ weighting_factor = _get_factor(indicator.get('term', {}), weighing_column)
79
+ coefficient = 0 if all([
80
+ weighting_factor == 0,
81
+ normalisation_factor == 0
82
+ ]) else (weighting_factor / 100) / normalisation_factor if all([
83
+ weighting_factor is not None,
84
+ normalisation_factor is not None
85
+ ]) else None
86
+
87
+ debugValues(impact_assessment, model=MODEL, term=TERM_ID,
88
+ node=indicator['term']['@id'],
89
+ value=value,
90
+ coefficient=coefficient)
91
+
92
+ return {
93
+ "value": value,
94
+ "normalisation-used": normalisation_factor,
95
+ "weighting-used": weighting_factor,
96
+ "coefficient": coefficient,
97
+ "weighted-value": value * coefficient if all([value is not None, coefficient is not None]) else None,
98
+ }
75
99
 
76
100
 
77
101
  def _indicator(value: float) -> dict:
@@ -81,38 +105,28 @@ def _indicator(value: float) -> dict:
81
105
 
82
106
 
83
107
  def _run(indicators: List[dict]):
84
- return _indicator(value=list_sum([indicator["weighted-normalised"] for indicator in indicators]))
108
+ return _indicator(value=list_sum([indicator["weighted-value"] for indicator in indicators]))
85
109
 
86
110
 
87
111
  def _valid_indicator(indicator: Optional[dict]) -> bool:
88
- return all([indicator is not None,
89
- isinstance(_node_value(indicator), (int, float)),
90
- _node_value(indicator) is not None,
91
- _is_a_PEF_indicator(indicator.get('term', {}).get('@id', ''))])
112
+ value = None if indicator is None else _node_value(indicator)
113
+ return isinstance(value, (int, float)) and _is_a_PEF_indicator(indicator)
92
114
 
93
115
 
94
116
  def _should_run(impact_assessment: dict) -> Tuple[bool, list[dict]]:
95
117
  indicators = [
96
118
  indicator for indicator in
97
119
  filter_list_term_type(impact_assessment.get('impacts', []), TermTermType.CHARACTERISEDINDICATOR)
98
- if _is_a_PEF_indicator(indicator.get('term', {}).get('@id', ''))
120
+ if _is_a_PEF_indicator(indicator)
99
121
  ]
100
-
101
122
  has_pef_indicators = bool(indicators)
102
123
 
103
124
  processed_indicators = [{
104
- "indicator": indicator,
125
+ "indicator": indicator['term']['@id'],
105
126
  "valid-indicator": _valid_indicator(indicator),
106
127
  "one-indicator-for-category": sum(1 for i in indicators if i['term']['@id'] == indicator['term']['@id']) == 1,
107
- "indicator-pef-category": indicator['term']['@id'],
108
- "value": _node_value(indicator),
109
- "normalised": _normalise(indicator),
110
- "normalisation-used": _get_factor(indicator['term']['@id'], normalisation_column),
111
- "weighted-normalised": _weighted_normalise(indicator),
112
- "weighting-used": _get_factor(indicator['term']['@id'], weighing_column),
113
- }
114
- for indicator in indicators
115
- ]
128
+ "indicator-pef-category": indicator.get('term', {}).get('@id'),
129
+ } | _indicator_factors(impact_assessment, indicator) for indicator in indicators]
116
130
 
117
131
  no_duplicate_indicators = all([indicator['one-indicator-for-category'] for indicator in processed_indicators])
118
132
  valid_indicators = [indicator for indicator in processed_indicators if indicator['valid-indicator']]
@@ -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
- from hestia_earth.utils.model import filter_list_term_type
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": {
@@ -26,7 +24,7 @@ REQUIREMENTS = {
26
24
  "@type": "Indicator",
27
25
  "term.termType": "resourceUse",
28
26
  "term.@id": "landTransformation20YearAverageDuringCycle",
29
- "value": "> 0",
27
+ "value": ">= 0",
30
28
  "landCover": {"@type": "Term", "term.termType": "landCover"},
31
29
  "previousLandCover": {"@type": "Term", "term.termType": "landCover"}
32
30
  }
@@ -38,7 +36,7 @@ REQUIREMENTS = {
38
36
  "@type": "Indicator",
39
37
  "term.termType": "resourceUse",
40
38
  "term.@id": "landTransformation20YearAverageInputsProduction",
41
- "value": "> 0",
39
+ "value": ">= 0",
42
40
  "landCover": {"@type": "Term", "term.termType": "landCover"},
43
41
  "previousLandCover": {"@type": "Term", "term.termType": "landCover"}
44
42
  }
@@ -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
 
@@ -80,7 +78,8 @@ def _indicator(value: float):
80
78
 
81
79
  def _run(transformations: List[dict]):
82
80
  values = [
83
- (transformation.get('factor-from', 0) + transformation.get('factor-to', 0)) * transformation.get('area', 0) * 20
81
+ (transformation.get("factor-from", 0) + transformation.get("factor-to", 0)
82
+ ) * transformation.get("value", 0) * 20
84
83
  for transformation in transformations
85
84
  ]
86
85
  return _indicator(list_sum(values))
@@ -92,46 +91,53 @@ def _is_valid_indicator(indicator: dict) -> bool:
92
91
 
93
92
 
94
93
  def _should_run(impact_assessment: dict) -> Tuple[bool, list]:
95
- resource_uses = filter_list_term_type(impact_assessment.get('emissionsResourceUse', []), TermTermType.RESOURCEUSE)
94
+ resource_uses = [
95
+ i for i in filter_list_term_type(impact_assessment.get('emissionsResourceUse', []), TermTermType.RESOURCEUSE) if
96
+ _is_valid_indicator(i)
97
+ ]
98
+
96
99
  found_transformations = [
97
100
  {
98
- 'area': _node_value(transformation_indicator),
101
+ 'value': _node_value(transformation_indicator),
99
102
  'land-cover-id-from': transformation_indicator.get('previousLandCover', {}).get("@id"),
100
103
  'land-cover-id-to': transformation_indicator.get('landCover', {}).get("@id"),
101
104
  'indicator-id': transformation_indicator.get('term', {}).get('@id', ''),
102
- 'indicator-is-valid': _is_valid_indicator(transformation_indicator),
103
- 'good-land-cover-term': all([bool(transformation_indicator.get('landCover')),
104
- bool(transformation_indicator.get('previousLandCover'))]),
105
+ 'good-land-cover-term': all([
106
+ bool(transformation_indicator.get('landCover')),
107
+ bool(transformation_indicator.get('previousLandCover'))
108
+ ]),
105
109
  'country-id': get_country_id(impact_assessment),
106
- 'area-is-valid': _node_value(transformation_indicator) is not None and _node_value(
107
- transformation_indicator) > 0,
108
- 'lookup-country': fallback_country(get_country_id(impact_assessment),
109
- [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]),
110
115
  } for transformation_indicator in resource_uses
111
116
  ]
112
117
 
113
118
  found_transformations_with_coefficient = [
114
119
  transformation | {
115
120
  'using-fallback-country-region-world-CFs': transformation['lookup-country'] != transformation['country-id'],
116
- 'factor-from': get_coefficient_factor(
121
+ 'factor-from': get_region_lookup_value(
122
+ model=MODEL,
123
+ term=TERM_ID,
117
124
  lookup_name=from_lookup_file,
118
- country_id=transformation['lookup-country'],
119
- term_id=TERM_ID,
120
- 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
121
127
  transformation['land-cover-id-from'] else None,
122
- 'factor-to': get_coefficient_factor(
128
+ 'factor-to': get_region_lookup_value(
129
+ model=MODEL,
130
+ term=TERM_ID,
123
131
  lookup_name=to_lookup_file,
124
- country_id=transformation['lookup-country'],
125
- term_id=TERM_ID,
126
- 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
127
134
  transformation['land-cover-id-to'] else None
128
135
  } for transformation in found_transformations
129
136
  ]
130
137
 
131
138
  valid_transformations_with_coef = [
132
139
  t for t in found_transformations_with_coefficient if all([
133
- t['area-is-valid'],
134
- t['indicator-is-valid'],
140
+ t['value-is-valid'],
135
141
  t['factor-from'] is not None,
136
142
  t['factor-to'] is not None
137
143
  ])
@@ -144,19 +150,24 @@ def _should_run(impact_assessment: dict) -> Tuple[bool, list]:
144
150
 
145
151
  all_transformations_are_valid = all(
146
152
  [
147
- all([t['area-is-valid'], t['indicator-is-valid'], t['good-land-cover-term']])
153
+ all([t['value-is-valid'], t['good-land-cover-term']])
148
154
  for t in found_transformations_with_coefficient
149
155
  ]
150
156
  ) if found_transformations_with_coefficient else False
151
157
 
158
+ has_a_during_cycle_indicator = bool(find_term_match(resource_uses, "landTransformation20YearAverageDuringCycle"))
159
+
152
160
  logRequirements(impact_assessment, model=MODEL, term=TERM_ID,
153
- has_land_occupation_indicators=has_land_transformation_indicators,
161
+ has_land_transformation_indicators=has_land_transformation_indicators,
162
+ has_a_during_cycle_indicator=has_a_during_cycle_indicator,
154
163
  all_transformations_are_valid=all_transformations_are_valid,
155
164
  has_valid_transformations_with_coef=bool(valid_transformations_with_coef),
156
165
  found_transformations=log_as_table(found_transformations_with_coefficient)
157
166
  )
158
167
 
159
- should_run = all([has_land_transformation_indicators, all_transformations_are_valid])
168
+ should_run = all([has_land_transformation_indicators,
169
+ has_a_during_cycle_indicator,
170
+ all_transformations_are_valid])
160
171
 
161
172
  logShouldRun(impact_assessment, MODEL, TERM_ID, should_run)
162
173
  return should_run, valid_transformations_with_coef
@@ -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,44 +33,46 @@ 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
- land_indicators = [
46
- i for i in impactassessment.get('emissionsResourceUse', []) if
47
- i.get('term', {}).get('@id', '') in ['soilQualityIndexLandOccupation', 'soilQualityIndexLandTransformation']
46
+ soil_quality_indicators = [
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
- has_indicators = bool(land_indicators)
50
+ has_soil_quality_indicators = bool(soil_quality_indicators)
50
51
 
51
- land_occupation_indicator = find_term_match(land_indicators, "soilQualityIndexLandOccupation",
52
- default_val=None)
53
- has_land_occupation_indicator = bool(land_occupation_indicator)
52
+ soil_quality_occupation_indicator = find_term_match(soil_quality_indicators, "soilQualityIndexLandOccupation",
53
+ default_val=None)
54
+ has_soil_quality_land_occupation_indicator = bool(soil_quality_occupation_indicator)
54
55
 
55
- land_transformation_indicator = find_term_match(land_indicators, "soilQualityIndexLandTransformation",
56
- default_val=None)
57
- has_land_transformation_indicator = bool(land_transformation_indicator)
56
+ soil_quality_transformation_indicator = find_term_match(soil_quality_indicators,
57
+ "soilQualityIndexLandTransformation",
58
+ default_val=None)
59
+ has_soil_quality_land_transformation_indicator = bool(soil_quality_transformation_indicator)
58
60
 
59
- has_valid_values = all([isinstance(indicator.get('value', None), (int, float)) for indicator in land_indicators])
61
+ has_valid_values = all(
62
+ [isinstance(indicator.get('value', None), (int, float)) for indicator in soil_quality_indicators])
60
63
 
61
64
  logRequirements(impactassessment, model=MODEL, term=TERM_ID,
62
- has_indicators=has_indicators,
63
- has_land_occupation_indicator=has_land_occupation_indicator,
64
- has_land_transformation_indicator=has_land_transformation_indicator,
65
+ has_soil_quality_indicators=has_soil_quality_indicators,
66
+ has_soil_quality_land_occupation_indicator=has_soil_quality_land_occupation_indicator,
67
+ has_soil_quality_land_transformation_indicator=has_soil_quality_land_transformation_indicator,
65
68
  has_valid_values=has_valid_values
66
69
  )
67
70
 
68
- should_run = all([has_indicators, has_valid_values,
69
- has_land_occupation_indicator, has_land_transformation_indicator])
71
+ should_run = all([has_soil_quality_indicators, has_valid_values,
72
+ has_soil_quality_land_occupation_indicator, has_soil_quality_land_transformation_indicator])
70
73
 
71
74
  logShouldRun(impactassessment, MODEL, TERM_ID, should_run)
72
- return should_run, land_indicators
75
+ return should_run, soil_quality_indicators
73
76
 
74
77
 
75
78
  def run(impactassessment: dict):
@@ -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,