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
@@ -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": [
@@ -46,7 +46,7 @@ VALID_SITE_TYPES = [SiteSiteType.ANIMAL_HOUSING.value, SiteSiteType.PERMANENT_PA
46
46
 
47
47
 
48
48
  def _product(term: str, value: float):
49
- product = _new_product(term, value)
49
+ product = _new_product(term, value, MODEL)
50
50
  return product
51
51
 
52
52
 
@@ -22,7 +22,7 @@ TERM_ID = 'longFallowRatio'
22
22
 
23
23
 
24
24
  def _practice(value: float):
25
- practice = _new_practice(TERM_ID)
25
+ practice = _new_practice(TERM_ID, MODEL)
26
26
  practice['value'] = [round(value, 7)]
27
27
  return practice
28
28
 
@@ -140,12 +140,14 @@ def management(data: dict):
140
140
 
141
141
 
142
142
  def _get_cycle_duration(cycle: dict, land_cover_id: str):
143
- return cycle.get('cycleDuration') or safe_parse_float(get_table_value(
143
+ cycle_duration = cycle.get('cycleDuration')
144
+ lookup_value = None if cycle_duration else safe_parse_float(get_table_value(
144
145
  download_lookup("crop.csv"),
145
146
  column_name('landCoverTermId'),
146
147
  land_cover_id,
147
148
  column_name('maximumCycleDuration')
148
- ))
149
+ ), default=None)
150
+ return cycle_duration or (lookup_value - 1 if lookup_value else None)
149
151
 
150
152
 
151
153
  def _gap_filled_date_only_str(date_str: str, mode: str = DatestrGapfillMode.END) -> str:
@@ -164,7 +166,7 @@ def _gap_filled_start_date(land_cover_id: str, end_date: str, cycle: dict) -> di
164
166
  cycle_duration = _get_cycle_duration(cycle, land_cover_id)
165
167
  return {
166
168
  "startDate": max(
167
- _gap_filled_date_obj(end_date) - timedelta(days=cycle_duration - 1)
169
+ _gap_filled_date_obj(end_date) - timedelta(days=cycle_duration)
168
170
  if cycle_duration else datetime.fromtimestamp(0),
169
171
  _gap_filled_date_obj(cycle.get("startDate"), mode=DatestrGapfillMode.START)
170
172
  if cycle.get("startDate") else datetime.fromtimestamp(0)
@@ -53,7 +53,7 @@ _SIGNIFICANT_DIGITS = 5
53
53
 
54
54
 
55
55
  def _input(term_id: str, value: float, stats: dict) -> dict:
56
- node = _new_input(term_id + _ID_SUFFIX)
56
+ node = _new_input(term_id + _ID_SUFFIX, MODEL)
57
57
  node['value'] = [value]
58
58
  return node | stats
59
59
 
@@ -51,7 +51,7 @@ VALID_SITE_TYPES = [
51
51
 
52
52
 
53
53
  def practice(term_id: str, value: float, properties: list, sd: float = None, min: float = None, max: float = None):
54
- data = _new_practice(term_id)
54
+ data = _new_practice(term_id, MODEL)
55
55
  data['value'] = [round(value, 2)]
56
56
  if properties:
57
57
  data['properties'] = properties
@@ -24,7 +24,7 @@ NPP_Aqua = {TemperatureLevel.LOW: 2, TemperatureLevel.MEDIUM: 4, TemperatureLeve
24
24
 
25
25
 
26
26
  def _measurement(site: dict, value: float):
27
- data = _new_measurement(TERM_ID)
27
+ data = _new_measurement(TERM_ID, MODEL)
28
28
  data['value'] = [value]
29
29
  data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
30
30
  return data | get_source(site, BIBLIO_TITLE)
@@ -64,7 +64,7 @@ VALID_MEASUREMENT_METHOD_CLASSIFICATIONS = {
64
64
  def _measurement(
65
65
  site: dict, value: float, depthUpper: Union[int, float], depthLower: Union[int, float], date: Optional[str] = None
66
66
  ) -> dict:
67
- data = _new_measurement(TERM_ID)
67
+ data = _new_measurement(TERM_ID, MODEL)
68
68
  data['value'] = [value]
69
69
  data['depthUpper'] = int(depthUpper)
70
70
  data['depthLower'] = int(depthLower)
@@ -25,7 +25,7 @@ KEY_TERM_ID = 'genericGrassPlant'
25
25
 
26
26
 
27
27
  def _practice():
28
- node = _new_practice(TERM_ID)
28
+ node = _new_practice(TERM_ID, MODEL)
29
29
  node['value'] = [100]
30
30
  node['key'] = linked_node(download_term(KEY_TERM_ID, TermTermType.LANDCOVER))
31
31
  return node
@@ -33,7 +33,7 @@ VALID_SITE_TYPES = [SiteSiteType.PERMANENT_PASTURE.value]
33
33
 
34
34
 
35
35
  def _practice(term_id: str):
36
- practice = _new_practice(term_id)
36
+ practice = _new_practice(term_id, MODEL)
37
37
  practice['value'] = [100]
38
38
  return practice
39
39
 
@@ -3,7 +3,7 @@ from hestia_earth.utils.tools import flatten, non_empty_list
3
3
 
4
4
  from hestia_earth.models.log import logRequirements, logShouldRun
5
5
  from hestia_earth.models.utils.measurement import _new_measurement
6
- from .utils import _slice_by_year
6
+ from .utils import slice_by_year
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -26,7 +26,7 @@ MEASUREMENT_ID = 'potentialEvapotranspirationMonthly'
26
26
 
27
27
 
28
28
  def _measurement(value: float, start_date: str, end_date: str):
29
- data = _new_measurement(TERM_ID)
29
+ data = _new_measurement(TERM_ID, MODEL)
30
30
  data['value'] = [value]
31
31
  data['startDate'] = start_date
32
32
  data['endDate'] = end_date
@@ -38,7 +38,7 @@ def _run(measurement: dict):
38
38
  values = measurement.get('value', [])
39
39
  dates = measurement.get('dates', [])
40
40
  term_id = measurement.get('term', {}).get('@id')
41
- results = _slice_by_year(term_id, dates, values)
41
+ results = slice_by_year(term_id, dates, values)
42
42
  return [_measurement(value, start_date, end_date) for (value, start_date, end_date) in results]
43
43
 
44
44
 
@@ -3,7 +3,7 @@ from hestia_earth.utils.tools import flatten, non_empty_list
3
3
 
4
4
  from hestia_earth.models.log import logRequirements, logShouldRun
5
5
  from hestia_earth.models.utils.measurement import _new_measurement
6
- from .utils import _group_by_month
6
+ from .utils import group_by_month
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -25,7 +25,7 @@ MEASUREMENT_ID = 'potentialEvapotranspirationDaily'
25
25
 
26
26
 
27
27
  def _measurement(value: list, dates: list):
28
- data = _new_measurement(TERM_ID)
28
+ data = _new_measurement(TERM_ID, MODEL)
29
29
  data['value'] = value
30
30
  data['dates'] = dates
31
31
  data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
@@ -36,7 +36,7 @@ def _run(measurement: dict):
36
36
  values = measurement.get('value', [])
37
37
  dates = measurement.get('dates', [])
38
38
  term_id = measurement.get('term', {}).get('@id')
39
- result = _group_by_month(term_id, dates, values)
39
+ result = group_by_month(term_id, dates, values)
40
40
  return _measurement(result[0], result[1]) if len(result[0]) > 0 else None
41
41
 
42
42
 
@@ -3,7 +3,7 @@ from hestia_earth.utils.tools import flatten, non_empty_list
3
3
 
4
4
  from hestia_earth.models.log import logRequirements, logShouldRun
5
5
  from hestia_earth.models.utils.measurement import _new_measurement
6
- from .utils import _slice_by_year
6
+ from .utils import slice_by_year
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -26,7 +26,7 @@ MEASUREMENT_ID = 'precipitationMonthly'
26
26
 
27
27
 
28
28
  def _measurement(value: float, start_date: str, end_date: str):
29
- data = _new_measurement(TERM_ID)
29
+ data = _new_measurement(TERM_ID, MODEL)
30
30
  data['value'] = [value]
31
31
  data['startDate'] = start_date
32
32
  data['endDate'] = end_date
@@ -38,7 +38,7 @@ def _run(measurement: dict):
38
38
  values = measurement.get('value', [])
39
39
  dates = measurement.get('dates', [])
40
40
  term_id = measurement.get('term', {}).get('@id')
41
- results = _slice_by_year(term_id, dates, values)
41
+ results = slice_by_year(term_id, dates, values)
42
42
  return [_measurement(value, start_date, end_date) for (value, start_date, end_date) in results]
43
43
 
44
44
 
@@ -3,7 +3,7 @@ from hestia_earth.utils.tools import flatten, non_empty_list
3
3
 
4
4
  from hestia_earth.models.log import logRequirements, logShouldRun
5
5
  from hestia_earth.models.utils.measurement import _new_measurement
6
- from .utils import _group_by_month
6
+ from .utils import group_by_month
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -25,7 +25,7 @@ MEASUREMENT_ID = 'precipitationDaily'
25
25
 
26
26
 
27
27
  def _measurement(value: list, dates: list):
28
- data = _new_measurement(TERM_ID)
28
+ data = _new_measurement(TERM_ID, MODEL)
29
29
  data['value'] = value
30
30
  data['dates'] = dates
31
31
  data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
@@ -36,7 +36,7 @@ def _run(measurement: dict):
36
36
  values = measurement.get('value', [])
37
37
  dates = measurement.get('dates', [])
38
38
  term_id = measurement.get('term', {}).get('@id')
39
- result = _group_by_month(term_id, dates, values)
39
+ result = group_by_month(term_id, dates, values)
40
40
  return _measurement(result[0], result[1]) if len(result[0]) > 0 else None
41
41
 
42
42
 
@@ -3,7 +3,7 @@ from hestia_earth.utils.tools import flatten, non_empty_list
3
3
 
4
4
  from hestia_earth.models.log import logRequirements, logShouldRun
5
5
  from hestia_earth.models.utils.measurement import _new_measurement
6
- from .utils import _slice_by_year
6
+ from .utils import slice_by_year
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -26,7 +26,7 @@ MEASUREMENT_ID = 'rainfallMonthly'
26
26
 
27
27
 
28
28
  def _measurement(value: float, start_date: str, end_date: str):
29
- data = _new_measurement(TERM_ID)
29
+ data = _new_measurement(TERM_ID, MODEL)
30
30
  data['value'] = [value]
31
31
  data['startDate'] = start_date
32
32
  data['endDate'] = end_date
@@ -38,7 +38,7 @@ def _run(measurement: dict):
38
38
  values = measurement.get('value', [])
39
39
  dates = measurement.get('dates', [])
40
40
  term_id = measurement.get('term', {}).get('@id')
41
- results = _slice_by_year(term_id, dates, values)
41
+ results = slice_by_year(term_id, dates, values)
42
42
  return [_measurement(value, start_date, end_date) for (value, start_date, end_date) in results]
43
43
 
44
44
 
@@ -3,7 +3,7 @@ from hestia_earth.utils.tools import flatten, non_empty_list
3
3
 
4
4
  from hestia_earth.models.log import logRequirements, logShouldRun
5
5
  from hestia_earth.models.utils.measurement import _new_measurement
6
- from .utils import _group_by_month
6
+ from .utils import group_by_month
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -25,7 +25,7 @@ MEASUREMENT_ID = 'rainfallDaily'
25
25
 
26
26
 
27
27
  def _measurement(value: list, dates: list):
28
- data = _new_measurement(TERM_ID)
28
+ data = _new_measurement(TERM_ID, MODEL)
29
29
  data['value'] = value
30
30
  data['dates'] = dates
31
31
  data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
@@ -36,7 +36,7 @@ def _run(measurement: dict):
36
36
  values = measurement.get('value', [])
37
37
  dates = measurement.get('dates', [])
38
38
  term_id = measurement.get('term', {}).get('@id')
39
- result = _group_by_month(term_id, dates, values)
39
+ result = group_by_month(term_id, dates, values)
40
40
  return _measurement(result[0], result[1]) if len(result[0]) > 0 else None
41
41
 
42
42
 
@@ -36,7 +36,7 @@ TERM_ID = 'readyToCookWeightPerHead'
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
 
@@ -25,7 +25,7 @@ TERM_ID = 'residueBurnt'
25
25
 
26
26
 
27
27
  def _practice(value: float):
28
- practice = _new_practice(TERM_ID)
28
+ practice = _new_practice(TERM_ID, MODEL)
29
29
  practice['value'] = [value]
30
30
  return practice
31
31
 
@@ -35,7 +35,7 @@ TERM_ID = 'residueIncorporated'
35
35
 
36
36
 
37
37
  def _practice(value: float):
38
- practice = _new_practice(TERM_ID)
38
+ practice = _new_practice(TERM_ID, MODEL)
39
39
  practice['value'] = [value]
40
40
  return practice
41
41
 
@@ -25,7 +25,7 @@ TERM_ID = 'residueLeftOnField'
25
25
 
26
26
 
27
27
  def _practice(value: float):
28
- practice = _new_practice(TERM_ID)
28
+ practice = _new_practice(TERM_ID, MODEL)
29
29
  practice['value'] = [value]
30
30
  return practice
31
31
 
@@ -1,5 +1,5 @@
1
1
  from hestia_earth.schema import TermTermType
2
- from hestia_earth.utils.model import filter_list_term_type
2
+ from hestia_earth.utils.model import filter_list_term_type, find_term_match
3
3
  from hestia_earth.utils.tools import list_sum
4
4
 
5
5
  from hestia_earth.models.log import logRequirements, logShouldRun, log_as_table
@@ -11,14 +11,20 @@ from . import MODEL
11
11
  REQUIREMENTS = {
12
12
  "Cycle": {
13
13
  "completeness.cropResidue": "False",
14
- "practices": [{
15
- "@type": "Practice",
16
- "term.@id": [
17
- "residueIncorporated",
18
- "residueIncorporatedLessThan30DaysBeforeCultivation",
19
- "residueIncorporatedMoreThan30DaysBeforeCultivation"
14
+ "or": {
15
+ "practices": [{
16
+ "@type": "Practice",
17
+ "term.@id": [
18
+ "residueIncorporated",
19
+ "residueIncorporatedLessThan30DaysBeforeCultivation",
20
+ "residueIncorporatedMoreThan30DaysBeforeCultivation"
21
+ ]
22
+ }],
23
+ "products": [
24
+ {"@type": "Product", "term.@id": "aboveGroundCropResidueTotal", "value": "> 0"},
25
+ {"@type": "Product", "term.@id": "aboveGroundCropResidueRemoved", "value": "> 0"}
20
26
  ]
21
- }],
27
+ },
22
28
  "none": {
23
29
  "practices": [{
24
30
  "@type": "Practice",
@@ -45,14 +51,57 @@ def _practice(value: float):
45
51
  return practice
46
52
 
47
53
 
48
- def _should_run(cycle: dict):
54
+ def _run_by_products(cycle: dict):
55
+ products = cycle.get('products', [])
56
+ aboveGroundCropResidueTotal = list_sum(find_term_match(products, 'aboveGroundCropResidueTotal').get('value'))
57
+ aboveGroundCropResidueRemoved = list_sum(find_term_match(products, 'aboveGroundCropResidueRemoved').get('value'))
58
+ return [_practice(aboveGroundCropResidueRemoved / aboveGroundCropResidueTotal * 100)]
59
+
60
+
61
+ def _should_run_by_products(cycle: dict):
62
+ crop_residue_incomplete = _is_term_type_incomplete(cycle, TermTermType.CROPRESIDUE)
63
+ products = cycle.get('products', [])
64
+ aboveGroundCropResidueTotal = list_sum(find_term_match(products, 'aboveGroundCropResidueTotal').get('value', [0]))
65
+ has_aboveGroundCropResidueTotal = aboveGroundCropResidueTotal > 0
66
+ aboveGroundCropResidueRemoved = list_sum(
67
+ find_term_match(products, 'aboveGroundCropResidueRemoved').get('value', [0]))
68
+ has_aboveGroundCropResidueRemoved = aboveGroundCropResidueRemoved > 0
69
+
70
+ logRequirements(cycle, model=MODEL, term=TERM_ID,
71
+ term_type_cropResidue_incomplete=crop_residue_incomplete,
72
+ has_aboveGroundCropResidueTotal=has_aboveGroundCropResidueTotal,
73
+ has_aboveGroundCropResidueRemoved=has_aboveGroundCropResidueRemoved)
74
+
75
+ should_run = all([crop_residue_incomplete, has_aboveGroundCropResidueTotal, has_aboveGroundCropResidueRemoved])
76
+ logShouldRun(cycle, MODEL, TERM_ID, should_run)
77
+ return should_run
78
+
79
+
80
+ def _is_incorporated_practice(practice: dict):
81
+ return all([
82
+ practice.get('term', {}).get('@id').startswith('residueIncorporated'),
83
+ practice.get('term', {}).get('termType') == TermTermType.CROPRESIDUEMANAGEMENT.value,
84
+ not is_from_model(practice)
85
+ ])
86
+
87
+
88
+ def _run_by_practices(cycle: dict):
89
+ incorporated_value = list_sum([
90
+ list_sum(p.get('value'))
91
+ for p in cycle.get('practices', [])
92
+ if _is_incorporated_practice(p)
93
+ ])
94
+ return [_practice(100 - (incorporated_value or 0))]
95
+
96
+
97
+ def _should_run_by_practices(cycle: dict):
49
98
  crop_residue_incomplete = _is_term_type_incomplete(cycle, TermTermType.CROPRESIDUE)
50
99
 
51
100
  practices = filter_list_term_type(cycle.get('practices', []), TermTermType.CROPRESIDUEMANAGEMENT)
52
101
  incorporated_practices = [
53
102
  {'id': p.get('term', {}).get('@id'), 'value': list_sum(p.get('value'), None)}
54
103
  for p in practices
55
- if p.get('term', {}).get('@id').startswith('residueIncorporated') and not is_from_model(p)
104
+ if _is_incorporated_practice(p)
56
105
  ]
57
106
  has_other_practices = any([
58
107
  not p.get('term', {}).get('@id').startswith('residueIncorporated')
@@ -68,9 +117,12 @@ def _should_run(cycle: dict):
68
117
 
69
118
  should_run = all([crop_residue_incomplete, incorporated_value, not has_other_practices])
70
119
  logShouldRun(cycle, MODEL, TERM_ID, should_run)
71
- return should_run, 100 - (incorporated_value or 0)
120
+ return should_run
72
121
 
73
122
 
74
123
  def run(cycle: dict):
75
- should_run, value = _should_run(cycle)
76
- return [_practice(value)] if should_run else []
124
+ return (
125
+ _run_by_products(cycle) if _should_run_by_products(cycle) else
126
+ _run_by_practices(cycle) if _should_run_by_practices(cycle) else
127
+ []
128
+ )
@@ -22,7 +22,7 @@ TERM_ID = 'salineWater'
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
@@ -27,7 +27,7 @@ REQUIREMENTS = {
27
27
  "term.termType": "seed",
28
28
  "value": "> 0",
29
29
  "none": {
30
- "impactAssessment": "",
30
+ "impactAssessment": {"@type": "ImpactAssessment"},
31
31
  "fromCycle": "True",
32
32
  "producedInCycle": "True"
33
33
  }
@@ -32,7 +32,7 @@ STANDARD_DEPTHS = {(0, 30), (0, 50)}
32
32
 
33
33
 
34
34
  def _measurement(value: float, date: str, term_id: str, standard_fields: dict):
35
- data = _new_measurement(term=term_id)
35
+ data = _new_measurement(term_id)
36
36
  data["value"] = [value]
37
37
  data["depthUpper"] = standard_fields["depthUpper"]
38
38
  data["depthLower"] = standard_fields["depthLower"]
@@ -28,7 +28,7 @@ TERM_ID = 'stockingDensityAnimalHousingAverage'
28
28
 
29
29
 
30
30
  def _practice(value: float):
31
- practice = _new_practice(TERM_ID)
31
+ practice = _new_practice(TERM_ID, MODEL)
32
32
  practice['value'] = [round(value, 7)]
33
33
  return practice
34
34
 
@@ -3,7 +3,7 @@ from hestia_earth.utils.tools import flatten, non_empty_list
3
3
 
4
4
  from hestia_earth.models.log import logRequirements, logShouldRun
5
5
  from hestia_earth.models.utils.measurement import _new_measurement
6
- from .utils import _slice_by_year
6
+ from .utils import slice_by_year
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -26,7 +26,7 @@ MEASUREMENT_ID = 'temperatureMonthly'
26
26
 
27
27
 
28
28
  def _measurement(value: float, start_date: str, end_date: str):
29
- data = _new_measurement(TERM_ID)
29
+ data = _new_measurement(TERM_ID, MODEL)
30
30
  data['value'] = [value]
31
31
  data['startDate'] = start_date
32
32
  data['endDate'] = end_date
@@ -38,7 +38,7 @@ def _run(measurement: dict):
38
38
  values = measurement.get('value', [])
39
39
  dates = measurement.get('dates', [])
40
40
  term_id = measurement.get('term', {}).get('@id')
41
- results = _slice_by_year(term_id, dates, values)
41
+ results = slice_by_year(term_id, dates, values)
42
42
  return [_measurement(value, start_date, end_date) for (value, start_date, end_date) in results]
43
43
 
44
44
 
@@ -3,7 +3,7 @@ from hestia_earth.utils.tools import flatten, non_empty_list
3
3
 
4
4
  from hestia_earth.models.log import logRequirements, logShouldRun
5
5
  from hestia_earth.models.utils.measurement import _new_measurement
6
- from .utils import _group_by_month
6
+ from .utils import group_by_month
7
7
  from . import MODEL
8
8
 
9
9
  REQUIREMENTS = {
@@ -25,7 +25,7 @@ MEASUREMENT_ID = 'temperatureDaily'
25
25
 
26
26
 
27
27
  def _measurement(value: list, dates: list):
28
- data = _new_measurement(TERM_ID)
28
+ data = _new_measurement(TERM_ID, MODEL)
29
29
  data['value'] = value
30
30
  data['dates'] = dates
31
31
  data['methodClassification'] = MeasurementMethodClassification.MODELLED_USING_OTHER_MEASUREMENTS.value
@@ -36,7 +36,7 @@ def _run(measurement: dict):
36
36
  values = measurement.get('value', [])
37
37
  dates = measurement.get('dates', [])
38
38
  term_id = measurement.get('term', {}).get('@id')
39
- result = _group_by_month(term_id, dates, values)
39
+ result = group_by_month(term_id, dates, values)
40
40
  return _measurement(result[0], result[1]) if len(result[0]) > 0 else None
41
41
 
42
42
 
@@ -25,7 +25,7 @@ BIBLIO_TITLE = 'Reducing food’s environmental impacts through producers and co
25
25
 
26
26
 
27
27
  def _measurement(site: dict, value: float):
28
- data = _new_measurement(TERM_ID)
28
+ data = _new_measurement(TERM_ID, MODEL)
29
29
  data['value'] = [value]
30
30
  data['depthUpper'] = 0
31
31
  data['depthLower'] = 50
@@ -28,7 +28,7 @@ TERM_ID = 'unknownPreSeasonWaterRegime'
28
28
 
29
29
 
30
30
  def _practice():
31
- practice = _new_practice(TERM_ID)
31
+ practice = _new_practice(TERM_ID, MODEL)
32
32
  practice['value'] = [100]
33
33
  return practice
34
34
 
@@ -1,6 +1,11 @@
1
+ from functools import reduce
1
2
  from hestia_earth.schema import TermTermType
3
+ from hestia_earth.utils.tools import non_empty_list
4
+ from hestia_earth.utils.date import DAY
2
5
 
6
+ from hestia_earth.models.utils import _omit, first_day_of_month, last_day_of_month
3
7
  from hestia_earth.models.utils.term import get_lookup_value
8
+ from hestia_earth.models.utils.measurement import _new_measurement, measurement_value, has_all_months
4
9
  from . import MODEL
5
10
 
6
11
  IPCC_LAND_USE_CATEGORY_ANNUAL = "Annual crops"
@@ -45,3 +50,91 @@ def crop_ipcc_land_use_category(
45
50
  column='IPCC_LAND_USE_CATEGORY',
46
51
  model=MODEL
47
52
  )
53
+
54
+
55
+ def get_liveAnimal_term_id(product: dict, **log_ars):
56
+ term_id = get_lookup_value(product.get('term', {}), 'liveAnimalTermId', model=MODEL, **log_ars)
57
+ return term_id.split(';')[0] if term_id else None
58
+
59
+
60
+ def _value_func(data: dict, apply_func, key: str = 'value'):
61
+ values = data.get(key, data.get('value', []))
62
+ return list(map(apply_func, values))
63
+
64
+
65
+ def copy_measurement(term_id: str, data: dict):
66
+ measurement = _new_measurement(term_id, MODEL)
67
+ return _omit(data, ['description', 'method']) | measurement
68
+
69
+
70
+ def slice_by_year(term_id: str, dates: list, values: list):
71
+ def group_values(group: dict, index: int):
72
+ try:
73
+ date = dates[index]
74
+ value = values[index]
75
+ month = dates[index][0:4]
76
+ group[month] = group.get(month, []) + [(date, value)]
77
+ except IndexError:
78
+ pass
79
+ return group
80
+
81
+ def iterate_values(data: list):
82
+ return (
83
+ measurement_value({
84
+ 'term': {
85
+ '@id': term_id,
86
+ 'termType': TermTermType.MEASUREMENT.value
87
+ },
88
+ 'value': non_empty_list([v for (_d, v) in data])
89
+ }, is_larger_unit=True),
90
+ data[0][0],
91
+ data[-1][0]
92
+ ) if has_all_months([d for (d, _v) in data]) else None
93
+
94
+ values_by_month = reduce(group_values, range(0, len(dates)), {})
95
+ return non_empty_list(map(iterate_values, values_by_month.values()))
96
+
97
+
98
+ def _extract_year_month(date: str):
99
+ try:
100
+ year = int(date[0:4])
101
+ month = int(date[5:7])
102
+ return year, month
103
+ except Exception:
104
+ return None, None
105
+
106
+
107
+ def group_by_month(term_id: str, dates: list, values: list):
108
+ def group_values(group: dict, index: int):
109
+ date = dates[index]
110
+ value = values[index]
111
+ month = dates[index][0:7]
112
+ group[month] = group.get(month, []) + [(date, value)]
113
+ return group
114
+
115
+ def map_to_month(data: list, year: int, month: int):
116
+ # make sure we got all the necessary days
117
+ difference = last_day_of_month(year, month) - first_day_of_month(year, month)
118
+ days_in_month = round(difference.days + difference.seconds / DAY, 1) + 1
119
+
120
+ return measurement_value({
121
+ 'term': {
122
+ '@id': term_id,
123
+ 'termType': TermTermType.MEASUREMENT.value
124
+ },
125
+ 'value': non_empty_list([v for (_d, v) in data])
126
+ }, is_larger_unit=True) if len(data) == days_in_month else None
127
+
128
+ values_by_month = reduce(group_values, range(0, len(dates)), {}) if len(dates) == len(values) else {}
129
+
130
+ values = []
131
+ dates = []
132
+ for month, data in values_by_month.items():
133
+ year, m = _extract_year_month(data[0][0])
134
+ # date might not contain a year or a month, cannot handle it
135
+ value = map_to_month(data, year, m) if year and m else None
136
+ if value is not None:
137
+ dates.append(month)
138
+ values.append(value)
139
+
140
+ return values, dates