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
@@ -3,7 +3,7 @@ This model calculates the scarcity weighted water use based on the geospatial AW
3
3
  (see UNEP (2016); Boulay et al (2016); Boulay et al (2020); EC-JRC (2017)).
4
4
  """
5
5
  from hestia_earth.schema import SiteSiteType
6
- from hestia_earth.utils.lookup import download_lookup, _get_single_table_value, column_name, get_table_value
6
+ from hestia_earth.utils.lookup import download_lookup, _get_single_table_value, column_name
7
7
  from hestia_earth.utils.tools import safe_parse_float
8
8
 
9
9
  from hestia_earth.models.log import logRequirements, debugMissingLookup, logShouldRun
@@ -13,6 +13,7 @@ from hestia_earth.models.utils.impact_assessment import (
13
13
  convert_value_from_cycle, emission_value, get_product, get_site, get_region_id
14
14
  )
15
15
  from hestia_earth.models.utils.input import sum_input_impacts
16
+ from hestia_earth.models.utils.lookup import get_region_lookup_value
16
17
  from . import MODEL
17
18
 
18
19
  REQUIREMENTS = {
@@ -40,8 +41,8 @@ RETURNS = {
40
41
  }
41
42
  LOOKUPS = {
42
43
  "@doc": "Different lookup files are used depending on the situation",
43
- "awareWaterBasinId": "using `awareWaterBasinId` and `YR_IRRI` (for `cropland`, `glass or high accessible cover`, or `permanent pasture`) or `YR_NONIRRI`", # noqa: E501
44
- "region-aware-factors": "using `region` and `YR_IRRI` (for `cropland`, `glass or high accessible cover` or `permanent pasture`) or `YR_NONIRRI`" # noqa: E501
44
+ "awareWaterBasinId": "",
45
+ "region-aware-factors": ""
45
46
  }
46
47
  TERM_ID = 'scarcityWeightedWaterUse'
47
48
  AWARE_KEY = 'awareWaterBasinId'
@@ -71,11 +72,9 @@ def _get_factor_from_region(impact_assessment: dict, site: dict):
71
72
  region_id = get_region_id(impact_assessment)
72
73
  site_type = site.get('siteType')
73
74
  lookup_name = 'region-aware-factors.csv'
74
- lookup = download_lookup(lookup_name)
75
75
  lookup_suffix = 'unspecified' if not site_type else ('irri' if site_type in IRRIGATED_SITE_TYPES else 'non_irri')
76
76
  column = f"Agg_CF_{lookup_suffix}"
77
- value = get_table_value(lookup, 'termid', region_id, column_name(column))
78
- debugMissingLookup(lookup_name, 'termid', region_id, column, value, model=MODEL, term=TERM_ID)
77
+ value = get_region_lookup_value(lookup_name, region_id, column, model=MODEL, term=TERM_ID)
79
78
  return safe_parse_float(value, None)
80
79
 
81
80
 
@@ -34,7 +34,7 @@ REQUIREMENTS = {
34
34
  }
35
35
  LOOKUPS = {
36
36
  "crop": ["isPlantation", "cropGroupingFaostatArea"],
37
- "region-crop-cropGroupingFaostatArea-ch4forestBiomassBurning": "use crop grouping above or default to site.siteType"
37
+ "region-crop-cropGroupingFaostatArea-ch4forestBiomassBurning": ""
38
38
  }
39
39
  RETURNS = {
40
40
  "Emission": [{
@@ -34,7 +34,7 @@ REQUIREMENTS = {
34
34
  }
35
35
  LOOKUPS = {
36
36
  "crop": ["isPlantation", "cropGroupingFaostatArea"],
37
- "region-crop-cropGroupingFaostatArea-co2LandUseChange": "use crop grouping above or default to site.siteType"
37
+ "region-crop-cropGroupingFaostatArea-co2LandUseChange": ""
38
38
  }
39
39
  RETURNS = {
40
40
  "Emission": [{
@@ -34,7 +34,7 @@ REQUIREMENTS = {
34
34
  }
35
35
  LOOKUPS = {
36
36
  "crop": ["isPlantation", "cropGroupingFaostatArea"],
37
- "region-crop-cropGroupingFaostatArea-n2oforestBiomassBurning": "use crop grouping above or default to site.siteType"
37
+ "region-crop-cropGroupingFaostatArea-n2oforestBiomassBurning": ""
38
38
  }
39
39
  RETURNS = {
40
40
  "Emission": [{
@@ -1,9 +1,10 @@
1
1
  from hestia_earth.utils.model import find_primary_product
2
- from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name, extract_grouped_data
2
+ from hestia_earth.utils.lookup import extract_grouped_data
3
3
  from hestia_earth.utils.tools import safe_parse_float
4
4
 
5
- from hestia_earth.models.log import debugMissingLookup, logger
5
+ from hestia_earth.models.log import logger
6
6
  from hestia_earth.models.utils.crop import FAOSTAT_AREA_LOOKUP_COLUMN, get_crop_grouping_faostat_area
7
+ from hestia_earth.models.utils.lookup import get_region_lookup_value
7
8
  from . import MODEL
8
9
 
9
10
 
@@ -18,13 +19,12 @@ def get_emission_factor(term_id: str, cycle: dict, factor: str):
18
19
  MODEL, country_id, product_id, f"'{crop_grouping}'")
19
20
 
20
21
  lookup_name = f"region-crop-{FAOSTAT_AREA_LOOKUP_COLUMN}-{factor}.csv"
21
- lookup = download_lookup(lookup_name)
22
- value = get_table_value(lookup, 'termid', country_id, column_name(crop_grouping)) if crop_grouping else None
23
- debugMissingLookup(lookup_name, 'termid', country_id, crop_grouping, value, model=MODEL, term=term_id)
22
+ value = get_region_lookup_value(
23
+ lookup_name, country_id, crop_grouping, model=MODEL, term=term_id
24
+ ) if crop_grouping else get_region_lookup_value(
25
+ lookup_name, country_id, 'NONE', model=MODEL, term=term_id
26
+ )
24
27
 
25
28
  data = safe_parse_float(value, None)
26
29
  # fallback to site.siteType data if possible
27
- return data if data is not None else safe_parse_float(
28
- extract_grouped_data(get_table_value(lookup, 'termid', country_id, column_name('NONE')), site.get('siteType')),
29
- None
30
- )
30
+ return data if data is not None else safe_parse_float(extract_grouped_data(value, site.get('siteType')), None)
@@ -2,7 +2,7 @@ from functools import reduce
2
2
  from enum import Enum
3
3
  from pydash.objects import merge
4
4
  from hestia_earth.utils.api import download_hestia
5
- from hestia_earth.utils.tools import flatten
5
+ from hestia_earth.utils.tools import flatten, non_empty_list
6
6
 
7
7
  from .log import logger
8
8
  from .utils import CACHE_KEY, cached_value
@@ -30,14 +30,24 @@ _VALUE_AS_PARAM = {
30
30
  }
31
31
 
32
32
 
33
+ def _value_as_param(param_type: ParamType = None): return _VALUE_AS_PARAM.get(param_type, lambda *args: None)
34
+
35
+
33
36
  def _cache_results(results: list, collections: list, index: int):
34
37
  start = index * len(collections)
35
38
  end = start + len(collections)
36
39
  return cache_site_results(results[start:end], collections)
37
40
 
38
41
 
39
- def _run_values(sites: list, param_type: ParamType, rasters: list = [], vectors: list = [], years: list = None):
40
- param_values = list(map(_VALUE_AS_PARAM.get(param_type), sites))
42
+ def _run_values(
43
+ sites: list,
44
+ param_type: ParamType = None,
45
+ rasters: list = [],
46
+ vectors: list = [],
47
+ years: list = None
48
+ ):
49
+ get_param_values = _value_as_param(param_type)
50
+ param_values = non_empty_list(map(get_param_values, sites))
41
51
  # unique list
42
52
  param_values = list(set(param_values)) if param_type == ParamType.GADM_IDS else list({
43
53
  str(v): v for v in param_values
@@ -59,13 +69,13 @@ def _run_values(sites: list, param_type: ParamType, rasters: list = [], vectors:
59
69
  site, area_size = site_values
60
70
 
61
71
  # get real index in values to handle duplicates
62
- param_value = _VALUE_AS_PARAM.get(param_type)([site])
63
- index = param_values.index(param_value)
72
+ param_value = get_param_values([site])
73
+ index = param_values.index(param_value) if param_value is not None else None
64
74
 
65
- cached_data = {
75
+ cached_data = ({
66
76
  **_cache_results(raster_results, rasters, index),
67
77
  **_cache_results(vector_results, vectors, index)
68
- } | ({CACHE_AREA_SIZE: area_size} if area_size is not None else {})
78
+ } if index is not None else {}) | ({CACHE_AREA_SIZE: area_size} if area_size is not None else {})
69
79
  cached_data = merge(cached_value(site, CACHE_GEOSPATIAL_KEY, {}), cached_data)
70
80
  site_cache = merge(
71
81
  site.get(CACHE_KEY, {}),
@@ -96,33 +106,35 @@ def _group_sites(sites: dict, check_has_cache: bool = True):
96
106
  (n, ) + (_should_run(n, area_size=get_region_area_size(n), check_has_cache=check_has_cache)) for n in sites
97
107
  ]
98
108
  # restrict sites based on should_cache result
99
- sites = [(site, area_size) for site, should_cache, area_size in sites if should_cache]
109
+ sites_run = [(site, area_size) for site, should_cache, area_size in sites if should_cache]
110
+ # will only cache area and years
111
+ sites_no_run = [(site, area_size) for site, should_cache, area_size in sites if not should_cache]
100
112
 
101
113
  with_coordinates = [
102
- (site, area_size) for site, area_size in sites if has_coordinates(site)
114
+ (site, area_size) for site, area_size in sites_run if has_coordinates(site)
103
115
  ]
104
116
  with_boundaries = [
105
- (site, area_size) for site, area_size in sites if not has_coordinates(site) and has_boundary(site)
117
+ (site, area_size) for site, area_size in sites_run if not has_coordinates(site) and has_boundary(site)
106
118
  ]
107
119
  with_gadm_ids = [
108
- (site, area_size) for site, area_size in sites if not has_coordinates(site) and not has_boundary(site)
120
+ (site, area_size) for site, area_size in sites_run if not has_coordinates(site) and not has_boundary(site)
109
121
  ]
110
122
 
111
123
  return {
112
124
  ParamType.COORDINATES: with_coordinates,
113
125
  ParamType.BOUNDARIES: with_boundaries,
114
126
  ParamType.GADM_IDS: with_gadm_ids
115
- }
127
+ }, sites_no_run
116
128
 
117
129
 
118
130
  def _run(sites: list, years: list = [], years_only: bool = False):
119
131
  rasters = list_rasters(years=years, years_only=years_only)
120
132
  vectors = [] if years_only else list_vectors(sites)
121
- filtered_data = _group_sites(sites, not years_only)
133
+ filtered_data, sites_no_run = _group_sites(sites, not years_only)
122
134
  return flatten([
123
135
  _run_values(filtered_data.get(param_type), param_type, rasters, vectors, years)
124
136
  for param_type in [e for e in ParamType] if len(filtered_data.get(param_type)) > 0
125
- ])
137
+ ] + _run_values(sites_no_run, years=years))
126
138
 
127
139
 
128
140
  def run(sites: list, years: list = None):
@@ -53,8 +53,8 @@ RETURNS = {
53
53
  }
54
54
  LOOKUPS = {
55
55
  "@doc": "Different lookup files are used depending on the situation",
56
- "ecoregion-siteType-LandOccupationChaudaryBrooks2018CF": "using `ecoregion`",
57
- "region-siteType-LandOccupationChaudaryBrooks2018CF": "using `country`"
56
+ "ecoregion-siteType-LandOccupationChaudaryBrooks2018CF": "",
57
+ "region-siteType-LandOccupationChaudaryBrooks2018CF": ""
58
58
  }
59
59
  TERM_ID = 'damageToTerrestrialEcosystemsLandOccupation'
60
60
  LOOKUP_SUFFIX = 'LandOccupationChaudaryBrooks2018CF'
@@ -41,8 +41,8 @@ RETURNS = {
41
41
  }
42
42
  LOOKUPS = {
43
43
  "@doc": "Different lookup files are used depending on the situation",
44
- "ecoregion-siteType-LandTransformationChaudaryBrooks2018CF": "using `ecoregion`",
45
- "region-siteType-LandTransformationChaudaryBrooks2018CF": "using `country`"
44
+ "ecoregion-siteType-LandTransformationChaudaryBrooks2018CF": "",
45
+ "region-siteType-LandTransformationChaudaryBrooks2018CF": ""
46
46
  }
47
47
  TERM_ID = 'damageToTerrestrialEcosystemsLandTransformation'
48
48
 
@@ -3,14 +3,14 @@ from hestia_earth.utils.tools import safe_parse_float
3
3
 
4
4
  from hestia_earth.models.log import debugMissingLookup, logRequirements
5
5
  from hestia_earth.models.utils.impact_assessment import get_site, get_country_id
6
+ from hestia_earth.models.utils.lookup import get_region_lookup_value
6
7
  from . import MODEL
7
8
 
8
9
 
9
- def _lookup_value(term_id: str, lookup_name: str, col_match: str, col_val: str, column: str, group_key: str = None):
10
- value = get_table_value(download_lookup(f"{lookup_name}.csv"), col_match, col_val, column_name(column))
11
- value = extract_grouped_data(value, group_key) if group_key else value
12
- debugMissingLookup(f"{lookup_name}.csv", col_match, col_val, column, value, model=MODEL, term=term_id)
13
- return safe_parse_float(value)
10
+ def _lookup_value(term_id: str, lookup_name: str, col_match: str, col_val: str, column: str):
11
+ value = get_table_value(download_lookup(lookup_name), col_match, col_val, column_name(column))
12
+ debugMissingLookup(lookup_name, col_match, col_val, column, value, model=MODEL, term=term_id)
13
+ return value
14
14
 
15
15
 
16
16
  def get_region_factor(term_id: str, impact_assessment: dict, lookup_suffix: str, group_key: str = None):
@@ -20,12 +20,17 @@ def get_region_factor(term_id: str, impact_assessment: dict, lookup_suffix: str,
20
20
  site_type = site.get('siteType')
21
21
 
22
22
  lookup_prefix = 'ecoregion' if ecoregion else 'region' if country_id else None
23
- col_name = 'ecoregion' if ecoregion else 'termid'
24
- col_val = ecoregion or country_id
23
+ lookup_name = f"{lookup_prefix}-siteType-{lookup_suffix}.csv"
25
24
 
26
25
  logRequirements(impact_assessment, model=MODEL, term=term_id,
27
26
  site_type=site_type,
28
27
  ecoregion=ecoregion,
29
28
  country_id=country_id)
30
29
 
31
- return _lookup_value(term_id, f"{lookup_prefix}-siteType-{lookup_suffix}", col_name, col_val, site_type, group_key)
30
+ value = get_region_lookup_value(
31
+ lookup_name, country_id, site_type, model=MODEL, term=term_id
32
+ ) if lookup_prefix == 'region' else _lookup_value(
33
+ term_id, lookup_name, 'ecoregion', ecoregion, site_type
34
+ )
35
+ value = extract_grouped_data(value, group_key) if group_key else value
36
+ return safe_parse_float(value)
@@ -17,7 +17,7 @@ Source: [JRC Technical reports Suggestions for updating the Product Environmenta
17
17
  Source: [Differences between EF model versions](https://eplca.jrc.ec.europa.eu/EFVersioning.html)
18
18
  """ # noqa: E501
19
19
  from itertools import chain
20
- from hestia_earth.utils.lookup import download_lookup, column_name
20
+ from hestia_earth.utils.lookup import download_lookup, column_name, find_term_ids_by
21
21
  from hestia_earth.utils.tools import list_sum, flatten
22
22
 
23
23
  from hestia_earth.models.log import logShouldRun, logRequirements, log_as_table
@@ -66,8 +66,7 @@ def get_all_non_renewable_terms(lookup_file_name: str, column: str) -> list:
66
66
  returns all non renewable term ids in lookup files like `electricity.csv` or `fuel.csv`
67
67
  """
68
68
  lookup = download_lookup(lookup_file_name)
69
- results = lookup[lookup[column_name(column)] == True]["termid"] # noqa: E712
70
- return list(map(str, results))
69
+ return find_term_ids_by(lookup, column_name(column), True)
71
70
 
72
71
 
73
72
  def _valid_resource_indicator(resource: dict) -> bool:
@@ -95,7 +95,7 @@ def _should_run(impact_assessment: dict) -> tuple[bool, list]:
95
95
  "indicator-input-is-valid": _valid_input(input),
96
96
  "value": _node_value(resource_indicator),
97
97
  "coefficient": get_table_value(
98
- array=download_lookup(filename=f"{input.get('termType')}.csv"),
98
+ lookup=download_lookup(filename=f"{input.get('termType')}.csv"),
99
99
  col_match='termid',
100
100
  col_match_with=input.get('@id'),
101
101
  col_val=column_name(LOOKUPS.get(input.get('termType'), ''))) if input else None
@@ -1183,6 +1183,21 @@
1183
1183
  },
1184
1184
  "stage": 2
1185
1185
  },
1186
+ {
1187
+ "key": "emissions",
1188
+ "model": "ipcc2019",
1189
+ "value": "nonCo2EmissionsToAirNaturalVegetationBurning",
1190
+ "runStrategy": "always",
1191
+ "runArgs": {
1192
+ "runNonMeasured": true,
1193
+ "runNonAddedTerm": true
1194
+ },
1195
+ "mergeStrategy": "list",
1196
+ "mergeArgs": {
1197
+ "replaceThreshold": ["value", 0.01]
1198
+ },
1199
+ "stage": 2
1200
+ },
1186
1201
  {
1187
1202
  "key": "emissions",
1188
1203
  "model": "schmidt2007",
@@ -865,7 +865,20 @@
865
865
  },
866
866
  "stage": 1
867
867
  },
868
-
868
+ {
869
+ "key": "impacts",
870
+ "model": "environmentalFootprintV3-1",
871
+ "value": "photochemicalOzoneCreationPotentialHumanHealthNmvocEq",
872
+ "runStrategy": "always",
873
+ "mergeStrategy": "list",
874
+ "mergeArgs": {
875
+ "replaceThreshold": [
876
+ "value",
877
+ 0.01
878
+ ]
879
+ },
880
+ "stage": 1
881
+ },
869
882
  {
870
883
  "key": "impacts",
871
884
  "model": "environmentalFootprintV3-1",
@@ -340,6 +340,14 @@
340
340
  "runStrategy": "add_blank_node_if_missing",
341
341
  "mergeStrategy": "list",
342
342
  "stage": 1
343
+ },
344
+ {
345
+ "key": "measurements",
346
+ "model": "geospatialDatabase",
347
+ "value": "altitude",
348
+ "runStrategy": "add_blank_node_if_missing",
349
+ "mergeStrategy": "list",
350
+ "stage": 1
343
351
  }
344
352
  ],
345
353
  [
@@ -4,12 +4,12 @@ Excreta (kg)
4
4
  This model calculates the amount of excreta in `kg` based on the amount of excreta in `kg N` or `kg Vs`.
5
5
  """
6
6
  from hestia_earth.schema import NodeType, TermTermType
7
- from hestia_earth.utils.api import download_hestia
8
7
  from hestia_earth.utils.model import filter_list_term_type, find_term_match
9
8
  from hestia_earth.utils.tools import non_empty_list, list_sum
10
9
 
11
10
  from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
12
11
  from hestia_earth.models.utils import get_kg_term_id, get_kg_N_term_id, get_kg_VS_term_id
12
+ from hestia_earth.models.utils.term import download_term
13
13
  from hestia_earth.models.utils.constant import Units
14
14
  from hestia_earth.models.utils.product import _new_product, convert_product_to_unit
15
15
  from . import MODEL
@@ -68,7 +68,7 @@ def _run_product(cycle: dict, product_term_id: str):
68
68
  ]
69
69
 
70
70
  # convert to 1kg first, then apply ratio to current value
71
- term = download_hestia(product_term_id)
71
+ term = download_term(product_term_id, TermTermType.EXCRETA)
72
72
  product = {
73
73
  'term': term,
74
74
  'value': [1]
@@ -5,7 +5,7 @@ This model gap-fills depreciated amount per Cycle from Site Infrastructure node.
5
5
  """
6
6
  from typing import Union
7
7
  from hestia_earth.schema import TermTermType
8
- from hestia_earth.utils.lookup import download_lookup
8
+ from hestia_earth.utils.lookup import download_lookup, lookup_term_ids
9
9
  from hestia_earth.utils.tools import to_precision, flatten, list_sum
10
10
  from hestia_earth.utils.model import filter_list_term_type
11
11
 
@@ -100,7 +100,8 @@ def _run_input(cycle: dict, input_node: dict) -> dict:
100
100
 
101
101
  def _has_depreciated_term(term: dict):
102
102
  lookup = download_lookup(f"{term.get('termType')}.csv")
103
- return term.get('@id') + _ID_SUFFIX in list(lookup.termid)
103
+ term_ids = lookup_term_ids(lookup)
104
+ return term.get('@id') + _ID_SUFFIX in term_ids
104
105
 
105
106
 
106
107
  def _should_run_input(cycle: dict, input_node: dict) -> bool:
@@ -1,9 +1,9 @@
1
- from hestia_earth.schema import SiteSiteType
2
- from hestia_earth.utils.api import download_hestia
1
+ from hestia_earth.schema import SiteSiteType, TermTermType
3
2
  from hestia_earth.utils.model import linked_node
4
3
 
5
4
  from hestia_earth.models.log import logRequirements, logShouldRun
6
5
  from hestia_earth.models.utils.practice import _new_practice
6
+ from hestia_earth.models.utils.term import download_term
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -27,7 +27,7 @@ KEY_TERM_ID = 'genericGrassPlant'
27
27
  def _practice():
28
28
  node = _new_practice(TERM_ID)
29
29
  node['value'] = [100]
30
- node['key'] = linked_node(download_hestia(KEY_TERM_ID))
30
+ node['key'] = linked_node(download_term(KEY_TERM_ID, TermTermType.LANDCOVER))
31
31
  return node
32
32
 
33
33
 
@@ -15,7 +15,7 @@ REQUIREMENTS = {
15
15
  }
16
16
  }
17
17
  LOOKUPS = {
18
- "excretaManagement": "EF_NON-N"
18
+ "excretaManagement": "EF_NO-N"
19
19
  }
20
20
  RETURNS = {
21
21
  "Emission": [{
@@ -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:
@@ -8,14 +8,15 @@ summed to obtain the EF single overall score. The number and the name of the imp
8
8
  in EF3.0 and EF3.1.
9
9
  """
10
10
  from typing import List, Optional, Tuple
11
+
11
12
  from hestia_earth.schema import TermTermType
12
13
  from hestia_earth.utils.model import filter_list_term_type
13
14
  from hestia_earth.utils.tools import list_sum
14
15
 
15
- from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
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
16
18
  from hestia_earth.models.utils.indicator import _new_indicator
17
19
  from hestia_earth.models.utils.lookup import _node_value
18
- from hestia_earth.models.utils.blank_node import get_lookup_value
19
20
  from . import MODEL
20
21
 
21
22
  REQUIREMENTS = {
@@ -71,16 +72,30 @@ def _get_pef_method_model(term: dict) -> List[str]:
71
72
  return entries.split(";")
72
73
 
73
74
 
74
- def _normalise(indicator: dict) -> Optional[float]:
75
- return (
76
- _node_value(indicator) / _get_factor(indicator.get('term', {}), normalisation_column)
77
- ) if (_node_value(indicator) is not None and _get_factor(indicator.get('term', {}), normalisation_column)) else None
78
-
79
-
80
- def _weighted_normalise(indicator: dict) -> Optional[float]:
81
- return (
82
- _normalise(indicator) * (_get_factor(indicator.get('term', {}), weighing_column) / 100)
83
- ) if (_normalise(indicator) is not None and _get_factor(indicator.get('term', {}), weighing_column)) else None
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
+ }
84
99
 
85
100
 
86
101
  def _indicator(value: float) -> dict:
@@ -90,7 +105,7 @@ def _indicator(value: float) -> dict:
90
105
 
91
106
 
92
107
  def _run(indicators: List[dict]):
93
- 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]))
94
109
 
95
110
 
96
111
  def _valid_indicator(indicator: Optional[dict]) -> bool:
@@ -104,20 +119,14 @@ def _should_run(impact_assessment: dict) -> Tuple[bool, list[dict]]:
104
119
  filter_list_term_type(impact_assessment.get('impacts', []), TermTermType.CHARACTERISEDINDICATOR)
105
120
  if _is_a_PEF_indicator(indicator)
106
121
  ]
107
-
108
122
  has_pef_indicators = bool(indicators)
109
123
 
110
124
  processed_indicators = [{
111
- "indicator": indicator,
125
+ "indicator": indicator['term']['@id'],
112
126
  "valid-indicator": _valid_indicator(indicator),
113
127
  "one-indicator-for-category": sum(1 for i in indicators if i['term']['@id'] == indicator['term']['@id']) == 1,
114
128
  "indicator-pef-category": indicator.get('term', {}).get('@id'),
115
- "value": _node_value(indicator),
116
- "normalised": _normalise(indicator),
117
- "normalisation-used": _get_factor(indicator.get('term', {}), normalisation_column),
118
- "weighted-normalised": _weighted_normalise(indicator),
119
- "weighting-used": _get_factor(indicator.get('term', {}), weighing_column),
120
- } for indicator in indicators]
129
+ } | _indicator_factors(impact_assessment, indicator) for indicator in indicators]
121
130
 
122
131
  no_duplicate_indicators = all([indicator['one-indicator-for-category'] for indicator in processed_indicators])
123
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": {