hestia-earth-models 0.72.2__py3-none-any.whl → 0.73.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) 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 +2 -2
  9. hestia_earth/models/chaudharyBrooks2018/damageToTerrestrialEcosystemsTotalLandUseEffects.py +1 -1
  10. hestia_earth/models/chaudharyBrooks2018/utils.py +1 -1
  11. hestia_earth/models/config/Cycle.json +48 -7
  12. hestia_earth/models/config/ImpactAssessment.json +22 -0
  13. hestia_earth/models/cycle/completeness/soilAmendment.py +1 -1
  14. hestia_earth/models/cycle/product/economicValueShare.py +3 -1
  15. hestia_earth/models/cycle/product/price.py +35 -10
  16. hestia_earth/models/cycle/product/revenue.py +5 -2
  17. hestia_earth/models/dammgen2009/noxToAirExcreta.py +14 -18
  18. hestia_earth/models/ecoinventV3/__init__.py +11 -6
  19. hestia_earth/models/ecoinventV3AndEmberClimate/utils.py +1 -1
  20. hestia_earth/models/emepEea2019/utils.py +2 -1
  21. hestia_earth/models/faostat2018/liveweightPerHead.py +1 -1
  22. hestia_earth/models/faostat2018/product/price.py +2 -2
  23. hestia_earth/models/faostat2018/seed.py +3 -2
  24. hestia_earth/models/faostat2018/utils.py +6 -5
  25. hestia_earth/models/geospatialDatabase/altitude.py +2 -1
  26. hestia_earth/models/geospatialDatabase/drainageClass.py +2 -1
  27. hestia_earth/models/geospatialDatabase/organicCarbonPerKgSoil.py +2 -1
  28. hestia_earth/models/geospatialDatabase/totalNitrogenPerKgSoil.py +2 -1
  29. hestia_earth/models/geospatialDatabase/totalPhosphorusPerKgSoil.py +2 -1
  30. hestia_earth/models/geospatialDatabase/utils.py +1 -1
  31. hestia_earth/models/globalCropWaterModel2008/rootingDepth.py +1 -1
  32. hestia_earth/models/hestia/brackishWater.py +1 -1
  33. hestia_earth/models/hestia/default_emissions.py +105 -0
  34. hestia_earth/models/hestia/default_resourceUse.py +110 -0
  35. hestia_earth/models/hestia/freshWater.py +1 -1
  36. hestia_earth/models/hestia/inorganicFertiliser.py +12 -12
  37. hestia_earth/models/hestia/landCover.py +7 -5
  38. hestia_earth/models/hestia/landTransformation100YearAverageDuringCycle.py +3 -0
  39. hestia_earth/models/hestia/landTransformation20YearAverageDuringCycle.py +3 -0
  40. hestia_earth/models/hestia/liveAnimal.py +1 -1
  41. hestia_earth/models/hestia/management.py +1 -1
  42. hestia_earth/models/hestia/netPrimaryProduction.py +1 -1
  43. hestia_earth/models/hestia/organicCarbonPerHa.py +2 -2
  44. hestia_earth/models/hestia/salineWater.py +1 -1
  45. hestia_earth/models/hestia/seed_emissions.py +34 -20
  46. hestia_earth/models/hestia/totalNitrogenPerKgSoil.py +1 -1
  47. hestia_earth/models/hestia/waterSalinity.py +2 -1
  48. hestia_earth/models/ipcc2006/aboveGroundCropResidueRemoved.py +2 -2
  49. hestia_earth/models/ipcc2006/aboveGroundCropResidueTotal.py +10 -6
  50. hestia_earth/models/ipcc2006/belowGroundCropResidue.py +12 -8
  51. hestia_earth/models/ipcc2019/animal/utils.py +1 -1
  52. hestia_earth/models/ipcc2019/belowGroundCropResidue.py +1 -1
  53. hestia_earth/models/ipcc2019/carbonContent.py +1 -1
  54. hestia_earth/models/ipcc2019/ch4ToAirAquacultureSystems.py +17 -9
  55. hestia_earth/models/ipcc2019/ch4ToAirEntericFermentation.py +6 -6
  56. hestia_earth/models/ipcc2019/ch4ToAirExcreta.py +4 -2
  57. hestia_earth/models/ipcc2019/co2ToAirUreaHydrolysis.py +1 -1
  58. hestia_earth/models/ipcc2019/croppingDuration.py +4 -2
  59. hestia_earth/models/ipcc2019/ligninContent.py +1 -1
  60. hestia_earth/models/{akagiEtAl2011AndIpcc2006 → ipcc2019}/n2OToAirCropResidueBurningDirect.py +8 -4
  61. hestia_earth/models/ipcc2019/nitrogenContent.py +1 -1
  62. hestia_earth/models/ipcc2019/nonCo2EmissionsToAirNaturalVegetationBurning.py +6 -2
  63. hestia_earth/models/ipcc2019/pastureGrass_utils.py +13 -12
  64. hestia_earth/models/ipcc2019/utils.py +6 -2
  65. hestia_earth/models/koble2014/residueBurnt.py +6 -3
  66. hestia_earth/models/koble2014/residueRemoved.py +1 -1
  67. hestia_earth/models/mocking/search-results.json +1577 -1573
  68. hestia_earth/models/pooreNemecek2018/aboveGroundCropResidueTotal.py +1 -1
  69. hestia_earth/models/pooreNemecek2018/belowGroundCropResidue.py +1 -1
  70. hestia_earth/models/pooreNemecek2018/excretaKgVs.py +1 -1
  71. hestia_earth/models/pooreNemecek2018/freshwaterWithdrawalsDuringCycle.py +1 -1
  72. hestia_earth/models/pooreNemecek2018/longFallowDuration.py +1 -1
  73. hestia_earth/models/pooreNemecek2018/nurseryDensity.py +1 -1
  74. hestia_earth/models/pooreNemecek2018/nurseryDuration.py +1 -1
  75. hestia_earth/models/pooreNemecek2018/plantationDensity.py +1 -1
  76. hestia_earth/models/pooreNemecek2018/plantationLifespan.py +1 -1
  77. hestia_earth/models/pooreNemecek2018/plantationProductiveLifespan.py +3 -1
  78. hestia_earth/models/pooreNemecek2018/saplingsDepreciatedAmountPerCycle.py +1 -1
  79. hestia_earth/models/resourceUseNotRelevant/__init__.py +65 -0
  80. hestia_earth/models/schererPfister2015/nErosionSoilFlux.py +5 -3
  81. hestia_earth/models/schererPfister2015/pErosionSoilFlux.py +5 -3
  82. hestia_earth/models/schererPfister2015/utils.py +5 -4
  83. hestia_earth/models/stehfestBouwman2006/n2OToAirSoilFlux_utils.py +1 -1
  84. hestia_earth/models/stehfestBouwman2006GisImplementation/noxToAirSoilFlux_utils.py +3 -3
  85. hestia_earth/models/utils/background_emissions.py +14 -10
  86. hestia_earth/models/utils/blank_node.py +6 -4
  87. hestia_earth/models/utils/crop.py +1 -1
  88. hestia_earth/models/utils/cropResidue.py +16 -0
  89. hestia_earth/models/utils/cycle.py +1 -1
  90. hestia_earth/models/utils/ecoClimateZone.py +2 -2
  91. hestia_earth/models/utils/excretaManagement.py +1 -1
  92. hestia_earth/models/utils/feedipedia.py +3 -3
  93. hestia_earth/models/utils/fertiliser.py +7 -1
  94. hestia_earth/models/utils/inorganicFertiliser.py +2 -2
  95. hestia_earth/models/utils/input.py +34 -1
  96. hestia_earth/models/utils/liveAnimal.py +2 -2
  97. hestia_earth/models/utils/lookup.py +1 -1
  98. hestia_earth/models/utils/measurement.py +5 -4
  99. hestia_earth/models/utils/productivity.py +1 -1
  100. hestia_earth/models/utils/property.py +4 -2
  101. hestia_earth/models/utils/site.py +2 -1
  102. hestia_earth/models/version.py +1 -1
  103. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/METADATA +1 -1
  104. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/RECORD +124 -113
  105. tests/models/akagiEtAl2011/test_ch4ToAirCropResidueBurning.py +33 -0
  106. tests/models/akagiEtAl2011/test_nh3ToAirCropResidueBurning.py +33 -0
  107. tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/test_noxToAirCropResidueBurning.py +5 -17
  108. tests/models/akagiEtAl2011/test_pm25ToAirCropResidueBurning.py +33 -0
  109. tests/models/akagiEtAl2011/test_so2ToAirCropResidueBurning.py +33 -0
  110. tests/models/akagiEtAl2011/test_utils.py +18 -0
  111. tests/models/cycle/product/test_price.py +1 -11
  112. tests/models/dammgen2009/test_noxToAirExcreta.py +30 -10
  113. tests/models/geospatialDatabase/test_utils.py +2 -1
  114. tests/models/hestia/test_default_emissions.py +25 -0
  115. tests/models/hestia/test_default_resourceUse.py +26 -0
  116. tests/models/hestia/test_landCover.py +2 -2
  117. tests/models/ipcc2019/test_ch4ToAirAquacultureSystems.py +2 -2
  118. tests/models/{akagiEtAl2011AndIpcc2006/test_nh3ToAirCropResidueBurning.py → ipcc2019/test_n2OToAirCropResidueBurningDirect.py} +2 -2
  119. tests/models/test_resourceUseNotRelevant.py +27 -0
  120. tests/models/{akagiEtAl2011AndIpcc2006/test_utils.py → utils/test_cropResidue.py} +6 -6
  121. hestia_earth/models/akagiEtAl2011AndIpcc2006/ch4ToAirCropResidueBurning.py +0 -57
  122. hestia_earth/models/akagiEtAl2011AndIpcc2006/nh3ToAirCropResidueBurning.py +0 -57
  123. hestia_earth/models/akagiEtAl2011AndIpcc2006/noxToAirCropResidueBurning.py +0 -57
  124. hestia_earth/models/akagiEtAl2011AndIpcc2006/utils.py +0 -15
  125. tests/models/akagiEtAl2011AndIpcc2006/test_ch4ToAirCropResidueBurning.py +0 -45
  126. tests/models/akagiEtAl2011AndIpcc2006/test_n2OToAirCropResidueBurningDirect.py +0 -46
  127. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/LICENSE +0 -0
  128. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/WHEEL +0 -0
  129. {hestia_earth_models-0.72.2.dist-info → hestia_earth_models-0.73.0.dist-info}/top_level.txt +0 -0
  130. /tests/models/{akagiEtAl2011AndIpcc2006 → akagiEtAl2011}/__init__.py +0 -0
@@ -6,7 +6,7 @@ from hestia_earth.models.utils.blank_node import run_if_required
6
6
 
7
7
  CURRENT_DIR = dirname(abspath(__file__)) + '/'
8
8
  sys.path.append(CURRENT_DIR)
9
- MODEL = 'akagiEtAl2011AndIpcc2006'
9
+ MODEL = 'akagiEtAl2011'
10
10
  PKG = '.'.join(['hestia_earth', 'models', MODEL])
11
11
 
12
12
 
@@ -0,0 +1,32 @@
1
+ from hestia_earth.schema import EmissionMethodTier
2
+
3
+ from .utils import run_emission
4
+
5
+ REQUIREMENTS = {
6
+ "Cycle": {
7
+ "or": {
8
+ "products": [{
9
+ "@type": "Product",
10
+ "term.@id": ["aboveGroundCropResidueBurnt", "discardedCropBurnt"],
11
+ "value": ""
12
+ }],
13
+ "completeness.cropResidue": "True"
14
+ }
15
+ }
16
+ }
17
+ RETURNS = {
18
+ "Emission": [{
19
+ "value": "",
20
+ "sd": "",
21
+ "methodTier": "tier 1",
22
+ "statsDefinition": "modelled"
23
+ }]
24
+ }
25
+ LOOKUPS = {
26
+ "emission": ["akagiEtAl2011CropResidueBurningFactor", "akagiEtAl2011CropResidueBurningFactor-sd"]
27
+ }
28
+ TERM_ID = 'ch4ToAirCropResidueBurning'
29
+ TIER = EmissionMethodTier.TIER_1.value
30
+
31
+
32
+ def run(cycle: dict): return run_emission(TERM_ID, cycle)
@@ -0,0 +1,32 @@
1
+ from hestia_earth.schema import EmissionMethodTier
2
+
3
+ from .utils import run_emission
4
+
5
+ REQUIREMENTS = {
6
+ "Cycle": {
7
+ "or": {
8
+ "products": [{
9
+ "@type": "Product",
10
+ "term.@id": ["aboveGroundCropResidueBurnt", "discardedCropBurnt"],
11
+ "value": ""
12
+ }],
13
+ "completeness.cropResidue": "True"
14
+ }
15
+ }
16
+ }
17
+ RETURNS = {
18
+ "Emission": [{
19
+ "value": "",
20
+ "sd": "",
21
+ "methodTier": "tier 1",
22
+ "statsDefinition": "modelled"
23
+ }]
24
+ }
25
+ LOOKUPS = {
26
+ "emission": ["akagiEtAl2011CropResidueBurningFactor", "akagiEtAl2011CropResidueBurningFactor-sd"]
27
+ }
28
+ TERM_ID = 'nh3ToAirCropResidueBurning'
29
+ TIER = EmissionMethodTier.TIER_1.value
30
+
31
+
32
+ def run(cycle: dict): return run_emission(TERM_ID, cycle)
@@ -0,0 +1,32 @@
1
+ from hestia_earth.schema import EmissionMethodTier
2
+
3
+ from .utils import run_emission
4
+
5
+ REQUIREMENTS = {
6
+ "Cycle": {
7
+ "or": {
8
+ "products": [{
9
+ "@type": "Product",
10
+ "term.@id": ["aboveGroundCropResidueBurnt", "discardedCropBurnt"],
11
+ "value": ""
12
+ }],
13
+ "completeness.cropResidue": "True"
14
+ }
15
+ }
16
+ }
17
+ RETURNS = {
18
+ "Emission": [{
19
+ "value": "",
20
+ "sd": "",
21
+ "methodTier": "tier 1",
22
+ "statsDefinition": "modelled"
23
+ }]
24
+ }
25
+ LOOKUPS = {
26
+ "emission": ["akagiEtAl2011CropResidueBurningFactor", "akagiEtAl2011CropResidueBurningFactor-sd"]
27
+ }
28
+ TERM_ID = 'noxToAirCropResidueBurning'
29
+ TIER = EmissionMethodTier.TIER_1.value
30
+
31
+
32
+ def run(cycle: dict): return run_emission(TERM_ID, cycle)
@@ -0,0 +1,32 @@
1
+ from hestia_earth.schema import EmissionMethodTier
2
+
3
+ from .utils import run_emission
4
+
5
+ REQUIREMENTS = {
6
+ "Cycle": {
7
+ "or": {
8
+ "products": [{
9
+ "@type": "Product",
10
+ "term.@id": ["aboveGroundCropResidueBurnt", "discardedCropBurnt"],
11
+ "value": ""
12
+ }],
13
+ "completeness.cropResidue": "True"
14
+ }
15
+ }
16
+ }
17
+ RETURNS = {
18
+ "Emission": [{
19
+ "value": "",
20
+ "sd": "",
21
+ "methodTier": "tier 1",
22
+ "statsDefinition": "modelled"
23
+ }]
24
+ }
25
+ LOOKUPS = {
26
+ "emission": ["akagiEtAl2011CropResidueBurningFactor", "akagiEtAl2011CropResidueBurningFactor-sd"]
27
+ }
28
+ TERM_ID = 'pm25ToAirCropResidueBurning'
29
+ TIER = EmissionMethodTier.TIER_1.value
30
+
31
+
32
+ def run(cycle: dict): return run_emission(TERM_ID, cycle)
@@ -0,0 +1,32 @@
1
+ from hestia_earth.schema import EmissionMethodTier
2
+
3
+ from .utils import run_emission
4
+
5
+ REQUIREMENTS = {
6
+ "Cycle": {
7
+ "or": {
8
+ "products": [{
9
+ "@type": "Product",
10
+ "term.@id": ["aboveGroundCropResidueBurnt", "discardedCropBurnt"],
11
+ "value": ""
12
+ }],
13
+ "completeness.cropResidue": "True"
14
+ }
15
+ }
16
+ }
17
+ RETURNS = {
18
+ "Emission": [{
19
+ "value": "",
20
+ "sd": "",
21
+ "methodTier": "tier 1",
22
+ "statsDefinition": "modelled"
23
+ }]
24
+ }
25
+ LOOKUPS = {
26
+ "emission": ["akagiEtAl2011CropResidueBurningFactor", "akagiEtAl2011CropResidueBurningFactor-sd"]
27
+ }
28
+ TERM_ID = 'so2ToAirCropResidueBurning'
29
+ TIER = EmissionMethodTier.TIER_1.value
30
+
31
+
32
+ def run(cycle: dict): return run_emission(TERM_ID, cycle)
@@ -0,0 +1,45 @@
1
+ from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition, TermTermType
2
+
3
+ from hestia_earth.models.log import logRequirements, logShouldRun
4
+ from hestia_earth.models.utils.emission import _new_emission
5
+ from hestia_earth.models.utils.blank_node import get_lookup_value
6
+ from hestia_earth.models.utils.cropResidue import get_crop_residue_burnt_value
7
+ from . import MODEL
8
+
9
+ TIER = EmissionMethodTier.TIER_1.value
10
+ LOOKUP_NAME = 'akagiEtAl2011CropResidueBurningFactor'
11
+
12
+
13
+ def _emission(term_id: str, value: float, sd: float = None):
14
+ emission = _new_emission(term_id, MODEL)
15
+ emission['value'] = [value]
16
+ emission['methodTier'] = TIER
17
+ if sd is not None:
18
+ emission['sd'] = [sd]
19
+ emission['statsDefinition'] = EmissionStatsDefinition.MODELLED.value
20
+ return emission
21
+
22
+
23
+ def _run(term_id: str, product_value: list):
24
+ value = sum(product_value)
25
+ term = {'termType': TermTermType.EMISSION.value, '@id': term_id}
26
+ factor = get_lookup_value(term, LOOKUP_NAME)
27
+ factor_sd = get_lookup_value(term, LOOKUP_NAME + '-sd')
28
+ return [_emission(term_id, value * factor, value * factor_sd)]
29
+
30
+
31
+ def _should_run(term_id: str, cycle: dict):
32
+ crop_residue_burnt_value = get_crop_residue_burnt_value(cycle)
33
+ has_crop_residue_burnt = len(crop_residue_burnt_value) > 0
34
+
35
+ logRequirements(cycle, model=MODEL, term=term_id,
36
+ has_crop_residue_burnt=has_crop_residue_burnt)
37
+
38
+ should_run = all([has_crop_residue_burnt])
39
+ logShouldRun(cycle, MODEL, term_id, should_run, methodTier=TIER)
40
+ return should_run, crop_residue_burnt_value
41
+
42
+
43
+ def run_emission(term_id: str, cycle: dict):
44
+ should_run, crop_residue_burnt_value = _should_run(term_id, cycle)
45
+ return _run(term_id, crop_residue_burnt_value) if should_run else []
@@ -61,7 +61,7 @@ def _get_factor_from_basinId(site: dict, aware_id: str):
61
61
  download_lookup(f"{AWARE_KEY}.csv"), column_name(AWARE_KEY), int(aware_id), column_name(lookup_col)
62
62
  )
63
63
  debugMissingLookup(f"{AWARE_KEY}.csv", AWARE_KEY, aware_id, lookup_col, value, model=MODEL, term=TERM_ID)
64
- return safe_parse_float(value, None)
64
+ return safe_parse_float(value, default=None)
65
65
 
66
66
 
67
67
  def _get_factor_from_region(impact_assessment: dict, site: dict):
@@ -71,7 +71,7 @@ def _get_factor_from_region(impact_assessment: dict, site: dict):
71
71
  lookup_suffix = 'unspecified' if not site_type else ('irri' if site_type in IRRIGATED_SITE_TYPES else 'non_irri')
72
72
  column = f"Agg_CF_{lookup_suffix}"
73
73
  value = get_region_lookup_value(lookup_name, region_id, column, model=MODEL, term=TERM_ID)
74
- return safe_parse_float(value, None)
74
+ return safe_parse_float(value, default=None)
75
75
 
76
76
 
77
77
  def run(impact_assessment: dict):
@@ -45,7 +45,7 @@ def _indicator(value: float):
45
45
  def impact_value(impact_assessment: dict, term_id: str):
46
46
  impact = find_term_match(impact_assessment.get('impacts', []), term_id)
47
47
  value = impact.get('value')
48
- value = safe_parse_float(value, None)
48
+ value = safe_parse_float(value, default=None)
49
49
  debugValues(impact, model=MODEL, term=TERM_ID, node=term_id, value=value, coefficient=1)
50
50
  return value
51
51
 
@@ -33,4 +33,4 @@ def get_region_factor(term_id: str, impact_assessment: dict, lookup_suffix: str,
33
33
  term_id, lookup_name, 'ecoregion', ecoregion, site_type
34
34
  )
35
35
  value = extract_grouped_data(value, group_key) if group_key else value
36
- return safe_parse_float(value)
36
+ return safe_parse_float(value, default=None)
@@ -976,6 +976,17 @@
976
976
  },
977
977
  "stage": 2
978
978
  },
979
+ {
980
+ "key": "emissions",
981
+ "model": "hestia",
982
+ "value": "default_emissions",
983
+ "runStrategy": "always",
984
+ "mergeStrategy": "list",
985
+ "mergeArgs": {
986
+ "replaceThreshold": ["value", 0.01]
987
+ },
988
+ "stage": 2
989
+ },
979
990
  [
980
991
  {
981
992
  "key": "emissions",
@@ -1649,7 +1660,7 @@
1649
1660
  [
1650
1661
  {
1651
1662
  "key": "emissions",
1652
- "model": "akagiEtAl2011AndIpcc2006",
1663
+ "model": "akagiEtAl2011",
1653
1664
  "value": "ch4ToAirCropResidueBurning",
1654
1665
  "runStrategy": "add_blank_node_if_missing",
1655
1666
  "runArgs": {
@@ -1664,8 +1675,8 @@
1664
1675
  },
1665
1676
  {
1666
1677
  "key": "emissions",
1667
- "model": "akagiEtAl2011AndIpcc2006",
1668
- "value": "n2OToAirCropResidueBurningDirect",
1678
+ "model": "akagiEtAl2011",
1679
+ "value": "nh3ToAirCropResidueBurning",
1669
1680
  "runStrategy": "add_blank_node_if_missing",
1670
1681
  "runArgs": {
1671
1682
  "runNonMeasured": true,
@@ -1679,8 +1690,8 @@
1679
1690
  },
1680
1691
  {
1681
1692
  "key": "emissions",
1682
- "model": "akagiEtAl2011AndIpcc2006",
1683
- "value": "nh3ToAirCropResidueBurning",
1693
+ "model": "akagiEtAl2011",
1694
+ "value": "noxToAirCropResidueBurning",
1684
1695
  "runStrategy": "add_blank_node_if_missing",
1685
1696
  "runArgs": {
1686
1697
  "runNonMeasured": true,
@@ -1694,8 +1705,23 @@
1694
1705
  },
1695
1706
  {
1696
1707
  "key": "emissions",
1697
- "model": "akagiEtAl2011AndIpcc2006",
1698
- "value": "noxToAirCropResidueBurning",
1708
+ "model": "akagiEtAl2011",
1709
+ "value": "pm25ToAirCropResidueBurning",
1710
+ "runStrategy": "add_blank_node_if_missing",
1711
+ "runArgs": {
1712
+ "runNonMeasured": true,
1713
+ "runNonAddedTerm": true
1714
+ },
1715
+ "mergeStrategy": "list",
1716
+ "mergeArgs": {
1717
+ "replaceThreshold": ["value", 0.01]
1718
+ },
1719
+ "stage": 2
1720
+ },
1721
+ {
1722
+ "key": "emissions",
1723
+ "model": "akagiEtAl2011",
1724
+ "value": "so2ToAirCropResidueBurning",
1699
1725
  "runStrategy": "add_blank_node_if_missing",
1700
1726
  "runArgs": {
1701
1727
  "runNonMeasured": true,
@@ -1767,6 +1793,21 @@
1767
1793
  },
1768
1794
  "stage": 2
1769
1795
  },
1796
+ {
1797
+ "key": "emissions",
1798
+ "model": "ipcc2019",
1799
+ "value": "n2OToAirCropResidueBurningDirect",
1800
+ "runStrategy": "add_blank_node_if_missing",
1801
+ "runArgs": {
1802
+ "runNonMeasured": true,
1803
+ "runNonAddedTerm": true
1804
+ },
1805
+ "mergeStrategy": "list",
1806
+ "mergeArgs": {
1807
+ "replaceThreshold": ["value", 0.01]
1808
+ },
1809
+ "stage": 2
1810
+ },
1770
1811
  {
1771
1812
  "key": "emissions",
1772
1813
  "model": "ipcc2019",
@@ -56,6 +56,17 @@
56
56
  },
57
57
  "stage": 1
58
58
  },
59
+ {
60
+ "key": "emissionsResourceUse",
61
+ "model": "hestia",
62
+ "value": "default_resourceUse",
63
+ "runStrategy": "always",
64
+ "mergeStrategy": "list",
65
+ "mergeArgs": {
66
+ "replaceThreshold": ["value", 0.01]
67
+ },
68
+ "stage": 1
69
+ },
59
70
  [
60
71
  {
61
72
  "key": "emissionsResourceUse",
@@ -216,6 +227,17 @@
216
227
  "stage": 1
217
228
  }
218
229
  ],
230
+ {
231
+ "key": "emissionsResourceUse",
232
+ "model": "resourceUseNotRelevant",
233
+ "value": "all",
234
+ "runStrategy": "always",
235
+ "mergeStrategy": "list",
236
+ "mergeArgs": {
237
+ "replaceLowerTier": true
238
+ },
239
+ "stage": 1
240
+ },
219
241
  [
220
242
  {
221
243
  "key": "impacts",
@@ -29,7 +29,7 @@ def run(cycle: dict):
29
29
  soilPh = measurement_value(soilPh_measurement)
30
30
 
31
31
  soilPh_added = is_from_model(soilPh_measurement)
32
- soilPh_above_6_5 = soilPh > 6.5
32
+ soilPh_above_6_5 = soilPh is not None and soilPh > 6.5
33
33
 
34
34
  logRequirements(cycle, model=MODEL, term=None, key=MODEL_KEY,
35
35
  soilPh_added=soilPh_added,
@@ -31,8 +31,10 @@ RETURNS = {
31
31
  LOOKUPS = {
32
32
  "@doc": "Depending on the primary product [termType](https://hestia.earth/schema/Product#term)",
33
33
  "crop": "global_economic_value_share",
34
+ "processedFood": "global_economic_value_share",
34
35
  "excreta": "global_economic_value_share",
35
- "animalProduct": "global_economic_value_share"
36
+ "animalProduct": "global_economic_value_share",
37
+ "waste": "global_economic_value_share"
36
38
  }
37
39
  MODEL_KEY = 'economicValueShare'
38
40
  MAX_VALUE = 100.5
@@ -1,4 +1,4 @@
1
- from hestia_earth.utils.tools import non_empty_list
1
+ from hestia_earth.utils.tools import list_sum, non_empty_list
2
2
 
3
3
  from hestia_earth.models.log import logRequirements, logShouldRun
4
4
  from hestia_earth.models.utils.currency import DEFAULT_CURRENCY
@@ -7,7 +7,15 @@ from .. import MODEL
7
7
 
8
8
  REQUIREMENTS = {
9
9
  "Cycle": {
10
- "products": [{"@type": "Product"}]
10
+ "products": [{
11
+ "@type": "Product",
12
+ "optional": {
13
+ "revenue": "0"
14
+ },
15
+ "none": {
16
+ "price": ""
17
+ }
18
+ }]
11
19
  }
12
20
  }
13
21
  RETURNS = {
@@ -15,6 +23,14 @@ RETURNS = {
15
23
  "price": ""
16
24
  }]
17
25
  }
26
+ LOOKUPS = {
27
+ "@doc": "Depending on the primary product [termType](https://hestia.earth/schema/Product#term)",
28
+ "crop": "global_economic_value_share",
29
+ "processedFood": "global_economic_value_share",
30
+ "excreta": "global_economic_value_share",
31
+ "animalProduct": "global_economic_value_share",
32
+ "waste": "global_economic_value_share"
33
+ }
18
34
  MODEL_KEY = 'price'
19
35
 
20
36
 
@@ -24,26 +40,35 @@ def _product(product: dict, value: float):
24
40
  return {'currency': DEFAULT_CURRENCY, **product, MODEL_KEY: value}
25
41
 
26
42
 
27
- def _should_run_product_by_share_0(cycle: dict, product: dict):
43
+ def _should_run_product(cycle: dict, product: dict):
28
44
  term_id = product.get('term', {}).get('@id')
45
+
46
+ value = list_sum(product.get('value') or [], default=None)
47
+ is_yield_0 = value == 0
48
+
29
49
  share = lookup_share(MODEL_KEY, product)
30
50
  share_is_0 = share is not None and share == 0
31
51
 
52
+ revenue = product.get('revenue', -1)
53
+ revenue_is_0 = revenue == 0
54
+
32
55
  logRequirements(cycle, model=MODEL, term=term_id, key=MODEL_KEY, by='economicValueShare',
33
- share_is_0=share_is_0)
56
+ global_economic_value_share=share,
57
+ share_is_0=share_is_0,
58
+ revenue=revenue,
59
+ revenue_is_0=revenue_is_0,
60
+ product_yield=value,
61
+ is_yield_0=is_yield_0)
34
62
 
35
- should_run = all([share_is_0])
63
+ should_run = any([share_is_0, revenue_is_0, is_yield_0])
36
64
  logShouldRun(cycle, MODEL, term_id, should_run, key=MODEL_KEY, by='economicValueShare')
37
65
  return should_run
38
66
 
39
67
 
40
- def _should_run_product(product: dict): return product.get(MODEL_KEY) is None
41
-
42
-
43
68
  def run(cycle: dict):
44
- products = list(filter(_should_run_product, cycle.get('products', [])))
69
+ products = list(filter(lambda p: p.get(MODEL_KEY) is None, cycle.get('products', [])))
45
70
  return non_empty_list([
46
71
  (
47
- _product(p, 0) if _should_run_product_by_share_0(cycle, p) else None
72
+ _product(p, 0) if _should_run_product(cycle, p) else None
48
73
  ) for p in products
49
74
  ])
@@ -9,9 +9,12 @@ REQUIREMENTS = {
9
9
  "Cycle": {
10
10
  "products": [{
11
11
  "@type": "Product",
12
- "price": "",
13
12
  "optional": {
14
- "value": ""
13
+ "value": "",
14
+ "price": ""
15
+ },
16
+ "none": {
17
+ "revenue": ""
15
18
  }
16
19
  }]
17
20
  }
@@ -1,22 +1,19 @@
1
1
  from hestia_earth.schema import EmissionMethodTier
2
+ from hestia_earth.utils.model import find_term_match
3
+ from hestia_earth.utils.tools import list_sum
2
4
 
3
5
  from hestia_earth.models.log import logRequirements, logShouldRun
4
6
  from hestia_earth.models.utils.constant import Units, get_atomic_conversion
5
7
  from hestia_earth.models.utils.emission import _new_emission
6
- from hestia_earth.models.utils.input import total_excreta
7
- from hestia_earth.models.utils.excretaManagement import get_lookup_factor
8
8
  from . import MODEL
9
9
 
10
10
  REQUIREMENTS = {
11
11
  "Cycle": {
12
- "practices": [
13
- {"@type": "Practice", "value": "", "term.termType": "excretaManagement"}
12
+ "emissions": [
13
+ {"@type": "Emission", "value": "", "term.@id": "n2OToAirExcretaDirect"}
14
14
  ]
15
15
  }
16
16
  }
17
- LOOKUPS = {
18
- "excretaManagement": "EF_NO-N"
19
- }
20
17
  RETURNS = {
21
18
  "Emission": [{
22
19
  "value": "",
@@ -25,6 +22,7 @@ RETURNS = {
25
22
  }
26
23
  TERM_ID = 'noxToAirExcreta'
27
24
  TIER = EmissionMethodTier.TIER_1.value
25
+ N2O_TERM_ID = 'n2OToAirExcretaDirect'
28
26
 
29
27
 
30
28
  def _emission(value: float):
@@ -34,24 +32,22 @@ def _emission(value: float):
34
32
  return emission
35
33
 
36
34
 
37
- def _run(excretaKgN: float, NO_N_EF: float):
38
- value = (NO_N_EF or 0) * (excretaKgN or 0) * get_atomic_conversion(Units.KG_NOX, Units.TO_N)
35
+ def _run(n2o: dict):
36
+ value = 0.1 * list_sum(n2o.get("value", [])) / get_atomic_conversion(Units.KG_N2O, Units.TO_N)
37
+ value = value * get_atomic_conversion(Units.KG_NOX, Units.TO_N)
39
38
  return [_emission(value)]
40
39
 
41
40
 
42
41
  def _should_run(cycle: dict):
43
- excretaKgN = total_excreta(cycle.get('inputs', []))
44
- NO_N_EF = get_lookup_factor(cycle.get('practices', []), LOOKUPS['excretaManagement'])
42
+ n2o = find_term_match(cycle.get('emissions', []), N2O_TERM_ID)
45
43
 
46
- logRequirements(cycle, model=MODEL, term=TERM_ID,
47
- excretaKgN=excretaKgN,
48
- NO_N_EF=NO_N_EF)
44
+ logRequirements(cycle, model=MODEL, term=TERM_ID, has_n2o=n2o is not None)
49
45
 
50
- should_run = all([excretaKgN is not None, NO_N_EF is not None])
46
+ should_run = all([n2o])
51
47
  logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
52
- return should_run, excretaKgN, NO_N_EF
48
+ return should_run, n2o
53
49
 
54
50
 
55
51
  def run(cycle: dict):
56
- should_run, excretaKgN, NO_N_EF = _should_run(cycle)
57
- return _run(excretaKgN, NO_N_EF) if should_run else []
52
+ should_run, n2o = _should_run(cycle)
53
+ return _run(n2o) if should_run else []
@@ -79,7 +79,7 @@ def _emission(term_id: str, value: float, input: dict):
79
79
  return emission
80
80
 
81
81
 
82
- def _add_emission(cycle: dict, input: dict):
82
+ def _add_emission(cycle: dict, input: dict, **extra_logs):
83
83
  input_term_id = input.get('term', {}).get('@id')
84
84
  operation_term_id = input.get('operation', {}).get('@id')
85
85
  animal_term_id = input.get('animal', {}).get('@id')
@@ -89,7 +89,7 @@ def _add_emission(cycle: dict, input: dict):
89
89
  emissions = ecoinventV3_emissions(ecoinventName)
90
90
  for emission_term_id, value in emissions:
91
91
  # log run on each emission so we know it did run
92
- logShouldRun(cycle, MODEL, input_term_id, True, methodTier=TIER, emission_id=emission_term_id)
92
+ logShouldRun(cycle, MODEL, input_term_id, True, methodTier=TIER, emission_id=emission_term_id, **extra_logs)
93
93
  debugValues(cycle, model=MODEL, term=emission_term_id,
94
94
  value=value,
95
95
  coefficient=coefficient,
@@ -112,6 +112,10 @@ def _run_input(cycle: dict):
112
112
  mappings = get_input_mappings(MODEL, cycle, input)
113
113
  has_mappings = len(mappings) > 0
114
114
 
115
+ # grouping the inputs together in the logs
116
+ input_parent_term_id = input.get('parent', {}).get('@id')
117
+ extra_logs = {'input_group_id': input_parent_term_id} if input_parent_term_id else {}
118
+
115
119
  # skip input that has background emissions we have already gap-filled (model run before)
116
120
  has_no_gap_filled_background_emissions = no_gap_filled_background_emissions_func(input)
117
121
 
@@ -119,13 +123,14 @@ def _run_input(cycle: dict):
119
123
  has_ecoinvent_mappings=has_mappings,
120
124
  ecoinvent_mappings=';'.join([v[0] for v in mappings]),
121
125
  has_no_gap_filled_background_emissions=has_no_gap_filled_background_emissions,
122
- input_value=input_value)
126
+ input_value=input_value,
127
+ **extra_logs)
123
128
 
124
129
  should_run = all([has_mappings, has_no_gap_filled_background_emissions, input_value])
125
- logShouldRun(cycle, MODEL, input_term_id, should_run, methodTier=TIER)
130
+ logShouldRun(cycle, MODEL, input_term_id, should_run, methodTier=TIER, **extra_logs)
126
131
 
127
- grouped_emissions = reduce(_add_emission(cycle, input), mappings, {}) if should_run else {}
128
- log_missing_emissions_func(input_term_id, list(grouped_emissions.keys()))
132
+ grouped_emissions = reduce(_add_emission(cycle, input, **extra_logs), mappings, {}) if should_run else {}
133
+ log_missing_emissions_func(input_term_id, list(grouped_emissions.keys()), **extra_logs)
129
134
  return [
130
135
  _emission(term_id, value * input_value, input)
131
136
  for term_id, value in grouped_emissions.items()
@@ -19,4 +19,4 @@ def get_input_coefficient(model: str, cycle: dict, country_id: str, ecoinventNam
19
19
  # find the ratio for the country / year
20
20
  data = get_region_lookup_value(REGION_EMBER_SOURCES_LOOKUP_NAME, country_id, source_name, model=model)
21
21
  percentage = extract_grouped_data(data, str(year))
22
- return safe_parse_float(percentage, 0) / 100
22
+ return safe_parse_float(percentage, default=0) / 100
@@ -95,7 +95,8 @@ def group_fuel_inputs(inputs: list):
95
95
 
96
96
  def _get_emissions_factor(animal: dict, lookup_col: str) -> float:
97
97
  return safe_parse_float(
98
- get_lookup_value(animal.get("term", {}), lookup_col, model=MODEL, term=animal.get("term", ""))
98
+ get_lookup_value(animal.get("term", {}), lookup_col, model=MODEL, term=animal.get("term", "")),
99
+ default=None
99
100
  )
100
101
 
101
102
 
@@ -55,7 +55,7 @@ def _product_value(product: dict, year: int, country_id: str):
55
55
  groupingFAO = get_animalProduct_lookup_value(MODEL, product_id, FAO_LOOKUP_COLUMN)
56
56
 
57
57
  data = get_region_lookup_value(LOOKUP_WEIGHT, country_id, groupingFAO, model=MODEL, term=TERM_ID)
58
- average_carcass_weight = safe_parse_float(extract_grouped_data_closest_date(data, year), None)
58
+ average_carcass_weight = safe_parse_float(extract_grouped_data_closest_date(data, year), default=None)
59
59
  # average_carcass_weight is in hg, divide by 10 to go back to kg
60
60
  kg_carcass_weight = average_carcass_weight / 10 if average_carcass_weight else None
61
61