hestia-earth-models 0.69.1__py3-none-any.whl → 0.70.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 (219) hide show
  1. hestia_earth/models/aware/scarcityWeightedWaterUse.py +8 -16
  2. hestia_earth/models/cache_sites.py +3 -2
  3. hestia_earth/models/cml2001Baseline/abioticResourceDepletionFossilFuels.py +2 -1
  4. hestia_earth/models/cml2001Baseline/abioticResourceDepletionMineralsAndMetals.py +3 -2
  5. hestia_earth/models/config/Cycle.json +82 -60
  6. hestia_earth/models/config/ImpactAssessment.json +12 -4
  7. hestia_earth/models/config/Site.json +33 -22
  8. hestia_earth/models/cycle/animal/input/hestiaAggregatedData.py +1 -1
  9. hestia_earth/models/cycle/animal/input/properties.py +1 -1
  10. hestia_earth/models/cycle/cycleDuration.py +2 -2
  11. hestia_earth/models/cycle/input/hestiaAggregatedData.py +12 -14
  12. hestia_earth/models/cycle/input/properties.py +1 -1
  13. hestia_earth/models/cycle/siteDuration.py +3 -3
  14. hestia_earth/models/cycle/transformation.py +1 -1
  15. hestia_earth/models/cycle/utils.py +0 -6
  16. hestia_earth/models/data/ecoinventV3/__init__.py +15 -13
  17. hestia_earth/models/ecoalimV9/__init__.py +13 -0
  18. hestia_earth/models/ecoalimV9/cycle.py +128 -0
  19. hestia_earth/models/ecoalimV9/impact_assessment.py +125 -0
  20. hestia_earth/models/ecoalimV9/utils.py +31 -0
  21. hestia_earth/models/ecoinventV3/__init__.py +6 -14
  22. hestia_earth/models/ecoinventV3/utils.py +1 -29
  23. hestia_earth/models/ecoinventV3AndEmberClimate/__init__.py +8 -2
  24. hestia_earth/models/emissionNotRelevant/__init__.py +33 -8
  25. hestia_earth/models/frischknechtEtAl2000/ionisingRadiationKbqU235Eq.py +1 -1
  26. hestia_earth/models/geospatialDatabase/croppingIntensity.py +4 -4
  27. hestia_earth/models/geospatialDatabase/longFallowRatio.py +4 -4
  28. hestia_earth/models/geospatialDatabase/region.py +3 -2
  29. hestia_earth/models/geospatialDatabase/utils.py +6 -5
  30. hestia_earth/models/haversineFormula/transport/distance.py +5 -4
  31. hestia_earth/models/{koble2014 → hestia}/aboveGroundCropResidue.py +4 -5
  32. hestia_earth/models/{cycle → hestia}/aboveGroundCropResidueTotal.py +2 -2
  33. hestia_earth/models/{site → hestia}/brackishWater.py +1 -1
  34. hestia_earth/models/{site → hestia}/cationExchangeCapacityPerKgSoil.py +1 -1
  35. hestia_earth/models/{cycle → hestia}/coldCarcassWeightPerHead.py +1 -1
  36. hestia_earth/models/{cycle → hestia}/coldDressedCarcassWeightPerHead.py +1 -1
  37. hestia_earth/models/{cycle → hestia}/concentrateFeed.py +1 -1
  38. hestia_earth/models/{cycle → hestia}/cropResidueManagement.py +1 -1
  39. hestia_earth/models/{cycle → hestia}/croppingIntensity.py +1 -1
  40. hestia_earth/models/{cycle → hestia}/energyContentLowerHeatingValue.py +2 -2
  41. hestia_earth/models/{cycle → hestia}/excretaKgMass.py +7 -2
  42. hestia_earth/models/{cycle → hestia}/excretaKgN.py +1 -1
  43. hestia_earth/models/{cycle → hestia}/excretaKgVs.py +1 -1
  44. hestia_earth/models/{cycle → hestia}/feedConversionRatio/__init__.py +1 -1
  45. hestia_earth/models/{site → hestia}/flowingWater.py +1 -1
  46. hestia_earth/models/{site → hestia}/freshWater.py +1 -1
  47. hestia_earth/models/{cycle → hestia}/inorganicFertiliser.py +1 -1
  48. hestia_earth/models/{cycle → hestia}/irrigatedTypeUnspecified.py +14 -19
  49. hestia_earth/models/hestia/landCover.py +31 -27
  50. hestia_earth/models/hestia/landTransformation100YearAverageDuringCycle.py +2 -1
  51. hestia_earth/models/hestia/landTransformation20YearAverageDuringCycle.py +2 -1
  52. hestia_earth/models/{cycle → hestia}/liveAnimal.py +1 -1
  53. hestia_earth/models/{cycle → hestia}/longFallowRatio.py +1 -1
  54. hestia_earth/models/{site → hestia}/management.py +5 -3
  55. hestia_earth/models/{cycle → hestia}/materialAndSubstrate.py +1 -1
  56. hestia_earth/models/{cycle → hestia}/milkYield.py +1 -1
  57. hestia_earth/models/{site → hestia}/netPrimaryProduction.py +1 -1
  58. hestia_earth/models/{site → hestia}/organicCarbonPerHa.py +1 -1
  59. hestia_earth/models/{cycle → hestia}/pastureGrass.py +1 -1
  60. hestia_earth/models/{cycle → hestia}/pastureSystem.py +1 -1
  61. hestia_earth/models/{site → hestia}/potentialEvapotranspirationAnnual.py +3 -3
  62. hestia_earth/models/{site → hestia}/potentialEvapotranspirationMonthly.py +3 -3
  63. hestia_earth/models/{site → hestia}/precipitationAnnual.py +3 -3
  64. hestia_earth/models/{site → hestia}/precipitationMonthly.py +3 -3
  65. hestia_earth/models/{site → hestia}/rainfallAnnual.py +3 -3
  66. hestia_earth/models/{site → hestia}/rainfallMonthly.py +3 -3
  67. hestia_earth/models/{cycle → hestia}/readyToCookWeightPerHead.py +1 -1
  68. hestia_earth/models/{cycle → hestia}/residueBurnt.py +1 -1
  69. hestia_earth/models/{cycle → hestia}/residueIncorporated.py +1 -1
  70. hestia_earth/models/{cycle → hestia}/residueLeftOnField.py +1 -1
  71. hestia_earth/models/hestia/residueRemoved.py +65 -13
  72. hestia_earth/models/{site → hestia}/salineWater.py +1 -1
  73. hestia_earth/models/hestia/seed_emissions.py +1 -1
  74. hestia_earth/models/{site → hestia}/soilMeasurement.py +1 -1
  75. hestia_earth/models/{cycle → hestia}/stockingDensityAnimalHousingAverage.py +1 -1
  76. hestia_earth/models/{site → hestia}/temperatureAnnual.py +3 -3
  77. hestia_earth/models/{site → hestia}/temperatureMonthly.py +3 -3
  78. hestia_earth/models/{site → hestia}/totalNitrogenPerKgSoil.py +1 -1
  79. hestia_earth/models/{cycle → hestia}/unknownPreSeasonWaterRegime.py +1 -1
  80. hestia_earth/models/hestia/utils.py +93 -0
  81. hestia_earth/models/{site → hestia}/waterDepth.py +1 -1
  82. hestia_earth/models/hestia/waterSalinity.py +78 -0
  83. hestia_earth/models/impact_assessment/emissions.py +1 -1
  84. hestia_earth/models/impact_assessment/product/economicValueShare.py +1 -1
  85. hestia_earth/models/impact_assessment/product/value.py +1 -1
  86. hestia_earth/models/ipcc2019/aboveGroundBiomass.py +1 -1
  87. hestia_earth/models/ipcc2019/animal/fatContent.py +2 -2
  88. hestia_earth/models/ipcc2019/animal/milkYieldPerAnimal.py +2 -2
  89. hestia_earth/models/ipcc2019/animal/trueProteinContent.py +2 -2
  90. hestia_earth/models/ipcc2019/belowGroundBiomass.py +1 -1
  91. hestia_earth/models/ipcc2019/biomass_utils.py +2 -4
  92. hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +7 -2
  93. hestia_earth/models/ipcc2019/ch4ToAirFloodedRice.py +163 -78
  94. hestia_earth/models/ipcc2019/co2ToAirAboveGroundBiomassStockChange.py +1 -0
  95. hestia_earth/models/ipcc2019/co2ToAirBelowGroundBiomassStockChange.py +2 -1
  96. hestia_earth/models/ipcc2019/co2ToAirCarbonStockChange_utils.py +31 -20
  97. hestia_earth/models/ipcc2019/co2ToAirSoilOrganicCarbonStockChange.py +2 -1
  98. hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +16 -9
  99. hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +36 -47
  100. hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_1.py +94 -9
  101. hestia_earth/models/ipcc2019/organicCarbonPerHa_tier_2.py +167 -13
  102. hestia_earth/models/ipcc2019/organicCarbonPerHa_utils.py +7 -5
  103. hestia_earth/models/koble2014/cropResidueManagement.py +1 -1
  104. hestia_earth/models/koble2014/residueBurnt.py +1 -1
  105. hestia_earth/models/koble2014/residueRemoved.py +1 -1
  106. hestia_earth/models/koble2014/utils.py +3 -3
  107. hestia_earth/models/mocking/search-results.json +1263 -1229
  108. hestia_earth/models/pooreNemecek2018/excretaKgN.py +1 -1
  109. hestia_earth/models/pooreNemecek2018/freshwaterWithdrawalsDuringCycle.py +1 -1
  110. hestia_earth/models/pooreNemecek2018/utils.py +12 -3
  111. hestia_earth/models/schmidt2007/ch4ToAirWasteTreatment.py +1 -6
  112. hestia_earth/models/schmidt2007/h2SToAirWasteTreatment.py +1 -6
  113. hestia_earth/models/schmidt2007/n2OToAirWasteTreatmentDirect.py +1 -6
  114. hestia_earth/models/schmidt2007/nh3ToAirWasteTreatment.py +1 -6
  115. hestia_earth/models/site/pre_checks/country.py +4 -2
  116. hestia_earth/models/transformation/input/excreta.py +1 -1
  117. hestia_earth/models/utils/aggregated.py +12 -15
  118. hestia_earth/models/utils/background_emissions.py +52 -0
  119. hestia_earth/models/utils/blank_node.py +24 -6
  120. hestia_earth/models/utils/impact_assessment.py +26 -17
  121. hestia_earth/models/utils/lookup.py +48 -39
  122. hestia_earth/models/utils/measurement.py +3 -3
  123. hestia_earth/models/utils/product.py +1 -1
  124. hestia_earth/models/utils/source.py +2 -1
  125. hestia_earth/models/utils/term.py +26 -1
  126. hestia_earth/models/version.py +1 -1
  127. {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/METADATA +2 -2
  128. {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/RECORD +214 -209
  129. tests/models/aware/test_scarcityWeightedWaterUse.py +1 -12
  130. tests/models/cycle/input/test_hestiaAggregatedData.py +18 -16
  131. tests/models/ecoalimV9/__init__.py +0 -0
  132. tests/models/ecoalimV9/test_cycle.py +21 -0
  133. tests/models/ecoalimV9/test_impact_assessment.py +24 -0
  134. tests/models/environmentalFootprintV3_1/test_scarcityWeightedWaterUse.py +4 -2
  135. tests/models/geospatialDatabase/test_region.py +1 -1
  136. tests/models/geospatialDatabase/test_utils.py +1 -1
  137. tests/models/haversineFormula/transport/test_distance.py +2 -2
  138. tests/models/{koble2014 → hestia}/test_aboveGroundCropResidue.py +3 -3
  139. tests/models/{cycle → hestia}/test_aboveGroundCropResidueTotal.py +1 -1
  140. tests/models/{site → hestia}/test_brackishWater.py +1 -1
  141. tests/models/{site → hestia}/test_cationExchangeCapacityPerKgSoil.py +1 -1
  142. tests/models/{cycle → hestia}/test_coldCarcassWeightPerHead.py +1 -1
  143. tests/models/{cycle → hestia}/test_coldDressedCarcassWeightPerHead.py +1 -1
  144. tests/models/{cycle → hestia}/test_concentrateFeed.py +1 -1
  145. tests/models/{cycle → hestia}/test_cropResidueManagement.py +1 -1
  146. tests/models/{cycle → hestia}/test_croppingIntensity.py +1 -1
  147. tests/models/{cycle → hestia}/test_energyContentLowerHeatingValue.py +5 -3
  148. tests/models/{cycle → hestia}/test_excretaKgMass.py +1 -1
  149. tests/models/{cycle → hestia}/test_excretaKgN.py +1 -1
  150. tests/models/{cycle → hestia}/test_excretaKgVs.py +1 -1
  151. tests/models/{cycle → hestia}/test_feedConversionRatio.py +1 -1
  152. tests/models/{site → hestia}/test_flowingWater.py +1 -1
  153. tests/models/{site → hestia}/test_freshWater.py +1 -1
  154. tests/models/{cycle → hestia}/test_inorganicFertiliser.py +1 -1
  155. tests/models/{cycle → hestia}/test_irrigatedTypeUnspecified.py +2 -5
  156. tests/models/hestia/test_landCover.py +4 -34
  157. tests/models/{cycle → hestia}/test_liveAnimal.py +1 -1
  158. tests/models/{cycle → hestia}/test_longFallowRatio.py +1 -1
  159. tests/models/{site → hestia}/test_management.py +1 -1
  160. tests/models/{cycle → hestia}/test_materialsAndSubstrate.py +1 -1
  161. tests/models/{cycle → hestia}/test_milkYield.py +1 -1
  162. tests/models/{site → hestia}/test_netPrimaryProduction.py +1 -1
  163. tests/models/{site → hestia}/test_organicCarbonPerHa.py +1 -1
  164. tests/models/{site → hestia}/test_organicCarbonPerKgSoil.py +1 -1
  165. tests/models/{site → hestia}/test_organicCarbonPerM3Soil.py +1 -1
  166. tests/models/{site → hestia}/test_organicMatterPerKgSoil.py +1 -1
  167. tests/models/{site → hestia}/test_organicMatterPerM3Soil.py +1 -1
  168. tests/models/{cycle → hestia}/test_pastureGrass.py +1 -1
  169. tests/models/{cycle → hestia}/test_pastureSystem.py +1 -1
  170. tests/models/{site → hestia}/test_potentialEvapotranspirationAnnual.py +1 -1
  171. tests/models/{site → hestia}/test_potentialEvapotranspirationMonthly.py +1 -1
  172. tests/models/{site → hestia}/test_precipitationAnnual.py +1 -1
  173. tests/models/{site → hestia}/test_precipitationMonthly.py +1 -1
  174. tests/models/{site → hestia}/test_rainfallAnnual.py +1 -1
  175. tests/models/{site → hestia}/test_rainfallMonthly.py +1 -1
  176. tests/models/{cycle → hestia}/test_readyToCookWeightPerHead.py +1 -1
  177. tests/models/{cycle → hestia}/test_residueBurnt.py +1 -1
  178. tests/models/{cycle → hestia}/test_residueIncorporated.py +1 -1
  179. tests/models/{cycle → hestia}/test_residueLeftOnField.py +1 -1
  180. tests/models/hestia/test_residueRemoved.py +15 -3
  181. tests/models/{site → hestia}/test_salineWater.py +1 -1
  182. tests/models/{site → hestia}/test_soilMeasurement.py +2 -2
  183. tests/models/{cycle → hestia}/test_stockingDensityAnimalHousingAverage.py +1 -1
  184. tests/models/{site → hestia}/test_temperatureAnnual.py +1 -1
  185. tests/models/{site → hestia}/test_temperatureMonthly.py +1 -1
  186. tests/models/{site → hestia}/test_totalNitrogenPerKgSoil.py +1 -1
  187. tests/models/{cycle → hestia}/test_unknownPreSeasonWaterRegime.py +1 -1
  188. tests/models/{site → hestia}/test_waterDepth.py +1 -1
  189. tests/models/hestia/test_waterSalinity.py +26 -0
  190. tests/models/ipcc2019/test_ch4ToAirEntericFermentation.py +11 -0
  191. tests/models/ipcc2019/test_ch4ToAirFloodedRice.py +10 -42
  192. tests/models/ipcc2019/test_co2ToAirSoilOrganicCarbonStockChange.py +2 -1
  193. tests/models/ipcc2019/test_nonCo2EmissionsToAirNaturalVegetationBurning.py +22 -8
  194. tests/models/ipcc2019/test_organicCarbonPerHa.py +4 -2
  195. tests/models/pooreNemecek2018/test_landOccupationDuringCycle.py +3 -0
  196. tests/models/site/pre_checks/test_country.py +4 -3
  197. tests/models/test_ecoinventV3.py +2 -2
  198. tests/models/test_ecoinventV3AndEmberClimate.py +2 -2
  199. tests/models/test_emissionNotRelevant.py +0 -8
  200. tests/models/utils/test_measurement.py +1 -1
  201. tests/models/utils/test_source.py +15 -5
  202. tests/orchestrator/test_models.py +1 -0
  203. hestia_earth/models/cycle/residueRemoved.py +0 -54
  204. hestia_earth/models/hestia/nh3ToSurfaceWaterAquacultureSystems.py +0 -64
  205. hestia_earth/models/site/utils.py +0 -93
  206. tests/models/cycle/test_residueRemoved.py +0 -37
  207. tests/models/hestia/test_nh3ToSurfaceWaterAquacultureSystems.py +0 -51
  208. /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioCarbon.py +0 -0
  209. /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioDryMatter.py +0 -0
  210. /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioEnergy.py +0 -0
  211. /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioFedWeight.py +0 -0
  212. /hestia_earth/models/{cycle → hestia}/feedConversionRatio/feedConversionRatioNitrogen.py +0 -0
  213. /hestia_earth/models/{site → hestia}/organicCarbonPerKgSoil.py +0 -0
  214. /hestia_earth/models/{site → hestia}/organicCarbonPerM3Soil.py +0 -0
  215. /hestia_earth/models/{site → hestia}/organicMatterPerKgSoil.py +0 -0
  216. /hestia_earth/models/{site → hestia}/organicMatterPerM3Soil.py +0 -0
  217. {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/LICENSE +0 -0
  218. {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/WHEEL +0 -0
  219. {hestia_earth_models-0.69.1.dist-info → hestia_earth_models-0.70.1.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,11 @@
1
- from hestia_earth.schema import NodeType, EmissionMethodTier
1
+ from hestia_earth.schema import NodeType, EmissionMethodTier, TermTermType
2
+ from hestia_earth.utils.lookup import download_lookup, lookup_term_ids, lookup_columns, column_name
2
3
  from hestia_earth.utils.lookup_utils import is_in_system_boundary
4
+ from hestia_earth.utils.tools import flatten
3
5
 
4
6
  from hestia_earth.models.log import logRequirements, logShouldRun
5
7
  from hestia_earth.models.utils.emission import _new_emission
6
- from hestia_earth.models.utils.blank_node import _run_required
7
- from hestia_earth.models.utils.term import get_all_emission_terms
8
+ from hestia_earth.models.utils.blank_node import _run_required, _run_model_required
8
9
 
9
10
  REQUIREMENTS = {
10
11
  "Cycle": {
@@ -18,7 +19,17 @@ RETURNS = {
18
19
  }]
19
20
  }
20
21
  LOOKUPS = {
21
- "emission": "inHestiaDefaultSystemBoundary"
22
+ "emission": [
23
+ "term.id",
24
+ "inHestiaDefaultSystemBoundary",
25
+ "inputTermTypesAllowed",
26
+ "productTermIdsAllowed",
27
+ "productTermTypesAllowed",
28
+ "siteTypesAllowed",
29
+ "typesAllowed"
30
+ ],
31
+ "emission-model-productTermIdsAllowed": "",
32
+ "emission-model-siteTypesAllowed": ""
22
33
  }
23
34
  MODEL = 'emissionNotRelevant'
24
35
  TIER = EmissionMethodTier.NOT_RELEVANT.value
@@ -31,9 +42,22 @@ def _emission(term_id: str):
31
42
  return emission
32
43
 
33
44
 
34
- def _should_run_emission(cycle: dict):
45
+ def _emission_ids():
46
+ return lookup_term_ids(download_lookup(f"{TermTermType.EMISSION.value}.csv"))
47
+
48
+
49
+ def _model_ids(lookup_suffix: str):
50
+ return [
51
+ col for col in lookup_columns(download_lookup(f"emission-model-{lookup_suffix}.csv"))
52
+ if col != column_name('term.id')
53
+ ]
54
+
55
+
56
+ def _should_run_emission(cycle: dict, model_ids: list):
35
57
  def run(term_id: str):
36
- is_not_relevant = not _run_required(MODEL, term_id, cycle)
58
+ is_not_relevant = not _run_required(MODEL, term_id, cycle) or any([
59
+ not _run_model_required(model_id, term_id, cycle, skip_logs=True) for model_id in model_ids
60
+ ])
37
61
  in_system_boundary = is_in_system_boundary(term_id)
38
62
 
39
63
  should_run = all([is_not_relevant, in_system_boundary])
@@ -49,8 +73,9 @@ def _should_run_emission(cycle: dict):
49
73
 
50
74
 
51
75
  def _run(cycle: dict):
52
- emissions = get_all_emission_terms()
53
- term_ids = list(filter(_should_run_emission(cycle), emissions))
76
+ emissions = _emission_ids()
77
+ model_ids = list(set(flatten(map(_model_ids, ['productTermIdsAllowed', 'siteTypesAllowed']))))
78
+ term_ids = list(filter(_should_run_emission(cycle, model_ids), emissions))
54
79
  return list(map(_emission, term_ids))
55
80
 
56
81
 
@@ -18,7 +18,7 @@ REQUIREMENTS = {
18
18
  "ionisingCompoundsToWaterInputsProduction",
19
19
  "ionisingCompoundsToSaltwaterInputsProduction"
20
20
  ],
21
- "inputs": {"@type": "Term", "term.termType": "waste", "term.units": "kg"}
21
+ "inputs": [{"@type": "Term", "term.termType": "waste", "term.units": "kg"}]
22
22
  }]
23
23
  }
24
24
  }
@@ -14,8 +14,8 @@ REQUIREMENTS = {
14
14
  "site": {
15
15
  "@type": "Site",
16
16
  "or": [
17
- {"region": {"@type": "Term"}},
18
- {"country": {"@type": "Term"}}
17
+ {"region": {"@type": "Term", "termType": "region"}},
18
+ {"country": {"@type": "Term", "termType": "region"}}
19
19
  ]
20
20
  },
21
21
  "optional": {
@@ -23,8 +23,8 @@ REQUIREMENTS = {
23
23
  {
24
24
  "@type": "Site",
25
25
  "or": [
26
- {"region": {"@type": "Term"}},
27
- {"country": {"@type": "Term"}}
26
+ {"region": {"@type": "Term", "termType": "region"}},
27
+ {"country": {"@type": "Term", "termType": "region"}}
28
28
  ]
29
29
  }
30
30
  ]
@@ -14,8 +14,8 @@ REQUIREMENTS = {
14
14
  "site": {
15
15
  "@type": "Site",
16
16
  "or": [
17
- {"region": {"@type": "Term"}},
18
- {"country": {"@type": "Term"}}
17
+ {"region": {"@type": "Term", "termType": "region"}},
18
+ {"country": {"@type": "Term", "termType": "region"}}
19
19
  ]
20
20
  },
21
21
  "optional": {
@@ -23,8 +23,8 @@ REQUIREMENTS = {
23
23
  {
24
24
  "@type": "Site",
25
25
  "or": [
26
- {"region": {"@type": "Term"}},
27
- {"country": {"@type": "Term"}}
26
+ {"region": {"@type": "Term", "termType": "region"}},
27
+ {"country": {"@type": "Term", "termType": "region"}}
28
28
  ]
29
29
  }
30
30
  ]
@@ -1,8 +1,9 @@
1
- from hestia_earth.utils.api import download_hestia
1
+ from hestia_earth.schema import TermTermType
2
2
  from hestia_earth.utils.model import linked_node
3
3
 
4
4
  from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
5
5
  from .utils import download, has_coordinates
6
+ from hestia_earth.models.utils.term import download_term
6
7
  from . import MODEL
7
8
 
8
9
  REQUIREMENTS = {
@@ -30,7 +31,7 @@ def _download_region(site: dict):
30
31
  only_coordinates=True
31
32
  )
32
33
  try:
33
- return None if gadm_id is None else linked_node(download_hestia(f"GADM-{gadm_id}"))
34
+ return None if gadm_id is None else linked_node(download_term(f"GADM-{gadm_id}", TermTermType.REGION))
34
35
  except Exception:
35
36
  return None
36
37
 
@@ -1,10 +1,10 @@
1
1
  import os
2
2
  from hestia_earth.schema import TermTermType
3
- from hestia_earth.utils.api import download_hestia
4
3
  from hestia_earth.utils.tools import non_empty_list
5
4
 
6
5
  from hestia_earth.models.log import debugValues, logErrorRun, logRequirements
7
6
  from hestia_earth.models.utils.site import cached_value, region_factor, region_level_1_id
7
+ from hestia_earth.models.utils.term import download_term
8
8
  from . import MODEL
9
9
 
10
10
  MAX_AREA_SIZE = int(os.getenv('MAX_AREA_SIZE', '5000'))
@@ -97,7 +97,7 @@ def _get_boundary_area_size(boundary: dict):
97
97
 
98
98
  def _get_region_area_size(site: dict):
99
99
  term = site.get('region', site.get('country'))
100
- return term.get('area', (download_hestia(term.get('@id')) or {}).get('area')) if term else None
100
+ return term.get('area', (download_term(term.get('@id'), TermTermType.REGION) or {}).get('area')) if term else None
101
101
 
102
102
 
103
103
  def get_area_size(site: dict):
@@ -153,9 +153,10 @@ def _get_cached_data(term: str, site: dict, data: dict):
153
153
  cache = _cached_value(site, term)
154
154
  cache_sub_key = _cache_sub_key(data)
155
155
  # data can be grouped by year when required
156
- value = cache.get(cache_sub_key) if (
157
- isinstance(cache, dict) and cache_sub_key in cache and cache is not None
158
- ) else cache
156
+ value = cache.get(cache_sub_key) if all([
157
+ isinstance(cache, dict),
158
+ cache_sub_key
159
+ ]) else cache
159
160
  if value is not None:
160
161
  debugValues(site, model=MODEL, term=term, value_from_cache=value)
161
162
  return value
@@ -1,9 +1,10 @@
1
1
  from haversine import haversine
2
- from hestia_earth.utils.api import download_hestia
2
+ from hestia_earth.schema import TermTermType
3
3
  from hestia_earth.utils.tools import non_empty_list
4
4
 
5
5
  from hestia_earth.models.log import logRequirements, logShouldRun, debugValues
6
6
  from hestia_earth.models.utils.method import include_methodModel
7
+ from hestia_earth.models.utils.term import download_term
7
8
  from .. import MODEL
8
9
 
9
10
  REQUIREMENTS = {
@@ -55,7 +56,7 @@ def _should_run_transport(cycle: dict, transport: dict):
55
56
  def _run_input(cycle: dict, site_country: dict):
56
57
  def exec(input: dict):
57
58
  term_id = input.get('term', {}).get('@id')
58
- input_country = download_hestia(input.get('country', {}).get('@id'))
59
+ input_country = download_term(input.get('country', {}).get('@id'), TermTermType.REGION)
59
60
  distance_kms = haversine(
60
61
  (site_country.get('latitude'), site_country.get('longitude')),
61
62
  (input_country.get('latitude'), input_country.get('longitude'))
@@ -74,7 +75,7 @@ def _should_run_input(site_country_id: str):
74
75
  def exec(input: dict):
75
76
  input_country = input.get('country', {}) or {}
76
77
  input_country_id = input_country.get('@id')
77
- input_country = download_hestia(input_country_id)
78
+ input_country = download_term(input_country_id, TermTermType.REGION)
78
79
  has_transports = len(input.get('transport', [])) > 0
79
80
  should_run = input_country and all([
80
81
  input_country.get('latitude'), input_country.get('latitude'),
@@ -89,7 +90,7 @@ def _should_run(cycle: dict):
89
90
  country_id = cycle.get('site', {}).get('country', {}).get('@id')
90
91
  inputs = list(filter(_should_run_input(country_id), cycle.get('inputs', [])))
91
92
  # download full term to get coordinates only if there is anything to run
92
- country = download_hestia(country_id) if len(inputs) > 0 else {}
93
+ country = download_term(country_id, TermTermType.REGION) if len(inputs) > 0 else {}
93
94
 
94
95
  # can only run if the site country has centroid coordinates
95
96
  logRequirements(cycle, model=MODEL, term=None, key=MODEL_KEY,
@@ -33,6 +33,10 @@ TOTAL_TERM_ID = 'aboveGroundCropResidueTotal'
33
33
  REMAINING_MODEL = PRODUCT_ID_TO_PRACTICES_ID[-1]['product']
34
34
 
35
35
 
36
+ def _product(term_id: str, value: float):
37
+ return _new_product(term_id, round(value, 7), MODEL)
38
+
39
+
36
40
  def _get_practices(term_id: str):
37
41
  return flatten([
38
42
  model.get('practices', []) for model in PRODUCT_ID_TO_PRACTICES_ID if all([
@@ -50,11 +54,6 @@ def _get_practice_value(term_ids: list, cycle: dict) -> float:
50
54
  return list_sum(values) / 100 if len(values) > 0 else None
51
55
 
52
56
 
53
- def _product(term_id: str, value: float):
54
- product = _new_product(term_id, round(value, 2), MODEL)
55
- return product
56
-
57
-
58
57
  def _should_run_model(model, cycle: dict, total_value: float):
59
58
  term_id = model.get('product')
60
59
  practice_value = _get_practice_value(model.get('practices'), cycle)
@@ -22,7 +22,7 @@ TERM_ID = 'aboveGroundCropResidueTotal'
22
22
 
23
23
 
24
24
  def _product(value: float):
25
- product = _new_product(TERM_ID, value)
25
+ product = _new_product(TERM_ID, value, MODEL)
26
26
  return product
27
27
 
28
28
 
@@ -30,7 +30,7 @@ def _run(practice: dict, product: dict):
30
30
  practice_value = list_sum(practice.get('value', []))
31
31
  product_value = list_sum(product.get('value', []))
32
32
  value = product_value / (practice_value / 100)
33
- return [_product(round(value, 2))]
33
+ return [_product(round(value, 7))]
34
34
 
35
35
 
36
36
  def _matching_product_by_practice(term_id: str):
@@ -22,7 +22,7 @@ TERM_ID = 'brackishWater'
22
22
 
23
23
 
24
24
  def _measurement():
25
- data = _new_measurement(TERM_ID)
25
+ data = _new_measurement(TERM_ID, MODEL)
26
26
  data['value'] = [True]
27
27
  data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
28
28
  return data
@@ -30,7 +30,7 @@ BIBLIO_TITLE = 'Contribution of Organic Matter and Clay to Soil Cation-Exchange
30
30
 
31
31
 
32
32
  def _measurement(site: dict, value: float, depthUpper: int = None, depthLower: int = None):
33
- data = _new_measurement(TERM_ID)
33
+ data = _new_measurement(TERM_ID, MODEL)
34
34
  data['value'] = [value]
35
35
  if depthUpper is not None:
36
36
  data['depthUpper'] = depthUpper
@@ -36,7 +36,7 @@ TERM_ID = 'coldCarcassWeightPerHead'
36
36
 
37
37
 
38
38
  def _property(value: float):
39
- prop = _new_property(TERM_ID)
39
+ prop = _new_property(TERM_ID, MODEL)
40
40
  prop['value'] = value
41
41
  return prop
42
42
 
@@ -40,7 +40,7 @@ TERM_ID = 'coldDressedCarcassWeightPerHead'
40
40
 
41
41
 
42
42
  def _property(value: float):
43
- prop = _new_property(TERM_ID)
43
+ prop = _new_property(TERM_ID, MODEL)
44
44
  prop['value'] = value
45
45
  return prop
46
46
 
@@ -45,7 +45,7 @@ INPUT_TERM_TYPES = [
45
45
 
46
46
 
47
47
  def _property(term_id: str, value: float):
48
- prop = _new_property(term_id)
48
+ prop = _new_property(term_id, MODEL)
49
49
  prop['value'] = value
50
50
  return prop
51
51
 
@@ -31,7 +31,7 @@ PRACTICE_IDS = [
31
31
 
32
32
 
33
33
  def _practice(term_id: str):
34
- practice = _new_practice(term_id)
34
+ practice = _new_practice(term_id, MODEL)
35
35
  practice['value'] = [0]
36
36
  return practice
37
37
 
@@ -24,7 +24,7 @@ TERM_ID = 'croppingIntensity'
24
24
 
25
25
 
26
26
  def _practice(value: float):
27
- practice = _new_practice(TERM_ID)
27
+ practice = _new_practice(TERM_ID, MODEL)
28
28
  practice['value'] = [round(value, 7)]
29
29
  return practice
30
30
 
@@ -9,7 +9,7 @@ REQUIREMENTS = {
9
9
  "Cycle": {
10
10
  "inputs": [{
11
11
  "@type": "Input",
12
- "term.termType": ["woodFuel", "woodPellets"],
12
+ "term.@id": ["woodFuel", "woodPellets"],
13
13
  "properties": [{"@type": "Property", "value": "", "term.@id": "dryMatter"}]
14
14
  }]
15
15
  }
@@ -28,7 +28,7 @@ DRY_VALUE = 19.2 # Bone dry wood has an energy content of 19.2 MJ/kg
28
28
 
29
29
 
30
30
  def _property(value: float):
31
- prop = _new_property(TERM_ID)
31
+ prop = _new_property(TERM_ID, MODEL)
32
32
  prop['value'] = value
33
33
  return prop
34
34
 
@@ -14,6 +14,7 @@ REQUIREMENTS = {
14
14
  "products": [
15
15
  {
16
16
  "@type": "Product",
17
+ "value": "",
17
18
  "term.termType": "excreta",
18
19
  "term.units": ["kg N", "kg VS"]
19
20
  }
@@ -36,16 +37,20 @@ UNITS = [
36
37
 
37
38
 
38
39
  def _product(value: float, term_id: str):
39
- product = _new_product(term_id, value)
40
+ product = _new_product(term_id, value, MODEL)
40
41
  return product
41
42
 
42
43
 
43
44
  def _convert_by_product(cycle: dict, product: dict, term_id: str):
44
45
  existing_product = find_term_match(cycle.get('products', []), term_id)
46
+ existing_product_value = list_sum(existing_product.get('value', []), default=None)
45
47
 
46
48
  conversion_to_kg_ratio = convert_product_to_unit(product, existing_product.get('term', {}).get('units')) \
47
49
  if existing_product else None
48
- value = list_sum(existing_product.get('value', [])) / conversion_to_kg_ratio if conversion_to_kg_ratio else None
50
+ value = existing_product_value / conversion_to_kg_ratio if all([
51
+ existing_product_value is not None,
52
+ conversion_to_kg_ratio
53
+ ]) else None
49
54
 
50
55
  debugValues(cycle, model=MODEL, term=term_id,
51
56
  using_excreta_product=existing_product.get('term', {}).get('@id'),
@@ -30,7 +30,7 @@ MODEL_KEY = 'excretaKgN'
30
30
 
31
31
 
32
32
  def _product(value: float, term_id: str):
33
- product = _new_product(term_id, value)
33
+ product = _new_product(term_id, value, MODEL)
34
34
  return product
35
35
 
36
36
 
@@ -30,7 +30,7 @@ MODEL_KEY = 'excretaKgVs'
30
30
 
31
31
 
32
32
  def _product(value: float, term_id: str):
33
- product = _new_product(term_id, value)
33
+ product = _new_product(term_id, value, MODEL)
34
34
  return product
35
35
 
36
36
 
@@ -24,7 +24,7 @@ MODELS = [
24
24
 
25
25
 
26
26
  def _practice(term_id: str, value: float):
27
- practice = _new_practice(term_id)
27
+ practice = _new_practice(term_id, MODEL)
28
28
  practice['value'] = [value]
29
29
  return practice
30
30
 
@@ -25,7 +25,7 @@ SITE_TYPE_TO_TERM_ID = {
25
25
 
26
26
 
27
27
  def _measurement(site: dict, term_id: str):
28
- data = _new_measurement(term_id)
28
+ data = _new_measurement(term_id, MODEL)
29
29
  data['value'] = [True]
30
30
  data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
31
31
  return data | get_source(site, BIBLIO_TITLE)
@@ -22,7 +22,7 @@ TERM_ID = 'freshWater'
22
22
 
23
23
 
24
24
  def _measurement():
25
- data = _new_measurement(TERM_ID)
25
+ data = _new_measurement(TERM_ID, MODEL)
26
26
  data['value'] = [True]
27
27
  data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
28
28
  return data
@@ -70,7 +70,7 @@ VALUE_BY_UNIT = {
70
70
 
71
71
 
72
72
  def _input(term_id: str, value: float, min: float = None, max: float = None):
73
- input = _new_input(term_id)
73
+ input = _new_input(term_id, MODEL)
74
74
  input['value'] = [value]
75
75
  if min is not None:
76
76
  input['min'] = [min]
@@ -1,15 +1,13 @@
1
- from hestia_earth.schema import TermTermType, CycleFunctionalUnit
1
+ from hestia_earth.schema import CycleFunctionalUnit
2
2
 
3
3
  from hestia_earth.models.log import logRequirements, logShouldRun
4
4
  from hestia_earth.models.utils.cycle import is_irrigated
5
5
  from hestia_earth.models.utils.practice import _new_practice
6
6
  from hestia_earth.models.utils.input import get_total_irrigation_m3
7
- from hestia_earth.models.utils.completeness import _is_term_type_complete
8
7
  from . import MODEL
9
8
 
10
9
  REQUIREMENTS = {
11
10
  "Cycle": {
12
- "completeness.water": "",
13
11
  "functionalUnit": "1 ha",
14
12
  "none": {
15
13
  "practices": [{"@type": "Practice", "value": "> 0", "term.termType": "waterRegime"}]
@@ -31,38 +29,35 @@ TERM_ID = 'irrigatedTypeUnspecified'
31
29
  MIN_IRRIGATION_M3 = 250
32
30
 
33
31
 
34
- def _practice(value: float):
35
- practice = _new_practice(TERM_ID)
36
- practice['value'] = [value]
32
+ def _practice():
33
+ practice = _new_practice(TERM_ID, MODEL)
34
+ practice['value'] = [100]
37
35
  return practice
38
36
 
39
37
 
40
- def _run(irrigation_m3: float):
41
- value = 100 if irrigation_m3 > MIN_IRRIGATION_M3 else 0
42
- return [_practice(value)]
43
-
44
-
45
38
  def _should_run(cycle: dict):
46
39
  functional_unit = cycle.get('functionalUnit')
47
- water_complete = _is_term_type_complete(cycle, TermTermType.WATER)
48
40
  irrigation_value_m3 = get_total_irrigation_m3(cycle)
41
+ is_1_ha_functional_unit = functional_unit == CycleFunctionalUnit._1_HA.value
49
42
 
50
43
  no_irrigation_practice = not is_irrigated(cycle, model=MODEL, term=TERM_ID)
51
44
 
52
45
  logRequirements(cycle, model=MODEL, term=TERM_ID,
53
46
  no_irrigation_practice=no_irrigation_practice,
54
- term_type_water_complete=water_complete,
55
- irrigation_value_m3=irrigation_value_m3)
47
+ is_1_ha_functional_unit=is_1_ha_functional_unit,
48
+ irrigation_value_m3=irrigation_value_m3,
49
+ irrigation_min_m3=MIN_IRRIGATION_M3,
50
+ is_irrigated=irrigation_value_m3 > MIN_IRRIGATION_M3)
56
51
 
57
52
  should_run = all([
58
53
  no_irrigation_practice,
59
- functional_unit == CycleFunctionalUnit._1_HA.value,
60
- any([water_complete, irrigation_value_m3 > MIN_IRRIGATION_M3])
54
+ is_1_ha_functional_unit,
55
+ irrigation_value_m3 > MIN_IRRIGATION_M3
61
56
  ])
62
57
  logShouldRun(cycle, MODEL, TERM_ID, should_run)
63
- return should_run, irrigation_value_m3
58
+ return should_run
64
59
 
65
60
 
66
61
  def run(cycle: dict):
67
- should_run, irrigation_m3 = _should_run(cycle)
68
- return _run(irrigation_m3) if should_run else []
62
+ should_run = _should_run(cycle)
63
+ return [_practice()] if should_run else []
@@ -11,6 +11,7 @@ from hestia_earth.utils.model import filter_list_term_type
11
11
  from hestia_earth.utils.tools import safe_parse_float, to_precision
12
12
 
13
13
  from hestia_earth.models.log import logRequirements, log_as_table, logShouldRun
14
+ from hestia_earth.models.utils import _omit
14
15
  from hestia_earth.models.utils.constant import DAYS_IN_YEAR
15
16
  from hestia_earth.models.utils.management import _new_management
16
17
  from hestia_earth.models.utils.term import get_lookup_value
@@ -40,7 +41,7 @@ REQUIREMENTS = {
40
41
  "permanent pasture",
41
42
  "other natural vegetation"
42
43
  ],
43
- "country": "",
44
+ "country": {"@type": "Term", "termType": "region"},
44
45
  "management": [
45
46
  {
46
47
  "@type": "Management",
@@ -56,11 +57,7 @@ REQUIREMENTS = {
56
57
  }
57
58
  RETURNS = {
58
59
  "Management": [{
59
- "@type": "Management",
60
60
  "term.termType": "landCover",
61
- "term.@id": [
62
- "Forest", "Annual cropland", "Permanent cropland", "Permanent pasture", "Other natural vegetation"
63
- ],
64
61
  "value": "",
65
62
  "endDate": "",
66
63
  "startDate": ""
@@ -95,6 +92,7 @@ SITE_TYPES = {
95
92
  DEFAULT_WINDOW_IN_YEARS = 20
96
93
  DATE_TOLERANCE_IN_YEARS = 2
97
94
  OUTPUT_SIGNIFICANT_DIGITS = 3
95
+ ALLOWED_LAND_USE_TYPES = [ANNUAL_CROPLAND, PERMANENT_CROPLAND, PERMANENT_PASTURE]
98
96
  _LOOKUP_EXPANSION = "region-crop-cropGroupingFaostatProduction-areaHarvestedUpTo20YearExpansion.csv"
99
97
 
100
98
 
@@ -755,16 +753,21 @@ def _collect_land_use_types(nodes: list) -> list:
755
753
  """Look up the land use type from management nodes."""
756
754
  return [
757
755
  {
756
+ "value": node.get("value", ""),
757
+ "term": node.get("term", {}),
758
758
  "id": node.get("term", {}).get("@id"),
759
759
  "land-use-type": _get_land_use_term_from_node(node),
760
- "endDate": _gapfill_datestr(datestr=node.get("endDate"), mode=DatestrGapfillMode.END)[:10]
760
+ "endDate": _gapfill_datestr(datestr=node.get("endDate"), mode=DatestrGapfillMode.END)[:10],
761
+ "startDate": _gapfill_datestr(
762
+ datestr=node.get("startDate"), mode=DatestrGapfillMode.START
763
+ )[:10] if node.get("startDate") else None
761
764
  } for node in nodes
762
765
  ]
763
766
 
764
767
 
765
- def _no_prior_land_cover_data(nodes: list, end_date: str) -> bool:
768
+ def _no_prior_land_cover_data(nodes: list, node: dict) -> bool:
766
769
  target_date = (
767
- datetime.strptime(end_date, DatestrFormat.YEAR_MONTH_DAY.value)
770
+ datetime.strptime(node.get('startDate') or node.get('endDate'), DatestrFormat.YEAR_MONTH_DAY.value)
768
771
  - timedelta(days=DEFAULT_WINDOW_IN_YEARS * DAYS_IN_YEAR)
769
772
  )
770
773
  previous_nodes = [
@@ -774,45 +777,46 @@ def _no_prior_land_cover_data(nodes: list, end_date: str) -> bool:
774
777
  return len(previous_nodes) == 0
775
778
 
776
779
 
777
- def _should_run(site: dict, management_nodes: list) -> tuple[bool, dict]:
778
- summarised_nodes = _collect_land_use_types(management_nodes)
779
- allowed_land_use_types = [ANNUAL_CROPLAND, PERMANENT_CROPLAND, PERMANENT_PASTURE]
780
+ def _should_run(site: dict) -> tuple[bool, dict]:
781
+ management_nodes = _collect_land_use_types(
782
+ [
783
+ node for node in filter_list_term_type(site.get("management", []), TermTermType.LANDCOVER)
784
+ if not _should_group_landCover(node)
785
+ ]
786
+ )
780
787
  relevant_nodes = sorted(
781
788
  [
782
- node for node in summarised_nodes
783
- if node["land-use-type"] in allowed_land_use_types
789
+ node for node in management_nodes
790
+ if node["land-use-type"] in ALLOWED_LAND_USE_TYPES
784
791
  ],
785
- key=lambda n: n.get("endDate")
792
+ key=lambda n: n.get("startDate") or n.get("endDate")
786
793
  )
794
+
787
795
  land_use_type = relevant_nodes[0].get("land-use-type") if relevant_nodes else None
788
796
 
789
797
  has_no_prior_land_cover_data = _no_prior_land_cover_data(
790
- nodes=management_nodes,
791
- end_date=relevant_nodes[-1:][0].get("endDate")
798
+ nodes=relevant_nodes,
799
+ node=relevant_nodes[-1:][0]
792
800
  ) if relevant_nodes else None
793
801
 
794
802
  should_run_nodes, site_area = _should_run_historical_land_use_change(
795
803
  site=site,
796
- nodes=management_nodes,
804
+ nodes=relevant_nodes,
797
805
  land_use_type=land_use_type
798
806
  ) if all([land_use_type, has_no_prior_land_cover_data]) else (False, {})
799
807
 
800
808
  logRequirements(site, model=MODEL, model_key=MODEL_KEY,
801
- has_management_nodes=bool(management_nodes),
809
+ has_management_nodes=bool(relevant_nodes),
802
810
  land_use_type=land_use_type,
803
- allowed_land_use_types=';'.join(allowed_land_use_types),
811
+ allowed_land_use_types=';'.join(ALLOWED_LAND_USE_TYPES),
804
812
  has_no_prior_land_cover_data=has_no_prior_land_cover_data,
805
- summarised_nodes=log_as_table(summarised_nodes))
813
+ management_nodes=log_as_table([_omit(n, ['term']) for n in relevant_nodes]))
806
814
 
807
815
  should_run = all([land_use_type, has_no_prior_land_cover_data, should_run_nodes])
808
816
  logShouldRun(site, MODEL, None, should_run, model_key=MODEL_KEY)
809
- return should_run_nodes, site_area
817
+ return should_run_nodes, relevant_nodes, site_area
810
818
 
811
819
 
812
820
  def run(site: dict) -> list:
813
- management_nodes = [
814
- node for node in filter_list_term_type(site.get("management", []), TermTermType.LANDCOVER)
815
- if not _should_group_landCover(node)
816
- ]
817
- should_run, site_area = _should_run(site=site, management_nodes=management_nodes)
818
- return _run(site, management_nodes, site_area) if should_run else []
821
+ should_run, relevant_nodes, site_area = _should_run(site=site)
822
+ return _run(site, relevant_nodes, site_area) if should_run else []
@@ -2,7 +2,8 @@ from .resourceUse_utils import run_resource_use
2
2
 
3
3
  REQUIREMENTS = {
4
4
  "ImpactAssessment": {
5
- "Site": {
5
+ "site": {
6
+ "@type": "Site",
6
7
  "management": [{"@type": "Management", "value": ">=0", "term.termType": "landCover", "endDate": ""}]
7
8
  },
8
9
  "emissionsResourceUse": [