hestia-earth-models 0.72.2__py3-none-any.whl → 0.73.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 (144) hide show
  1. hestia_earth/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/__init__.py +1 -1
  2. hestia_earth/models/akagiEtAl2011/ch4ToAirCropResidueBurning.py +32 -0
  3. hestia_earth/models/akagiEtAl2011/nh3ToAirCropResidueBurning.py +32 -0
  4. hestia_earth/models/akagiEtAl2011/noxToAirCropResidueBurning.py +32 -0
  5. hestia_earth/models/akagiEtAl2011/pm25ToAirCropResidueBurning.py +32 -0
  6. hestia_earth/models/akagiEtAl2011/so2ToAirCropResidueBurning.py +32 -0
  7. hestia_earth/models/akagiEtAl2011/utils.py +45 -0
  8. hestia_earth/models/aware/scarcityWeightedWaterUse.py +10 -9
  9. hestia_earth/models/cache_sites.py +8 -4
  10. hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsLandTransformation.py +14 -11
  11. hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsTotalLandUseEffects.py +1 -1
  12. hestia_earth/models/chaudharyBrooks2018/utils.py +5 -3
  13. hestia_earth/models/config/Cycle.json +48 -7
  14. hestia_earth/models/config/ImpactAssessment.json +22 -0
  15. hestia_earth/models/cycle/completeness/electricityFuel.py +1 -1
  16. hestia_earth/models/cycle/completeness/freshForage.py +1 -1
  17. hestia_earth/models/cycle/completeness/soilAmendment.py +1 -1
  18. hestia_earth/models/cycle/input/hestiaAggregatedData.py +1 -2
  19. hestia_earth/models/cycle/product/economicValueShare.py +4 -2
  20. hestia_earth/models/cycle/product/price.py +35 -10
  21. hestia_earth/models/cycle/product/revenue.py +5 -2
  22. hestia_earth/models/dammgen2009/noxToAirExcreta.py +14 -18
  23. hestia_earth/models/ecoinventV3/__init__.py +11 -6
  24. hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +1 -1
  25. hestia_earth/models/emepEea2019/utils.py +2 -1
  26. hestia_earth/models/environmentalFootprintV3_1/environmentalFootprintSingleOverallScore.py +1 -1
  27. hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandOccupation.py +11 -11
  28. hestia_earth/models/environmentalFootprintV3_1/soilQualityIndexLandTransformation.py +14 -11
  29. hestia_earth/models/faostat2018/liveweightPerHead.py +1 -1
  30. hestia_earth/models/faostat2018/product/price.py +2 -2
  31. hestia_earth/models/faostat2018/seed.py +3 -2
  32. hestia_earth/models/faostat2018/utils.py +32 -18
  33. hestia_earth/models/geospatialDatabase/altitude.py +2 -1
  34. hestia_earth/models/geospatialDatabase/drainageClass.py +2 -1
  35. hestia_earth/models/geospatialDatabase/organicCarbonPerKgSoil.py +2 -1
  36. hestia_earth/models/geospatialDatabase/totalNitrogenPerKgSoil.py +2 -1
  37. hestia_earth/models/geospatialDatabase/totalPhosphorusPerKgSoil.py +2 -1
  38. hestia_earth/models/geospatialDatabase/utils.py +7 -5
  39. hestia_earth/models/globalCropWaterModel2008/rootingDepth.py +1 -1
  40. hestia_earth/models/hestia/brackishWater.py +1 -1
  41. hestia_earth/models/hestia/default_emissions.py +105 -0
  42. hestia_earth/models/hestia/default_resourceUse.py +110 -0
  43. hestia_earth/models/hestia/excretaKgMass.py +7 -9
  44. hestia_earth/models/hestia/freshWater.py +1 -1
  45. hestia_earth/models/hestia/inorganicFertiliser.py +12 -12
  46. hestia_earth/models/hestia/landCover.py +7 -5
  47. hestia_earth/models/hestia/landTransformation100YearAverageDuringCycle.py +3 -0
  48. hestia_earth/models/hestia/landTransformation20YearAverageDuringCycle.py +3 -0
  49. hestia_earth/models/hestia/liveAnimal.py +1 -1
  50. hestia_earth/models/hestia/management.py +1 -1
  51. hestia_earth/models/hestia/netPrimaryProduction.py +1 -1
  52. hestia_earth/models/hestia/organicCarbonPerHa.py +2 -2
  53. hestia_earth/models/hestia/salineWater.py +1 -1
  54. hestia_earth/models/hestia/seed_emissions.py +35 -21
  55. hestia_earth/models/hestia/stockingDensityAnimalHousingAverage.py +1 -1
  56. hestia_earth/models/hestia/totalNitrogenPerKgSoil.py +1 -1
  57. hestia_earth/models/hestia/waterSalinity.py +3 -2
  58. hestia_earth/models/ipcc2006/aboveGroundCropResidueRemoved.py +2 -2
  59. hestia_earth/models/ipcc2006/aboveGroundCropResidueTotal.py +10 -6
  60. hestia_earth/models/ipcc2006/belowGroundCropResidue.py +12 -8
  61. hestia_earth/models/ipcc2019/animal/utils.py +1 -1
  62. hestia_earth/models/ipcc2019/belowGroundCropResidue.py +1 -1
  63. hestia_earth/models/ipcc2019/carbonContent.py +1 -1
  64. hestia_earth/models/ipcc2019/ch4ToAirAquacultureSystems.py +18 -10
  65. hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +6 -6
  66. hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +4 -2
  67. hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +1 -1
  68. hestia_earth/models/ipcc2019/croppingDuration.py +4 -2
  69. hestia_earth/models/ipcc2019/ligninContent.py +1 -1
  70. hestia_earth/models/{akagiEtAl2011AndIpcc2006 → ipcc2019}/n2OToAirCropResidueBurningDirect.py +8 -4
  71. hestia_earth/models/ipcc2019/nitrogenContent.py +1 -1
  72. hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +6 -2
  73. hestia_earth/models/ipcc2019/pastureGrass_utils.py +13 -12
  74. hestia_earth/models/ipcc2019/utils.py +6 -2
  75. hestia_earth/models/koble2014/residueBurnt.py +6 -3
  76. hestia_earth/models/koble2014/residueRemoved.py +1 -1
  77. hestia_earth/models/mocking/search-results.json +1614 -1610
  78. hestia_earth/models/pooreNemecek2018/aboveGroundCropResidueTotal.py +1 -1
  79. hestia_earth/models/pooreNemecek2018/belowGroundCropResidue.py +1 -1
  80. hestia_earth/models/pooreNemecek2018/excretaKgVs.py +1 -1
  81. hestia_earth/models/pooreNemecek2018/freshwaterWithdrawalsDuringCycle.py +44 -6
  82. hestia_earth/models/pooreNemecek2018/longFallowDuration.py +1 -1
  83. hestia_earth/models/pooreNemecek2018/nurseryDensity.py +1 -1
  84. hestia_earth/models/pooreNemecek2018/nurseryDuration.py +1 -1
  85. hestia_earth/models/pooreNemecek2018/plantationDensity.py +1 -1
  86. hestia_earth/models/pooreNemecek2018/plantationLifespan.py +1 -1
  87. hestia_earth/models/pooreNemecek2018/plantationProductiveLifespan.py +3 -1
  88. hestia_earth/models/pooreNemecek2018/saplingsDepreciatedAmountPerCycle.py +1 -1
  89. hestia_earth/models/resourceUseNotRelevant/__init__.py +65 -0
  90. hestia_earth/models/schererPfister2015/nErosionSoilFlux.py +5 -3
  91. hestia_earth/models/schererPfister2015/pErosionSoilFlux.py +5 -3
  92. hestia_earth/models/schererPfister2015/utils.py +5 -4
  93. hestia_earth/models/site/grouped_measurement.py +1 -1
  94. hestia_earth/models/stehfestBouwman2006/n2OToAirSoilFlux_utils.py +1 -1
  95. hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirSoilFlux_utils.py +3 -3
  96. hestia_earth/models/utils/background_emissions.py +15 -11
  97. hestia_earth/models/utils/blank_node.py +6 -4
  98. hestia_earth/models/utils/crop.py +1 -1
  99. hestia_earth/models/utils/cropResidue.py +16 -0
  100. hestia_earth/models/utils/cycle.py +1 -1
  101. hestia_earth/models/utils/ecoClimateZone.py +2 -2
  102. hestia_earth/models/utils/excretaManagement.py +1 -1
  103. hestia_earth/models/utils/feedipedia.py +3 -3
  104. hestia_earth/models/utils/fertiliser.py +7 -1
  105. hestia_earth/models/utils/impact_assessment.py +29 -14
  106. hestia_earth/models/utils/inorganicFertiliser.py +2 -2
  107. hestia_earth/models/utils/input.py +34 -1
  108. hestia_earth/models/utils/liveAnimal.py +2 -2
  109. hestia_earth/models/utils/lookup.py +6 -2
  110. hestia_earth/models/utils/measurement.py +4 -4
  111. hestia_earth/models/utils/productivity.py +1 -1
  112. hestia_earth/models/utils/property.py +4 -2
  113. hestia_earth/models/utils/site.py +2 -1
  114. hestia_earth/models/version.py +1 -1
  115. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.1.dist-info}/METADATA +1 -1
  116. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.1.dist-info}/RECORD +138 -127
  117. tests/models/akagiEtAl2011/test_ch4ToAirCropResidueBurning.py +33 -0
  118. tests/models/akagiEtAl2011/test_nh3ToAirCropResidueBurning.py +33 -0
  119. tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/test_noxToAirCropResidueBurning.py +5 -17
  120. tests/models/akagiEtAl2011/test_pm25ToAirCropResidueBurning.py +33 -0
  121. tests/models/akagiEtAl2011/test_so2ToAirCropResidueBurning.py +33 -0
  122. tests/models/akagiEtAl2011/test_utils.py +18 -0
  123. tests/models/cycle/product/test_price.py +1 -11
  124. tests/models/dammgen2009/test_noxToAirExcreta.py +30 -10
  125. tests/models/geospatialDatabase/test_utils.py +2 -1
  126. tests/models/hestia/test_default_emissions.py +25 -0
  127. tests/models/hestia/test_default_resourceUse.py +26 -0
  128. tests/models/hestia/test_landCover.py +2 -2
  129. tests/models/ipcc2019/test_ch4ToAirAquacultureSystems.py +2 -2
  130. tests/models/{akagiEtAl2011AndIpcc2006/test_nh3ToAirCropResidueBurning.py → ipcc2019/test_n2OToAirCropResidueBurningDirect.py} +2 -2
  131. tests/models/pooreNemecek2018/test_freshwaterWithdrawalsDuringCycle.py +12 -0
  132. tests/models/test_resourceUseNotRelevant.py +27 -0
  133. tests/models/{akagiEtAl2011AndIpcc2006/test_utils.py → utils/test_cropResidue.py} +6 -6
  134. tests/models/utils/test_impact_assessment.py +29 -13
  135. hestia_earth/models/akagiEtAl2011AndIpcc2006/ch4ToAirCropResidueBurning.py +0 -57
  136. hestia_earth/models/akagiEtAl2011AndIpcc2006/nh3ToAirCropResidueBurning.py +0 -57
  137. hestia_earth/models/akagiEtAl2011AndIpcc2006/noxToAirCropResidueBurning.py +0 -57
  138. hestia_earth/models/akagiEtAl2011AndIpcc2006/utils.py +0 -15
  139. tests/models/akagiEtAl2011AndIpcc2006/test_ch4ToAirCropResidueBurning.py +0 -45
  140. tests/models/akagiEtAl2011AndIpcc2006/test_n2OToAirCropResidueBurningDirect.py +0 -46
  141. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.1.dist-info}/LICENSE +0 -0
  142. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.1.dist-info}/WHEEL +0 -0
  143. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.1.dist-info}/top_level.txt +0 -0
  144. /tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/__init__.py +0 -0
@@ -31,7 +31,7 @@ def _product(value: float):
31
31
 
32
32
  def _get_lookup_value(product: dict):
33
33
  term_id = product.get('term', {}).get('@id', '')
34
- return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
34
+ return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
35
35
 
36
36
 
37
37
  def _run(product: dict):
@@ -31,7 +31,7 @@ def _product(value: float):
31
31
 
32
32
  def _get_lookup_value(product: dict):
33
33
  term_id = product.get('term', {}).get('@id', '')
34
- return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
34
+ return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
35
35
 
36
36
 
37
37
  def _run(product: dict):
@@ -131,7 +131,7 @@ def _run(excreta_vs_products: list, excreta_n_products: list, mass_balance_items
131
131
  def _get_carbonContent(cycle: dict):
132
132
  primary_prod = find_primary_product(cycle) or {}
133
133
  return safe_parse_float(
134
- get_lookup_value(primary_prod.get('term', {}), 'carbonContent', model=MODEL, model_key=MODEL_KEY)
134
+ get_lookup_value(primary_prod.get('term', {}), 'carbonContent', model=MODEL, model_key=MODEL_KEY), default=0
135
135
  ) / 100
136
136
 
137
137
 
@@ -2,7 +2,7 @@ from hestia_earth.schema import TermTermType
2
2
  from hestia_earth.utils.tools import list_sum, safe_parse_float
3
3
  from hestia_earth.utils.model import filter_list_term_type
4
4
 
5
- from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
5
+ from hestia_earth.models.log import debugValues, logRequirements, logShouldRun, log_as_table
6
6
  from hestia_earth.models.utils.term import get_lookup_value
7
7
  from hestia_earth.models.utils.indicator import _new_indicator
8
8
  from hestia_earth.models.utils.impact_assessment import get_product, convert_value_from_cycle, get_site
@@ -25,6 +25,13 @@ REQUIREMENTS = {
25
25
  "completeness.water": "True",
26
26
  "inputs": [{"@type": "Input", "term.termType": "water", "value": "> 0"}]
27
27
  }
28
+ },
29
+ "optional": {
30
+ "practices": [{
31
+ "@type": "Practice",
32
+ "value": "> 0",
33
+ "term.termType": "waterRegime"
34
+ }]
28
35
  }
29
36
  }
30
37
  }
@@ -39,7 +46,8 @@ LOOKUPS = {
39
46
  "Conveyancing_Efficiency_Annual_crops",
40
47
  "Conveyancing_Efficiency_Permanent_crops",
41
48
  "Conveyancing_Efficiency_Perennial_crops"
42
- ]
49
+ ],
50
+ "waterRegime": "conveyancingEfficiency"
43
51
  }
44
52
  TERM_ID = 'freshwaterWithdrawalsDuringCycle'
45
53
 
@@ -50,19 +58,49 @@ def _indicator(term_id: str, value: float):
50
58
  return indicator
51
59
 
52
60
 
53
- def _get_conveyancing_efficiency(impact_assessment: dict, product: dict):
61
+ def _get_conveyancing_efficiency_from_waterRegime(impact_assessment: dict):
62
+ practices = filter_list_term_type(impact_assessment.get('cycle', {}).get('practices', []), TermTermType.WATERREGIME)
63
+ practices_with_factors = [
64
+ {
65
+ 'practice-id': p.get('term', {}).get('@id'),
66
+ 'practice-value': list_sum(p.get('value'), default=None),
67
+ 'conveyancing': safe_parse_float(
68
+ get_lookup_value(p.get('term', {}), 'conveyancingEfficiency'), default=None)
69
+ }
70
+ for p in practices
71
+ ]
72
+ total_practice_value = list_sum([p.get('practice-value', 0) for p in practices_with_factors])
73
+ conveyancing_from_practices = list_sum([
74
+ (p.get('practice-value') or 0) * (p.get('conveyancing', 0) or 0) for p in practices_with_factors
75
+ ]) / total_practice_value if total_practice_value > 0 else None
76
+ valid_waterRegime_practices = all([
77
+ p.get('conveyancing') is not None or p.get('practice-value', 0) == 0
78
+ for p in practices_with_factors
79
+ ])
80
+
81
+ debugValues(impact_assessment, model=MODEL, term=TERM_ID,
82
+ waterRegime_conveyancing_efficiency_values=log_as_table(practices_with_factors),
83
+ waterRegime_conveyancing_efficiency=conveyancing_from_practices)
84
+
85
+ return conveyancing_from_practices if valid_waterRegime_practices else None
86
+
87
+
88
+ def _get_conveyancing_efficiency_from_country(impact_assessment: dict, product: dict):
54
89
  site = get_site(impact_assessment)
55
90
  country = impact_assessment.get('country', {}) or site.get('country', {})
56
91
  grouping = get_crop_grouping_fao(MODEL, TERM_ID, product.get('term', {}))
57
92
  value = get_lookup_value(country, f"Conveyancing_Efficiency_{grouping}", model=MODEL, term=TERM_ID)
58
93
  debugValues(impact_assessment, model=MODEL, term=TERM_ID,
59
94
  grouping=grouping,
60
- conveyancing_efficiency=value)
61
- return safe_parse_float(value, 1)
95
+ country_conveyancing_efficiency=value)
96
+ return safe_parse_float(value, default=1)
62
97
 
63
98
 
64
99
  def _run(impact_assessment: dict, product: dict, irrigation: float):
65
- conveyancing = _get_conveyancing_efficiency(impact_assessment, product)
100
+ conveyancing = (
101
+ _get_conveyancing_efficiency_from_waterRegime(impact_assessment) or
102
+ _get_conveyancing_efficiency_from_country(impact_assessment, product)
103
+ )
66
104
  # convert from m3 to litre
67
105
  value = convert_value_from_cycle(
68
106
  impact_assessment,
@@ -29,7 +29,7 @@ def _practice(value: float):
29
29
 
30
30
  def _get_value(product: dict):
31
31
  term_id = product.get('term', {}).get('@id', '')
32
- return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
32
+ return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
33
33
 
34
34
 
35
35
  def _run(product: dict):
@@ -23,7 +23,7 @@ TERM_ID = 'nurseryDensity'
23
23
 
24
24
  def _get_value(product: dict):
25
25
  term_id = product.get('term', {}).get('@id', '')
26
- return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
26
+ return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
27
27
 
28
28
 
29
29
  def _practice(value: float):
@@ -29,7 +29,7 @@ def _practice(value: float):
29
29
 
30
30
  def _get_value(product: dict):
31
31
  term_id = product.get('term', {}).get('@id', '')
32
- return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
32
+ return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
33
33
 
34
34
 
35
35
  def run(cycle: dict):
@@ -29,7 +29,7 @@ def _practice(value: float):
29
29
 
30
30
  def _get_value(product: dict):
31
31
  term_id = product.get('term', {}).get('@id', '')
32
- return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
32
+ return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
33
33
 
34
34
 
35
35
  def run(cycle: dict):
@@ -23,7 +23,7 @@ TERM_ID = 'plantationLifespan'
23
23
 
24
24
  def _get_value(product: dict):
25
25
  term_id = product.get('term', {}).get('@id', '')
26
- return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
26
+ return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
27
27
 
28
28
 
29
29
  def _practice(value: float):
@@ -33,7 +33,9 @@ def _get_value(cycle: dict):
33
33
  def get(product: dict):
34
34
  term_id = product.get('term', {}).get('@id', '')
35
35
  plantationLifespan = get_plantationLifespan(product)
36
- nonProductiveLifespan = safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
36
+ nonProductiveLifespan = safe_parse_float(
37
+ get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None
38
+ )
37
39
  product_id = product.get('term').get('@id')
38
40
  product_id_logs = log_as_table({
39
41
  'plantationLifespan': plantationLifespan,
@@ -35,7 +35,7 @@ def _input(value: float):
35
35
 
36
36
  def _get_value(product: dict):
37
37
  term_id = product.get('term', {}).get('@id', '')
38
- return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), None)
38
+ return safe_parse_float(get_crop_lookup_value(MODEL, TERM_ID, term_id, LOOKUPS['crop']), default=None)
39
39
 
40
40
 
41
41
  def _run(product: dict, plantationLifespan: float, cycleDuration: float):
@@ -0,0 +1,65 @@
1
+ from hestia_earth.schema import IndicatorMethodTier, TermTermType
2
+ from hestia_earth.utils.lookup import download_lookup, lookup_term_ids
3
+ from hestia_earth.utils.lookup_utils import is_in_system_boundary
4
+
5
+ from hestia_earth.models.log import logRequirements, logShouldRun
6
+ from hestia_earth.models.utils.indicator import _new_indicator
7
+ from hestia_earth.models.utils.blank_node import _run_required
8
+ from hestia_earth.models.utils.impact_assessment import get_site
9
+ from hestia_earth.models.utils.site import get_land_cover_term_id
10
+
11
+ REQUIREMENTS = {
12
+ "ImpactAssessment": {
13
+ "emissionsResourceUse": [{"@type": "Indicator"}]
14
+ }
15
+ }
16
+ RETURNS = {
17
+ "Indicator": [{
18
+ "value": "0",
19
+ "methodTier": "not relevant"
20
+ }]
21
+ }
22
+ LOOKUPS = {
23
+ "resourceUse": [
24
+ "term.id",
25
+ "inHestiaDefaultSystemBoundary",
26
+ "siteTypesAllowed"
27
+ ]
28
+ }
29
+ MODEL = 'resourceUseNotRelevant'
30
+ TIER = IndicatorMethodTier.NOT_RELEVANT.value
31
+
32
+
33
+ def _indicator(term_id: str, land_cover_id: str):
34
+ indicator = _new_indicator(term_id, MODEL, land_cover_id)
35
+ indicator['value'] = 0
36
+ indicator['methodTier'] = TIER
37
+ return indicator
38
+
39
+
40
+ def _resourceUse_ids():
41
+ return lookup_term_ids(download_lookup(f"{TermTermType.RESOURCEUSE.value}.csv"))
42
+
43
+
44
+ def _should_run_resourceUse(impact: dict):
45
+ def run(term_id: str):
46
+ is_not_relevant = not _run_required(MODEL, term_id, impact.get('cycle', {}))
47
+ in_system_boundary = is_in_system_boundary(term_id)
48
+
49
+ should_run = all([is_not_relevant, in_system_boundary])
50
+ if should_run:
51
+ # no need to show the model failed
52
+ logRequirements(impact, model=MODEL, term=term_id,
53
+ is_not_relevant=is_not_relevant,
54
+ in_system_boundary=in_system_boundary,
55
+ run_required=False)
56
+ logShouldRun(impact, MODEL, term_id, should_run)
57
+ return should_run
58
+ return run
59
+
60
+
61
+ def run(_, impact: dict):
62
+ term_ids = _resourceUse_ids()
63
+ term_ids = list(filter(_should_run_resourceUse(impact), term_ids))
64
+ land_cover_term_id = get_land_cover_term_id(get_site(impact).get('siteType'))
65
+ return [_indicator(term_id, land_cover_term_id) for term_id in term_ids]
@@ -80,7 +80,7 @@ def _should_run(cycle: dict):
80
80
  measurements = site.get('measurements', [])
81
81
 
82
82
  def _get_measurement_content(term_id: str):
83
- return most_relevant_measurement_value(measurements, term_id, end_date)
83
+ return most_relevant_measurement_value(measurements, term_id, end_date, default=None)
84
84
 
85
85
  nla_environment = _get_measurement_content('nutrientLossToAquaticEnvironment')
86
86
  soil_nitrogen_content = _get_measurement_content('totalNitrogenPerKgSoil')
@@ -91,6 +91,7 @@ def _should_run(cycle: dict):
91
91
 
92
92
  precipitation = _get_measurement_content('precipitationAnnual')
93
93
  inputs_water = get_water_input(cycle)
94
+ total_water = list_sum([(inputs_water or 0)/10, precipitation or 0])
94
95
 
95
96
  practice_factor = get_practice_factor(TERM_ID, site)
96
97
  pcorr = get_pcorr(slope / 100) if slope is not None else None
@@ -100,7 +101,7 @@ def _should_run(cycle: dict):
100
101
  list_of_contents_for_A = [
101
102
  practice_factor, erodibility, slope_length,
102
103
  pcorr, p_ef_c1, ef_p_c2]
103
- list_of_contents_for_R = [heavy_winter_precipitation, list_sum([(inputs_water or 0)/10, precipitation or 0])]
104
+ list_of_contents_for_R = [heavy_winter_precipitation, total_water]
104
105
  list_of_contents_for_value = [nla_environment, soil_nitrogen_content]
105
106
 
106
107
  logRequirements(cycle, model=MODEL, term=TERM_ID,
@@ -118,8 +119,9 @@ def _should_run(cycle: dict):
118
119
  soil_nitrogen_content=soil_nitrogen_content)
119
120
 
120
121
  should_run = all([
122
+ heavy_winter_precipitation is not None,
123
+ total_water > 0,
121
124
  all(list_of_contents_for_A),
122
- all(list_of_contents_for_R),
123
125
  all(list_of_contents_for_value)
124
126
  ])
125
127
  logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
@@ -80,7 +80,7 @@ def _should_run(cycle: dict):
80
80
  measurements = site.get('measurements', [])
81
81
 
82
82
  def _get_measurement_content(term_id: str):
83
- return most_relevant_measurement_value(measurements, term_id, end_date)
83
+ return most_relevant_measurement_value(measurements, term_id, end_date, default=None)
84
84
 
85
85
  nla_environment = _get_measurement_content('nutrientLossToAquaticEnvironment')
86
86
  soil_phosphorus_content = _get_measurement_content('totalPhosphorusPerKgSoil')
@@ -91,6 +91,7 @@ def _should_run(cycle: dict):
91
91
 
92
92
  precipitation = _get_measurement_content('precipitationAnnual')
93
93
  inputs_water = get_water_input(cycle)
94
+ total_water = list_sum([(inputs_water or 0)/10, precipitation or 0])
94
95
 
95
96
  practice_factor = get_practice_factor(TERM_ID, site)
96
97
  pcorr = get_pcorr(slope / 100) if slope is not None else None
@@ -100,7 +101,7 @@ def _should_run(cycle: dict):
100
101
  list_of_contents_for_A = [
101
102
  practice_factor, erodibility, slope_length,
102
103
  pcorr, p_ef_c1, ef_p_c2]
103
- list_of_contents_for_R = [heavy_winter_precipitation, list_sum([(inputs_water or 0)/10, precipitation or 0])]
104
+ list_of_contents_for_R = [heavy_winter_precipitation, total_water]
104
105
  list_of_contents_for_value = [nla_environment, soil_phosphorus_content]
105
106
 
106
107
  logRequirements(cycle, model=MODEL, term=TERM_ID,
@@ -118,8 +119,9 @@ def _should_run(cycle: dict):
118
119
  soil_phosphorus_content=soil_phosphorus_content)
119
120
 
120
121
  should_run = all([
122
+ heavy_winter_precipitation is not None,
123
+ total_water > 0,
121
124
  all(list_of_contents_for_A),
122
- all(list_of_contents_for_R),
123
125
  all(list_of_contents_for_value)
124
126
  ])
125
127
  logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
@@ -43,25 +43,26 @@ def get_pcorr(slope: float):
43
43
 
44
44
 
45
45
  def _get_C2_factor(term_id: str, term: dict):
46
- return safe_parse_float(get_lookup_value(term, 'C2_FACTORS', model=MODEL, term=term_id), None)
46
+ return safe_parse_float(get_lookup_value(term, 'C2_FACTORS', model=MODEL, term=term_id), default=None)
47
47
 
48
48
 
49
49
  def get_practice_factor(term_id: str, site: dict):
50
50
  return safe_parse_float(
51
- get_lookup_value(site.get('country', {}), 'Practice_Factor', model=MODEL, term=term_id), None)
51
+ get_lookup_value(site.get('country', {}), 'Practice_Factor', model=MODEL, term=term_id), default=None)
52
52
 
53
53
 
54
54
  def get_p_ef_c1(term_id: str, cycle: dict):
55
55
  primary_product = find_primary_product(cycle) or {}
56
56
  return safe_parse_float(
57
- get_lookup_value(primary_product.get('term', {}), 'P_EF_C1', model=MODEL, term=term_id), None)
57
+ get_lookup_value(primary_product.get('term', {}), 'P_EF_C1', model=MODEL, term=term_id), default=None)
58
58
 
59
59
 
60
60
  def get_ef_p_c2(term_id: str, cycle: dict):
61
61
  tillage = _get_tillage(cycle)
62
62
  country = cycle.get('site', {}).get('country', {})
63
63
  return _get_C2_factor(term_id, tillage) if tillage else safe_parse_float(
64
- get_lookup_value(country, 'EF_P_C2', model=MODEL, term=term_id), None)
64
+ get_lookup_value(country, 'EF_P_C2', model=MODEL, term=term_id), default=None
65
+ )
65
66
 
66
67
 
67
68
  def get_water_input(cycle: dict):
@@ -5,7 +5,7 @@ from hestia_earth.utils.tools import non_empty_list, flatten, is_number, list_su
5
5
  from hestia_earth.models.log import logRequirements, logShouldRun
6
6
  from hestia_earth.models.utils import _include
7
7
  from hestia_earth.models.utils.measurement import _new_measurement
8
- from hestia_earth.models.utils.blank_node import get_lookup_value
8
+ from hestia_earth.models.utils.term import get_lookup_value
9
9
  from . import MODEL
10
10
 
11
11
  REQUIREMENTS = {
@@ -150,7 +150,7 @@ def _get_value(cycle: dict, content_list_of_items: list, N_total: float, term=TE
150
150
  sand_factor = _sand_factor(sand, clay)
151
151
  eco_factor = get_ecoClimateZone_lookup_value(ecoClimateZone, 'STEHFEST_BOUWMAN_2006_N2O-N_FACTOR')
152
152
  crop_grouping_factor = N2O_FACTORS_BY_CROP[crop_grouping]
153
- sum_factors = sum([carbon_factor, soil_factor, sand_factor, eco_factor, crop_grouping_factor])
153
+ sum_factors = sum([carbon_factor, soil_factor, sand_factor, eco_factor or 0, crop_grouping_factor])
154
154
  conversion_unit = get_atomic_conversion(Units.KG_N2O, Units.TO_N)
155
155
 
156
156
  try:
@@ -85,10 +85,10 @@ def _should_run(cycle: dict, term=TERM_ID, tier=TIER):
85
85
 
86
86
 
87
87
  def _get_value(cycle: dict, country: dict, N_total: float, term=TERM_ID):
88
- noxToAirSoilFlux = safe_parse_float(get_lookup_value(country, LOOKUPS['region'], model=MODEL, term=TERM_ID))
88
+ EF_NOX = safe_parse_float(get_lookup_value(country, LOOKUPS['region'], model=MODEL, term=TERM_ID), default=0)
89
89
  debugValues(cycle, model=MODEL, term=term,
90
- noxToAirSoilFlux=noxToAirSoilFlux)
91
- return noxToAirSoilFlux * N_total
90
+ EF_NOX=EF_NOX)
91
+ return EF_NOX * N_total
92
92
 
93
93
 
94
94
  def _run(cycle: dict, country: dict, N_total: float):
@@ -1,11 +1,11 @@
1
1
  from hestia_earth.schema import TermTermType
2
- from hestia_earth.utils.model import find_term_match
2
+ from hestia_earth.utils.model import find_term_match, filter_list_term_type
3
3
  from hestia_earth.utils.tools import flatten
4
4
  from hestia_earth.utils.emission import cycle_emissions_in_system_boundary
5
5
 
6
6
  from hestia_earth.models.log import logShouldRun
7
7
  from . import is_from_model
8
- from .blank_node import get_lookup_value
8
+ from .term import get_lookup_value
9
9
 
10
10
 
11
11
  def _animal_inputs(animal: dict):
@@ -35,8 +35,10 @@ def get_background_inputs(cycle: dict, extra_inputs: list = []):
35
35
  return list(filter(_should_run_input(cycle.get('products', [])), inputs))
36
36
 
37
37
 
38
- def no_gap_filled_background_emissions(cycle: dict):
39
- emissions = cycle.get('emissions', [])
38
+ def no_gap_filled_background_emissions(
39
+ node: dict, list_key: str = 'emissions', term_type: TermTermType = TermTermType.EMISSION
40
+ ):
41
+ blank_nodes = filter_list_term_type(node.get(list_key, []), term_type)
40
42
 
41
43
  def check_input(input: dict):
42
44
  input_term_id = input.get('term', {}).get('@id')
@@ -44,12 +46,12 @@ def no_gap_filled_background_emissions(cycle: dict):
44
46
  animal_term_id = input.get('animal', {}).get('@id')
45
47
 
46
48
  return not any([
47
- is_from_model(emission)
48
- for emission in emissions
49
+ is_from_model(blank_node)
50
+ for blank_node in blank_nodes
49
51
  if all([
50
- any([i.get('@id') == input_term_id for i in emission.get('inputs', [])]),
51
- emission.get('operation', {}).get('@id') == operation_term_id,
52
- emission.get('animal', {}).get('@id') == animal_term_id
52
+ any([i.get('@id') == input_term_id for i in blank_node.get('inputs', [])]),
53
+ blank_node.get('operation', {}).get('@id') == operation_term_id,
54
+ blank_node.get('animal', {}).get('@id') == animal_term_id
53
55
  ])
54
56
  ])
55
57
 
@@ -67,10 +69,12 @@ def all_background_emission_term_ids(cycle: dict):
67
69
  def log_missing_emissions(cycle: dict, **log_args):
68
70
  all_emission_term_ids = all_background_emission_term_ids(cycle)
69
71
 
70
- def log_input(input_term_id: str, included_emission_term_ids: list):
72
+ def log_input(input_term_id: str, included_emission_term_ids: list, **extra_log_args):
71
73
  missing_emission_term_ids = [
72
74
  term_id for term_id in all_emission_term_ids if term_id not in included_emission_term_ids
73
75
  ]
74
76
  for emission_id in missing_emission_term_ids:
75
- logShouldRun(cycle, term=input_term_id, should_run=False, emission_id=emission_id, **log_args)
77
+ logShouldRun(cycle, term=input_term_id, should_run=False, emission_id=emission_id,
78
+ **log_args,
79
+ **extra_log_args)
76
80
  return log_input
@@ -159,7 +159,7 @@ def _run_required(model: str, term_id: str, data: dict):
159
159
  input_id_allowed=input_id_allowed,
160
160
  input_termType_allowed=input_termType_allowed)
161
161
  # logging this for the model would cause issues parsing statuses
162
- if model != 'emissionNotRelevant':
162
+ if not model.endswith('NotRelevant'):
163
163
  debugValues(data, model=model, term=term_id, run_required=run_required)
164
164
  return run_required
165
165
 
@@ -1326,16 +1326,18 @@ def get_inputs_from_properties(input: dict, term_types: Union[TermTermType, List
1326
1326
  dict
1327
1327
  A dictionary of nodes grouped by latest date, in the format `{date: list[node]}`.
1328
1328
  """
1329
+ term = input.get('term', {})
1329
1330
  input_value = list_sum(input.get('value', []))
1330
1331
  properties = (
1331
1332
  input.get('properties') or
1332
- input.get('term', {}).get('defaultProperties') or
1333
- download_term(input.get('term', {})).get('defaultProperties')
1333
+ term.get('defaultProperties') or
1334
+ download_term(term).get('defaultProperties')
1334
1335
  )
1335
1336
  inputs = non_empty_list([
1336
1337
  {
1337
1338
  'term': p.get('key'),
1338
- 'value': [(p.get('value') / 100) * (p.get('share', 100) / 100) * input_value]
1339
+ 'value': [(p.get('value') / 100) * (p.get('share', 100) / 100) * input_value],
1340
+ 'parent': term
1339
1341
  } for p in (properties or []) if all([p.get('key'), p.get('value')])
1340
1342
  ]) if input_value > 0 else []
1341
1343
  return filter_list_term_type(inputs, term_types)
@@ -30,7 +30,7 @@ def get_N2ON_fertiliser_coeff_from_primary_product(model: str, log_id: str, cycl
30
30
  product = find_primary_product(cycle)
31
31
  term_id = product.get('term', {}).get('@id') if product else None
32
32
  percent = get_crop_lookup_value(model, log_id, term_id, 'N2ON_FERT') if term_id else None
33
- return safe_parse_float(percent, 0.01)
33
+ return safe_parse_float(percent, default=0.01)
34
34
 
35
35
 
36
36
  def is_plantation(model: str, log_id: str, term_id: str):
@@ -1,3 +1,9 @@
1
+ from hestia_earth.schema import TermTermType
2
+ from hestia_earth.utils.model import find_term_match
3
+ from hestia_earth.utils.tools import flatten
4
+
5
+ from .completeness import _is_term_type_complete
6
+
1
7
  PRODUCT_ID_TO_PRACTICES_ID = [
2
8
  {'product': 'aboveGroundCropResidueRemoved', 'practices': ['residueRemoved']},
3
9
  {'product': 'aboveGroundCropResidueIncorporated', 'practices': [
@@ -11,3 +17,13 @@ PRODUCT_ID_TO_PRACTICES_ID = [
11
17
 
12
18
 
13
19
  def crop_residue_product_ids(): return [v.get('product') for v in PRODUCT_ID_TO_PRACTICES_ID]
20
+
21
+
22
+ def get_crop_residue_burnt_value(cycle: dict):
23
+ products = cycle.get('products', [])
24
+ value = flatten([
25
+ find_term_match(products, 'aboveGroundCropResidueBurnt').get('value', []),
26
+ find_term_match(products, 'discardedCropBurnt').get('value', [])
27
+ ])
28
+ data_complete = _is_term_type_complete(cycle, TermTermType.CROPRESIDUE)
29
+ return [0] if len(value) == 0 and data_complete else value
@@ -204,7 +204,7 @@ def get_inorganic_fertiliser_P_total(cycle: dict) -> float:
204
204
 
205
205
  def get_max_rooting_depth(cycle: dict) -> float:
206
206
  properties = list(map(lambda p: get_node_property(p, 'rootingDepth'), cycle.get('products', [])))
207
- values = [safe_parse_float(p.get('value')) for p in properties if p.get('value') is not None]
207
+ values = [safe_parse_float(p.get('value'), default=0) for p in properties if p.get('value') is not None]
208
208
  return max(values) if len(values) > 0 else None
209
209
 
210
210
 
@@ -87,7 +87,7 @@ def get_ecoClimateZone_lookup_value(eco_climate_zone: str, col_name: str, group_
87
87
  code = int(str(eco_climate_zone))
88
88
  data = _get_single_table_value(lookup, column_name('ecoClimateZone'), code, column_name(col_name))
89
89
  return safe_parse_float(
90
- data if group_name is None else extract_grouped_data(data, group_name)
90
+ data if group_name is None else extract_grouped_data(data, group_name), default=None
91
91
  )
92
92
  except Exception:
93
93
  return 0
@@ -118,7 +118,7 @@ def get_ecoClimateZone_lookup_grouped_value(
118
118
  code = int(str(eco_climate_zone))
119
119
  data = _get_single_table_value(lookup, column_name('ecoClimateZone'), code, column_name(col_name))
120
120
  grouped_data = reduce(
121
- lambda prev, curr: prev | {curr.split(':')[0]: safe_parse_float(curr.split(':')[1])},
121
+ lambda prev, curr: prev | {curr.split(':')[0]: safe_parse_float(curr.split(':')[1], default=None)},
122
122
  data.split(';'),
123
123
  {}
124
124
  ) if data is not None and isinstance(data, str) and len(data) > 1 else default
@@ -19,7 +19,7 @@ def _get_nh3_factor(lookup_name: str, term_id: str, input: dict, **log_args):
19
19
  input_term_id = input.get('term', {}).get('@id')
20
20
  value = get_table_value(download_lookup(lookup_name), 'termid', term_id, column_name(input_term_id))
21
21
  debugMissingLookup(lookup_name, 'termid', term_id, input_term_id, value, **log_args)
22
- return safe_parse_float(value, None)
22
+ return safe_parse_float(value, default=None)
23
23
 
24
24
 
25
25
  def get_excreta_inputs_with_factor(cycle: dict, lookup_name: str, excreta_conversion_func, **log_args):
@@ -27,9 +27,9 @@ def _should_rescale_by_dm(property_id: str):
27
27
  def _dm_property(term_id: str, property_values: dict, dm_property_values: dict, dry_matter_property: dict):
28
28
  blank_node_data = {}
29
29
  for property_key in property_values.keys():
30
- new_dm_value = safe_parse_float(dry_matter_property.get(property_key))
31
- old_dm_value = safe_parse_float(dm_property_values.get(property_key))
32
- old_property_value = safe_parse_float(property_values.get(property_key))
30
+ new_dm_value = safe_parse_float(dry_matter_property.get(property_key), default=None)
31
+ old_dm_value = safe_parse_float(dm_property_values.get(property_key), default=None)
32
+ old_property_value = safe_parse_float(property_values.get(property_key), default=None)
33
33
  if all([new_dm_value, old_dm_value, old_property_value]):
34
34
  new_value = round(
35
35
  old_property_value / old_dm_value * new_dm_value,
@@ -5,7 +5,13 @@ from hestia_earth.utils.tools import flatten
5
5
 
6
6
  from .blank_node import get_inputs_from_properties
7
7
 
8
- _TERM_TYPES = [TermTermType.INORGANICFERTILISER, TermTermType.ORGANICFERTILISER]
8
+ _TERM_TYPES = [
9
+ TermTermType.INORGANICFERTILISER,
10
+ TermTermType.ORGANICFERTILISER,
11
+ TermTermType.OTHERINORGANICCHEMICAL,
12
+ TermTermType.OTHERORGANICCHEMICAL,
13
+ TermTermType.PESTICIDEAI
14
+ ]
9
15
 
10
16
 
11
17
  def get_fertilisers_from_inputs(cycle: dict, term_types: Union[TermTermType, List[TermTermType]] = _TERM_TYPES):