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
@@ -11,6 +11,7 @@ from . import MODEL
11
11
  REQUIREMENTS = {
12
12
  "Cycle": {
13
13
  "site": {
14
+ "@type": "Site",
14
15
  "measurements": [
15
16
  {
16
17
  "@type": "Measurement",
@@ -38,7 +39,7 @@ RETURNS = {
38
39
  "statsDefinition": "simulated",
39
40
  "observations": "",
40
41
  "methodTier": "",
41
- "depth": "30"
42
+ "depth": 30
42
43
  }]
43
44
  }
44
45
  TERM_ID = 'co2ToAirSoilOrganicCarbonStockChangeLandUseChange,co2ToAirSoilOrganicCarbonStockChangeManagementChange'
@@ -1,5 +1,5 @@
1
1
  from hestia_earth.schema import EmissionMethodTier
2
- from hestia_earth.utils.tools import list_sum, safe_parse_float
2
+ from hestia_earth.utils.tools import list_sum, safe_parse_float, non_empty_list
3
3
  from hestia_earth.utils.model import find_term_match
4
4
 
5
5
  from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
@@ -68,14 +68,21 @@ def _should_run(cycle: dict):
68
68
  uan_share = get_country_breakdown(MODEL, TERM_ID, country_id, LOOKUPS['inorganicFertiliser'][1])
69
69
  urea_unspecified_as_n = list_sum(find_term_match(inputs, UNSPECIFIED_TERM_ID).get('value', []))
70
70
 
71
- urea_values = [{'id': id, 'values': _get_urea_values(cycle, inputs, id)} for id in term_ids] + ([
72
- {'id': 'ureaKgN', 'values': [urea_unspecified_as_n * urea_share]},
73
- {'id': 'ureaAmmoniumNitrateKgN', 'values': [urea_unspecified_as_n * uan_share]}
74
- ] if all([
75
- urea_share,
76
- uan_share,
77
- urea_unspecified_as_n > 0
78
- ]) else [])
71
+ urea_values = [
72
+ {
73
+ 'id': id,
74
+ 'values': _get_urea_values(cycle, inputs, id)
75
+ } for id in term_ids
76
+ ] + non_empty_list([
77
+ {
78
+ 'id': 'ureaKgN',
79
+ 'values': [urea_unspecified_as_n * urea_share]
80
+ } if urea_share is not None else None,
81
+ {
82
+ 'id': 'ureaAmmoniumNitrateKgN',
83
+ 'values': [urea_unspecified_as_n * uan_share]
84
+ } if urea_share is not None else None
85
+ ] if urea_unspecified_as_n > 0 else [])
79
86
  has_urea_value = any([len(data.get('values')) > 0 for data in urea_values])
80
87
 
81
88
  logRequirements(cycle, model=MODEL, term=TERM_ID,
@@ -24,6 +24,7 @@ from .biomass_utils import BiomassCategory, get_valid_management_nodes, summaris
24
24
  REQUIREMENTS = {
25
25
  "Cycle": {
26
26
  "site": {
27
+ "@type": "Site",
27
28
  "management": [
28
29
  {
29
30
  "@type": "Management",
@@ -155,8 +156,6 @@ _Inventory = dict[int, _InventoryYear]
155
156
  {year (int): data (_InventoryYear)}
156
157
  """
157
158
 
158
- _EmissionInventory = dict[_EmissionTermId, npt.NDArray]
159
-
160
159
 
161
160
  _BIOMASS_CATEGORY_TO_FUEL_CATEGORY = {
162
161
  BiomassCategory.FOREST: {
@@ -517,9 +516,9 @@ def _sum_cycle_emissions(term_id: _EmissionTermId, cycle_id: str, inventory: _In
517
516
  return reduce(add_cycle_emissions, inventory.keys(), np.array(0))
518
517
 
519
518
 
520
- def _compile_run_data(
519
+ def _compile_inventory(
521
520
  cycle: dict, site: dict, land_cover_nodes: list[dict], eco_climate_zone: EcoClimateZone
522
- ) -> tuple[_EmissionInventory, _Inventory, dict]:
521
+ ):
523
522
  """
524
523
  Compile the run data for the model, collating data from `site.management` and related cycles. An annualised
525
524
  inventory of land cover change and natural vegetation burning events is constructed. Emissions from burning events
@@ -538,18 +537,12 @@ def _compile_run_data(
538
537
 
539
538
  Returns
540
539
  -------
541
- emission_inventory : _EmissionInventory
542
- A dictionary of emissions relevant to the cycle the model is run on, in the format:
543
- ```
544
- {
545
- emission_term_id (str): value (NDArray),
546
- ...
547
- }
548
- ```
540
+ should_run : bool
541
+ Whether the model should be run.
549
542
  inventory : _Inventory
550
- An inventory of model data
543
+ An inventory of model data.
551
544
  logs : dict
552
- Data from the compilation process that should be logged.
545
+ Data about the inventory compilation to be logged.
553
546
  """
554
547
  cycle_id = cycle.get("@id")
555
548
  related_cycles_ = related_cycles(site, cycles_mapping={cycle_id: cycle})
@@ -585,9 +578,15 @@ def _compile_run_data(
585
578
  Returns
586
579
  -------
587
580
  inventory : dict
588
- An inventory of model data, updated to include the new model year.
581
+ An inventory of model data, updated to include the input year.
589
582
  """
590
- land_cover_nodes = next((nodes for year_, nodes in land_cover_grouped.items() if year_ >= year), []) # Backfill
583
+ land_cover_nodes = land_cover_grouped.get(
584
+ next(
585
+ (k for k in sorted(land_cover_grouped) if k >= year), # backfill if possible
586
+ min(land_cover_grouped, key=lambda k: abs(k - year)) # else forward-fill
587
+ ),
588
+ []
589
+ )
591
590
 
592
591
  biomass_category_summary = summarise_land_cover_nodes(land_cover_nodes)
593
592
  prev_biomass_category_summary = inventory.get(year-1, {}).get("biomass_category_summary", {})
@@ -655,17 +654,17 @@ def _compile_run_data(
655
654
 
656
655
  inventory = reduce(build_inventory_year, range(min_year, max_year+1), dict())
657
656
 
658
- emission_inventory = {
659
- term_id: value for term_id in EMISSION_TERM_IDS
660
- if np.all((value := _sum_cycle_emissions(term_id, cycle_id, inventory)) > 0)
661
- }
657
+ n_land_cover_years = len(land_cover_grouped)
662
658
 
663
659
  logs = {
660
+ "n_land_cover_years": n_land_cover_years,
664
661
  "percent_burned": percent_burned,
665
662
  "seed": seed,
666
663
  }
667
664
 
668
- return emission_inventory, inventory, logs
665
+ should_run = bool(inventory and n_land_cover_years > 1)
666
+
667
+ return should_run, inventory, logs
669
668
 
670
669
 
671
670
  def _format_bool(value: Optional[bool]) -> str:
@@ -830,23 +829,16 @@ def _format_inventory(term_id: _EmissionTermId, cycle_id: str, inventory: dict)
830
829
  ) if inventory else "None"
831
830
 
832
831
 
833
- def _should_run_emission(
834
- term_id: _EmissionTermId, cycle: dict, emission_inventory: _EmissionInventory, inventory: dict, logs: dict
835
- ):
832
+ def _log_emission_data(should_run: bool, term_id: _EmissionTermId, cycle: dict, inventory: dict, logs: dict):
836
833
  """
837
- Determine, based on the compiled data, whether the model should run for a specifc emission term id. Format and log
838
- the model logs and inventory.
834
+ Format and log the model logs and inventory.
839
835
  """
840
- should_run = term_id in emission_inventory
841
-
842
836
  formatted_logs = _format_logs(logs)
843
837
  formatted_inventory = _format_inventory(term_id, cycle.get("@id"), inventory)
844
838
 
845
839
  logRequirements(cycle, model=MODEL, term=term_id, **formatted_logs, inventory=formatted_inventory)
846
840
  logShouldRun(cycle, MODEL, term_id, should_run)
847
841
 
848
- return should_run
849
-
850
842
 
851
843
  def _should_run(cycle: dict):
852
844
  """
@@ -860,8 +852,8 @@ def _should_run(cycle: dict):
860
852
 
861
853
  Returns
862
854
  -------
863
- tuple[bool, dict]
864
- should_run, emission_inventory
855
+ tuple[bool, _Inventory]
856
+ should_run, inventory
865
857
  """
866
858
  site = _get_site(cycle)
867
859
 
@@ -872,7 +864,7 @@ def _should_run(cycle: dict):
872
864
 
873
865
  has_valid_site_type = all([site_type, site_type not in _EXCLUDED_SITE_TYPES])
874
866
  has_valid_eco_climate_zone = all([eco_climate_zone, eco_climate_zone not in _EXCLUDED_ECO_CLIMATE_ZONES])
875
- has_land_cover_nodes = len(land_cover_nodes) > 0
867
+ has_land_cover_nodes = len(land_cover_nodes) > 1
876
868
 
877
869
  should_compile_inventory = all([
878
870
  has_valid_site_type,
@@ -880,9 +872,9 @@ def _should_run(cycle: dict):
880
872
  has_land_cover_nodes
881
873
  ])
882
874
 
883
- emission_inventory, inventory, compilation_logs = (
884
- _compile_run_data(cycle, site, land_cover_nodes, eco_climate_zone)
885
- if should_compile_inventory else ({}, {}, {})
875
+ should_run, inventory, compilation_logs = (
876
+ _compile_inventory(cycle, site, land_cover_nodes, eco_climate_zone)
877
+ if should_compile_inventory else (False, {}, {})
886
878
  )
887
879
 
888
880
  logs = {
@@ -896,21 +888,18 @@ def _should_run(cycle: dict):
896
888
  **compilation_logs
897
889
  }
898
890
 
899
- should_run = all([
900
- any([
901
- _should_run_emission(term_id, cycle, emission_inventory, inventory, logs) for term_id in EMISSION_TERM_IDS
902
- ])
903
- ])
891
+ for term_id in EMISSION_TERM_IDS:
892
+ _log_emission_data(should_run, term_id, cycle, inventory, logs)
904
893
 
905
- return should_run, emission_inventory
894
+ return should_run, inventory
906
895
 
907
896
 
908
- def _run_emission(term_id: _EmissionTermId, emissions: dict[_EmissionTermId, npt.NDArray]) -> list[dict]:
897
+ def _run_emission(term_id: _EmissionTermId, cycle_id: str, inventory: _Inventory) -> list[dict]:
909
898
  """
910
- Retrieve the pre-computed emissions and format them as a HESTIA
899
+ Retrieve the sum relevant emissions and format them as a HESTIA
911
900
  [Emission node](https://www.hestia.earth/schema/Emission).
912
901
  """
913
- emission = emissions[term_id]
902
+ emission = _sum_cycle_emissions(term_id, cycle_id, inventory)
914
903
  descriptive_stats = calc_descriptive_stats(emission, STATS_DEFINITION, decimals=3)
915
904
  return _emission(term_id, **descriptive_stats)
916
905
 
@@ -931,5 +920,5 @@ def run(cycle: dict):
931
920
  `ch4ToAirNaturalVegetationBurning` **OR** `coToAirNaturalVegetationBurning` **OR**
932
921
  `n2OToAirNaturalVegetationBurningDirect` **OR** `noxToAirNaturalVegetationBurning`.
933
922
  """
934
- should_run, emission_inventory = _should_run(cycle)
935
- return [_run_emission(term_id, emission_inventory) for term_id in emission_inventory] if should_run else []
923
+ should_run, inventory = _should_run(cycle)
924
+ return [_run_emission(term_id, cycle.get("@id"), inventory) for term_id in EMISSION_TERM_IDS] if should_run else []
@@ -31,7 +31,78 @@ from .organicCarbonPerHa_utils import (
31
31
  )
32
32
  from . import MODEL
33
33
 
34
- _LOOKUPS = {
34
+ REQUIREMENTS = {
35
+ "Site": {
36
+ "management": [
37
+ {"@type": "Management", "value": "", "term.termType": "landCover"}
38
+ ],
39
+ "measurements": [
40
+ {
41
+ "@type": "Measurement",
42
+ "value": ["1", "2", "3", "4", "7", "8", "9", "10", "11", "12"],
43
+ "term.@id": "ecoClimateZone"
44
+ }
45
+ ],
46
+ "optional": {
47
+ "measurements": [
48
+ {"@type": "Measurement", "value": "", "term.termType": ["soilType", "usdaSoilType"]}
49
+ ],
50
+ "management": [
51
+ {
52
+ "@type": "Management",
53
+ "value": "",
54
+ "startDate": "",
55
+ "endDate": "",
56
+ "term.termType": "cropResidueManagement",
57
+ "name": ["burnt", "removed"]
58
+ },
59
+ {
60
+ "@type": "Management",
61
+ "value": "",
62
+ "startDate": "",
63
+ "endDate": "",
64
+ "term.termType": "landUseManagement"
65
+ },
66
+ {"@type": "Management", "value": "", "startDate": "", "endDate": "", "term.termType": "tillage"},
67
+ {
68
+ "@type": "Management",
69
+ "value": "",
70
+ "startDate": "",
71
+ "endDate": "",
72
+ "term.termType": "waterRegime",
73
+ "name": ["deep water", "irrigated"]
74
+ },
75
+ {
76
+ "@type": "Management",
77
+ "value": "",
78
+ "startDate": "",
79
+ "endDate": "",
80
+ "term.@id": "amendmentIncreasingSoilCarbonUsed"
81
+ },
82
+ {"@type": "Management", "value": "", "startDate": "", "endDate": "", "term.@id": "animalManureUsed"},
83
+ {
84
+ "@type": "Management",
85
+ "value": "",
86
+ "startDate": "",
87
+ "endDate": "",
88
+ "term.@id": "inorganicNitrogenFertiliserUsed"
89
+ },
90
+ {
91
+ "@type": "Management",
92
+ "value": "",
93
+ "startDate": "",
94
+ "endDate": "",
95
+ "term.@id": "organicFertiliserUsed"
96
+ },
97
+ {"@type": "Management", "value": "", "startDate": "", "endDate": "", "term.@id": "shortBareFallow"}
98
+ ]
99
+ },
100
+ "none": {
101
+ "siteType": ["glass or high accessible cover"]
102
+ }
103
+ }
104
+ }
105
+ LOOKUPS = {
35
106
  "crop": "IPCC_LAND_USE_CATEGORY",
36
107
  "landCover": [
37
108
  "IPCC_LAND_USE_CATEGORY",
@@ -43,6 +114,20 @@ _LOOKUPS = {
43
114
  "tillage": "IPCC_TILLAGE_MANAGEMENT_CATEGORY",
44
115
  "usdaSoilType": "IPCC_SOIL_CATEGORY"
45
116
  }
117
+ RETURNS = {
118
+ "Measurement": [{
119
+ "value": "",
120
+ "sd": "",
121
+ "min": "",
122
+ "max": "",
123
+ "statsDefinition": "simulated",
124
+ "observations": "",
125
+ "dates": "",
126
+ "depthUpper": "0",
127
+ "depthLower": "30",
128
+ "methodClassification": "tier 1 model"
129
+ }]
130
+ }
46
131
 
47
132
  TERM_ID = 'organicCarbonPerHa'
48
133
  _METHOD_CLASSIFICATION = MeasurementMethodClassification.TIER_1_MODEL.value
@@ -108,7 +193,7 @@ def _measurement(
108
193
  dict
109
194
  A valid HESTIA `Measurement` node, see: https://www.hestia.earth/schema/Measurement.
110
195
  """
111
- measurement = _new_measurement(TERM_ID) | descriptive_stats_dict
196
+ measurement = _new_measurement(TERM_ID, MODEL) | descriptive_stats_dict
112
197
  measurement["dates"] = [f"{year}-12-31" for year in timestamps]
113
198
  measurement["depthUpper"] = DEPTH_UPPER
114
199
  measurement["depthLower"] = DEPTH_LOWER
@@ -992,8 +1077,8 @@ def _check_soil_category(
992
1077
  bool
993
1078
  `True` if the soil category matches, `False` otherwise.
994
1079
  """
995
- SOIL_TYPE_LOOKUP = _LOOKUPS["soilType"]
996
- USDA_SOIL_TYPE_LOOKUP = _LOOKUPS["usdaSoilType"]
1080
+ SOIL_TYPE_LOOKUP = LOOKUPS["soilType"]
1081
+ USDA_SOIL_TYPE_LOOKUP = LOOKUPS["usdaSoilType"]
997
1082
 
998
1083
  target_lookup_values = IPCC_SOIL_CATEGORY_TO_SOIL_TYPE_LOOKUP_VALUE.get(key, None)
999
1084
 
@@ -1183,7 +1268,7 @@ def _check_ipcc_land_use_category(*, key: IpccLandUseCategory, land_cover_nodes:
1183
1268
  bool
1184
1269
  `True` if the conditions match the specified land use category, `False` otherwise.
1185
1270
  """
1186
- LOOKUP = _LOOKUPS["landCover"][0]
1271
+ LOOKUP = LOOKUPS["landCover"][0]
1187
1272
  target_lookup_values = IPCC_LAND_USE_CATEGORY_TO_LAND_COVER_LOOKUP_VALUE.get(key, None)
1188
1273
  valid_lookup = cumulative_nodes_lookup_match(
1189
1274
  land_cover_nodes,
@@ -1340,7 +1425,7 @@ def _check_tillage_ipcc_management_category(
1340
1425
  bool
1341
1426
  `True` if the conditions match the specified management category, `False` otherwise.
1342
1427
  """
1343
- LOOKUP = _LOOKUPS["tillage"]
1428
+ LOOKUP = LOOKUPS["tillage"]
1344
1429
  target_lookup_values = IPCC_MANAGEMENT_CATEGORY_TO_TILLAGE_MANAGEMENT_LOOKUP_VALUE.get(key, None)
1345
1430
  return cumulative_nodes_lookup_match(
1346
1431
  tillage_nodes,
@@ -1798,9 +1883,9 @@ def _get_carbon_input_kwargs(
1798
1883
  The carbon input keyword arguments.
1799
1884
  """
1800
1885
 
1801
- PRACTICE_INCREASING_C_INPUT_LOOKUP = _LOOKUPS["landUseManagement"]
1802
- LOW_RESIDUE_PRODUCING_CROP_LOOKUP = _LOOKUPS["landCover"][1]
1803
- N_FIXING_CROP_LOOKUP = _LOOKUPS["landCover"][2]
1886
+ PRACTICE_INCREASING_C_INPUT_LOOKUP = LOOKUPS["landUseManagement"]
1887
+ LOW_RESIDUE_PRODUCING_CROP_LOOKUP = LOOKUPS["landCover"][1]
1888
+ N_FIXING_CROP_LOOKUP = LOOKUPS["landCover"][2]
1804
1889
 
1805
1890
  # To prevent double counting already explicitly checked practices.
1806
1891
  EXCLUDED_PRACTICE_TERM_IDS = {