hestia-earth-models 0.59.1__py3-none-any.whl → 0.59.3__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.

Potentially problematic release.


This version of hestia-earth-models might be problematic. Click here for more details.

Files changed (40) hide show
  1. hestia_earth/models/cycle/irrigatedTypeUnspecified.py +6 -7
  2. hestia_earth/models/impact_assessment/irrigated.py +4 -1
  3. hestia_earth/models/ipcc2006/n2OToAirCropResidueDecompositionDirect.py +83 -0
  4. hestia_earth/models/ipcc2006/n2OToAirCropResidueDecompositionIndirect.py +3 -3
  5. hestia_earth/models/ipcc2006/n2OToAirExcretaIndirect.py +3 -3
  6. hestia_earth/models/ipcc2006/n2OToAirInorganicFertiliserIndirect.py +5 -4
  7. hestia_earth/models/ipcc2006/n2OToAirOrganicFertiliserIndirect.py +5 -4
  8. hestia_earth/models/ipcc2006/utils.py +12 -16
  9. hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionDirect.py +8 -7
  10. hestia_earth/models/ipcc2019/n2OToAirCropResidueDecompositionIndirect.py +100 -0
  11. hestia_earth/models/ipcc2019/n2OToAirExcretaIndirect.py +100 -0
  12. hestia_earth/models/ipcc2019/n2OToAirInorganicFertiliserIndirect.py +54 -61
  13. hestia_earth/models/ipcc2019/n2OToAirOrganicFertiliserIndirect.py +58 -66
  14. hestia_earth/models/ipcc2019/nh3ToAirInorganicFertiliser.py +112 -0
  15. hestia_earth/models/ipcc2019/nh3ToAirOrganicFertiliser.py +107 -0
  16. hestia_earth/models/ipcc2019/noxToAirInorganicFertiliser.py +112 -0
  17. hestia_earth/models/ipcc2019/noxToAirOrganicFertiliser.py +107 -0
  18. hestia_earth/models/ipcc2019/organicCarbonPerHa.py +67 -21
  19. hestia_earth/models/ipcc2019/utils.py +28 -16
  20. hestia_earth/models/site/soilMeasurement.py +197 -0
  21. hestia_earth/models/utils/cycle.py +7 -6
  22. hestia_earth/models/utils/emission.py +15 -0
  23. hestia_earth/models/version.py +1 -1
  24. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.3.dist-info}/METADATA +1 -1
  25. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.3.dist-info}/RECORD +40 -24
  26. tests/models/ipcc2006/test_n2OToAirCropResidueDecompositionDirect.py +50 -0
  27. tests/models/ipcc2019/test_n2OToAirCropResidueDecompositionIndirect.py +71 -0
  28. tests/models/ipcc2019/test_n2OToAirExcretaIndirect.py +71 -0
  29. tests/models/ipcc2019/test_n2OToAirInorganicFertiliserIndirect.py +36 -13
  30. tests/models/ipcc2019/test_n2OToAirOrganicFertiliserIndirect.py +36 -13
  31. tests/models/ipcc2019/test_nh3ToAirInorganicFertiliser.py +47 -0
  32. tests/models/ipcc2019/test_nh3ToAirOrganicFertiliser.py +35 -0
  33. tests/models/ipcc2019/test_noxToAirInorganicFertiliser.py +47 -0
  34. tests/models/ipcc2019/test_noxToAirOrganicFertiliser.py +35 -0
  35. tests/models/ipcc2019/test_organicCarbonPerHa.py +51 -5
  36. tests/models/site/test_soilMeasurement.py +159 -0
  37. tests/models/utils/test_blank_node.py +5 -5
  38. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.3.dist-info}/LICENSE +0 -0
  39. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.3.dist-info}/WHEEL +0 -0
  40. {hestia_earth_models-0.59.1.dist-info → hestia_earth_models-0.59.3.dist-info}/top_level.txt +0 -0
@@ -1,107 +1,100 @@
1
- from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition, TermTermType
1
+ from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition
2
2
 
3
- from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
3
+ from hestia_earth.models.log import debugValues, logRequirements, logShouldRun, log_as_table
4
4
  from hestia_earth.models.utils.constant import Units, get_atomic_conversion
5
5
  from hestia_earth.models.utils.completeness import _is_term_type_complete
6
- from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total, get_ecoClimateZone
7
- from hestia_earth.models.utils.emission import _new_emission
8
- from .utils import get_nh3_no3_nox_to_n, COEFF_NO3_N2O, COEFF_N_NH3NOX_inorganic, get_FracNH3NOx_N2O, get_FracLEACH_H
6
+ from hestia_earth.models.utils.emission import _new_emission, get_nh3_no3_nox_to_n
7
+ from hestia_earth.models.utils.cycle import get_ecoClimateZone
8
+ from .utils import ecoClimate_factors, EF4_FACTORS, EF5_FACTORS
9
9
  from . import MODEL
10
10
 
11
11
  REQUIREMENTS = {
12
12
  "Cycle": {
13
13
  "completeness.fertiliser": "True",
14
- "completeness.water": "True",
15
- "inputs": [{
16
- "@type": "Input",
17
- "value": "",
18
- "term.units": ["kg", "kg N"],
19
- "term.termType": "inorganicFertiliser",
20
- "optional": {
21
- "properties": [{"@type": "Property", "value": "", "term.@id": "nitrogenContent"}]
22
- }
23
- }],
24
14
  "emissions": [
25
15
  {"@type": "Emission", "value": "", "term.@id": "no3ToGroundwaterInorganicFertiliser"},
26
16
  {"@type": "Emission", "value": "", "term.@id": "nh3ToAirInorganicFertiliser"},
27
17
  {"@type": "Emission", "value": "", "term.@id": "noxToAirInorganicFertiliser"}
28
18
  ],
29
- "site": {
30
- "@type": "Site",
31
- "measurements": [{"@type": "Measurement", "value": "", "term.@id": "ecoClimateZone"}]
32
- },
33
19
  "optional": {
34
- "practices": [{"@type": "Practice", "value": "", "term.termType": "waterRegime"}]
20
+ "site": {
21
+ "@type": "Site",
22
+ "measurements": [
23
+ {"@type": "Measurement", "value": "", "term.@id": "ecoClimateZone"}
24
+ ]
25
+ }
35
26
  }
36
27
  }
37
28
  }
38
29
  RETURNS = {
39
30
  "Emission": [{
40
31
  "value": "",
41
- "sd": "",
42
- "min": "",
43
- "max": "",
44
- "methodTier": "tier 1",
45
- "statsDefinition": "modelled"
32
+ "methodTier": "tier 1"
46
33
  }]
47
34
  }
48
-
49
35
  TERM_ID = 'n2OToAirInorganicFertiliserIndirect'
36
+ TIER = EmissionMethodTier.TIER_1.value
50
37
  NO3_TERM_ID = 'no3ToGroundwaterInorganicFertiliser'
51
38
  NH3_TERM_ID = 'nh3ToAirInorganicFertiliser'
52
39
  NOX_TERM_ID = 'noxToAirInorganicFertiliser'
53
- TIER = EmissionMethodTier.TIER_1.value
54
40
 
55
41
 
56
- def _emission(value: float, sd: float, min: float, max: float):
42
+ def _emission(value: float, min: float, max: float, aggregated: bool = False):
57
43
  emission = _new_emission(TERM_ID, MODEL)
58
44
  emission['value'] = [value]
59
- emission['sd'] = [sd]
60
45
  emission['min'] = [min]
61
46
  emission['max'] = [max]
62
47
  emission['methodTier'] = TIER
63
48
  emission['statsDefinition'] = EmissionStatsDefinition.MODELLED.value
49
+ emission['methodModelDescription'] = 'Aggregated version' if aggregated else 'Disaggregated version'
64
50
  return emission
65
51
 
66
52
 
67
- def _run(cycle: dict):
68
- N_total = get_inorganic_fertiliser_N_total(cycle)
69
- nh3_n, no3_n, nox_n = get_nh3_no3_nox_to_n(cycle, NH3_TERM_ID, NO3_TERM_ID, NOX_TERM_ID)
53
+ def _run(cycle: dict, no3: float, nh3: float, nox: float):
54
+ ecoClimateZone = get_ecoClimateZone(cycle)
55
+
56
+ ef4, aggregated = ecoClimate_factors(EF4_FACTORS, ecoClimateZone=ecoClimateZone)
57
+ ef5 = EF5_FACTORS.get('default')
58
+
70
59
  debugValues(cycle, model=MODEL, term=TERM_ID,
71
- no3_n=no3_n,
72
- nh3_n=nh3_n,
73
- nox_n=nox_n)
74
- value, min_val, max_val, std = [
75
- get_FracNH3NOx_N2O(cycle, TERM_ID)[x] * (
76
- N_total * COEFF_N_NH3NOX_inorganic[x] if nox_n == 0 or nh3_n == 0 else nh3_n + nox_n
77
- ) +
78
- COEFF_NO3_N2O[x] * (
79
- N_total * get_FracLEACH_H(cycle, TERM_ID)[x] if no3_n == 0 else no3_n
80
- ) for x in range(4)
81
- ]
82
- return [_emission(
83
- value * get_atomic_conversion(Units.KG_N2O, Units.TO_N),
84
- std * get_atomic_conversion(Units.KG_N2O, Units.TO_N),
85
- min_val * get_atomic_conversion(Units.KG_N2O, Units.TO_N),
86
- max_val * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
87
- )]
60
+ ecoClimateZone=ecoClimateZone,
61
+ ef4_factors_used=log_as_table(ef4),
62
+ ef5_factors_used=log_as_table(ef5),
63
+ aggregated=aggregated)
64
+
65
+ value = sum([
66
+ no3 * ef5['value'],
67
+ nh3 * ef4['value'],
68
+ nox * ef4['value']
69
+ ]) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
70
+ min = sum([
71
+ no3 * ef5['min'],
72
+ nh3 * ef4['min'],
73
+ nox * ef4['min']
74
+ ]) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
75
+ max = sum([
76
+ no3 * ef5['max'],
77
+ nh3 * ef4['max'],
78
+ nox * ef4['max']
79
+ ]) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
80
+ return [_emission(value, min, max, aggregated=aggregated)]
88
81
 
89
82
 
90
83
  def _should_run(cycle: dict):
91
- N_inorganic_fertiliser = get_inorganic_fertiliser_N_total(cycle)
92
- ecoClimateZone = get_ecoClimateZone(cycle)
93
- fertiliser_complete = _is_term_type_complete(cycle, 'fertiliser')
94
- water_complete = _is_term_type_complete(cycle, TermTermType.WATER)
84
+ nh3_n, no3_n, nox_n = get_nh3_no3_nox_to_n(cycle, NH3_TERM_ID, NO3_TERM_ID, NOX_TERM_ID)
85
+ term_type_complete = _is_term_type_complete(cycle, 'fertiliser')
95
86
 
96
87
  logRequirements(cycle, model=MODEL, term=TERM_ID,
97
- N_inorganic_fertiliser=N_inorganic_fertiliser,
98
- ecoClimateZone=ecoClimateZone,
99
- term_type_fertiliser_complete=fertiliser_complete,
100
- term_type_water_complete=water_complete)
88
+ no3_n=no3_n,
89
+ nh3_n=nh3_n,
90
+ nox_n=nox_n,
91
+ term_type_cropResidue_complete=term_type_complete)
101
92
 
102
- should_run = all([N_inorganic_fertiliser is not None, ecoClimateZone, fertiliser_complete, water_complete])
103
- logShouldRun(cycle, MODEL, TERM_ID, should_run)
104
- return should_run
93
+ should_run = all([no3_n is not None, nh3_n is not None, nox_n is not None, term_type_complete])
94
+ logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
95
+ return should_run, no3_n, nh3_n, nox_n
105
96
 
106
97
 
107
- def run(cycle: dict): return _run(cycle) if _should_run(cycle) else []
98
+ def run(cycle: dict):
99
+ should_run, no3, nh3, nox = _should_run(cycle)
100
+ return _run(cycle, no3, nh3, nox) if should_run else []
@@ -1,108 +1,100 @@
1
- from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition, TermTermType
1
+ from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition
2
2
 
3
- from hestia_earth.models.log import debugValues, logRequirements, logShouldRun
3
+ from hestia_earth.models.log import debugValues, logRequirements, logShouldRun, log_as_table
4
4
  from hestia_earth.models.utils.constant import Units, get_atomic_conversion
5
5
  from hestia_earth.models.utils.completeness import _is_term_type_complete
6
- from hestia_earth.models.utils.cycle import get_organic_fertiliser_N_total, get_ecoClimateZone
7
- from hestia_earth.models.utils.emission import _new_emission
8
- from .utils import get_nh3_no3_nox_to_n, COEFF_NO3_N2O, COEFF_N_NH3NOX_organic_animal, get_FracNH3NOx_N2O, \
9
- get_FracLEACH_H
6
+ from hestia_earth.models.utils.emission import _new_emission, get_nh3_no3_nox_to_n
7
+ from hestia_earth.models.utils.cycle import get_ecoClimateZone
8
+ from .utils import ecoClimate_factors, EF4_FACTORS, EF5_FACTORS
10
9
  from . import MODEL
11
10
 
12
11
  REQUIREMENTS = {
13
12
  "Cycle": {
14
13
  "completeness.fertiliser": "True",
15
- "completeness.water": "True",
16
- "inputs": [
17
- {
18
- "@type": "Input",
19
- "value": "",
20
- "term.termType": "organicFertiliser",
21
- "term.units": "kg N"
22
- }
23
- ],
24
14
  "emissions": [
25
- {"@type": "Emission", "value": "", "term.@id": "no3ToGroundwaterInorganicFertiliser"},
26
- {"@type": "Emission", "value": "", "term.@id": "nh3ToAirInorganicFertiliser"},
27
- {"@type": "Emission", "value": "", "term.@id": "noxToAirInorganicFertiliser"}
15
+ {"@type": "Emission", "value": "", "term.@id": "no3ToGroundwaterOrganicFertiliser"},
16
+ {"@type": "Emission", "value": "", "term.@id": "nh3ToAirOrganicFertiliser"},
17
+ {"@type": "Emission", "value": "", "term.@id": "noxToAirOrganicFertiliser"}
28
18
  ],
29
- "site": {
30
- "@type": "Site",
31
- "measurements": [{"@type": "Measurement", "value": "", "term.@id": "ecoClimateZone"}]
32
- },
33
19
  "optional": {
34
- "practices": [{"@type": "Practice", "value": "", "term.termType": "waterRegime"}]
20
+ "site": {
21
+ "@type": "Site",
22
+ "measurements": [
23
+ {"@type": "Measurement", "value": "", "term.@id": "ecoClimateZone"}
24
+ ]
25
+ }
35
26
  }
36
27
  }
37
28
  }
38
29
  RETURNS = {
39
30
  "Emission": [{
40
31
  "value": "",
41
- "sd": "",
42
- "min": "",
43
- "max": "",
44
- "methodTier": "tier 1",
45
- "statsDefinition": "modelled"
32
+ "methodTier": "tier 1"
46
33
  }]
47
34
  }
48
-
49
35
  TERM_ID = 'n2OToAirOrganicFertiliserIndirect'
50
- NO3_TERM_ID = 'no3ToGroundwaterInorganicFertiliser'
51
- NH3_TERM_ID = 'nh3ToAirInorganicFertiliser'
52
- NOX_TERM_ID = 'noxToAirInorganicFertiliser'
53
36
  TIER = EmissionMethodTier.TIER_1.value
37
+ NO3_TERM_ID = 'no3ToGroundwaterOrganicFertiliser'
38
+ NH3_TERM_ID = 'nh3ToAirOrganicFertiliser'
39
+ NOX_TERM_ID = 'noxToAirOrganicFertiliser'
54
40
 
55
41
 
56
- def _emission(value: float, sd: float, min: float, max: float):
42
+ def _emission(value: float, min: float, max: float, aggregated: bool = False):
57
43
  emission = _new_emission(TERM_ID, MODEL)
58
44
  emission['value'] = [value]
59
- emission['sd'] = [sd]
60
45
  emission['min'] = [min]
61
46
  emission['max'] = [max]
62
47
  emission['methodTier'] = TIER
63
48
  emission['statsDefinition'] = EmissionStatsDefinition.MODELLED.value
49
+ emission['methodModelDescription'] = 'Aggregated version' if aggregated else 'Disaggregated version'
64
50
  return emission
65
51
 
66
52
 
67
- def _run(cycle: dict):
68
- N_total = get_organic_fertiliser_N_total(cycle)
69
- nh3_n, no3_n, nox_n = get_nh3_no3_nox_to_n(cycle, NH3_TERM_ID, NO3_TERM_ID, NOX_TERM_ID)
53
+ def _run(cycle: dict, no3: float, nh3: float, nox: float):
54
+ ecoClimateZone = get_ecoClimateZone(cycle)
55
+
56
+ ef4, aggregated = ecoClimate_factors(EF4_FACTORS, ecoClimateZone=ecoClimateZone)
57
+ ef5 = EF5_FACTORS.get('default')
58
+
70
59
  debugValues(cycle, model=MODEL, term=TERM_ID,
71
- no3_n=no3_n,
72
- nh3_n=nh3_n,
73
- nox_n=nox_n)
60
+ ecoClimateZone=ecoClimateZone,
61
+ ef4_factors_used=log_as_table(ef4),
62
+ ef5_factors_used=log_as_table(ef5),
63
+ aggregated=aggregated)
74
64
 
75
- value, min_val, max_val, std = [
76
- get_FracNH3NOx_N2O(cycle, TERM_ID)[x] * (
77
- N_total * COEFF_N_NH3NOX_organic_animal[x] if nox_n == 0 or nh3_n == 0 else nh3_n + nox_n
78
- ) +
79
- COEFF_NO3_N2O[x] * (
80
- N_total * get_FracLEACH_H(cycle, TERM_ID)[x] if no3_n == 0 else no3_n
81
- ) for x in range(4)
82
- ]
83
- return [_emission(
84
- value * get_atomic_conversion(Units.KG_N2O, Units.TO_N),
85
- std * get_atomic_conversion(Units.KG_N2O, Units.TO_N),
86
- min_val * get_atomic_conversion(Units.KG_N2O, Units.TO_N),
87
- max_val * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
88
- )]
65
+ value = sum([
66
+ no3 * ef5['value'],
67
+ nh3 * ef4['value'],
68
+ nox * ef4['value']
69
+ ]) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
70
+ min = sum([
71
+ no3 * ef5['min'],
72
+ nh3 * ef4['min'],
73
+ nox * ef4['min']
74
+ ]) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
75
+ max = sum([
76
+ no3 * ef5['max'],
77
+ nh3 * ef4['max'],
78
+ nox * ef4['max']
79
+ ]) * get_atomic_conversion(Units.KG_N2O, Units.TO_N)
80
+ return [_emission(value, min, max, aggregated=aggregated)]
89
81
 
90
82
 
91
83
  def _should_run(cycle: dict):
92
- N_organic_fertiliser = get_organic_fertiliser_N_total(cycle)
93
- ecoClimateZone = get_ecoClimateZone(cycle)
94
- fertiliser_complete = _is_term_type_complete(cycle, 'fertiliser')
95
- water_complete = _is_term_type_complete(cycle, TermTermType.WATER)
84
+ nh3_n, no3_n, nox_n = get_nh3_no3_nox_to_n(cycle, NH3_TERM_ID, NO3_TERM_ID, NOX_TERM_ID)
85
+ term_type_complete = _is_term_type_complete(cycle, 'fertiliser')
96
86
 
97
87
  logRequirements(cycle, model=MODEL, term=TERM_ID,
98
- N_organic_fertiliser=N_organic_fertiliser,
99
- ecoClimateZone=ecoClimateZone,
100
- term_type_fertiliser_complete=fertiliser_complete,
101
- term_type_water_complete=water_complete)
88
+ no3_n=no3_n,
89
+ nh3_n=nh3_n,
90
+ nox_n=nox_n,
91
+ term_type_cropResidue_complete=term_type_complete)
102
92
 
103
- should_run = all([N_organic_fertiliser is not None, ecoClimateZone, fertiliser_complete, water_complete])
104
- logShouldRun(cycle, MODEL, TERM_ID, should_run)
105
- return should_run
93
+ should_run = all([no3_n is not None, nh3_n is not None, nox_n is not None, term_type_complete])
94
+ logShouldRun(cycle, MODEL, TERM_ID, should_run, methodTier=TIER)
95
+ return should_run, no3_n, nh3_n, nox_n
106
96
 
107
97
 
108
- def run(cycle: dict): return _run(cycle) if _should_run(cycle) else []
98
+ def run(cycle: dict):
99
+ should_run, no3, nh3, nox = _should_run(cycle)
100
+ return _run(cycle, no3, nh3, nox) if should_run else []
@@ -0,0 +1,112 @@
1
+ from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition, TermTermType
2
+ from hestia_earth.utils.model import filter_list_term_type, find_term_match
3
+ from hestia_earth.utils.tools import list_sum
4
+
5
+ from hestia_earth.models.log import logRequirements, logShouldRun, debugValues, log_as_table
6
+ from hestia_earth.models.utils.blank_node import get_N_total
7
+ from hestia_earth.models.utils.constant import Units, get_atomic_conversion
8
+ from hestia_earth.models.utils.completeness import _is_term_type_complete
9
+ from hestia_earth.models.utils.emission import _new_emission
10
+ from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total
11
+ from hestia_earth.models.utils.term import get_lookup_value
12
+ from . import MODEL
13
+
14
+ REQUIREMENTS = {
15
+ "Cycle": {
16
+ "completeness.fertiliser": "True",
17
+ "inputs": [
18
+ {
19
+ "@type": "Input",
20
+ "value": "",
21
+ "term.termType": "inorganicFertiliser",
22
+ "optional": {
23
+ "properties": [{"@type": "Property", "value": "", "term.@id": "nitrogenContent"}]
24
+ }
25
+ }
26
+ ]
27
+ }
28
+ }
29
+ RETURNS = {
30
+ "Emission": [{
31
+ "value": "",
32
+ "sd": "",
33
+ "min": "",
34
+ "max": "",
35
+ "methodTier": "tier 1",
36
+ "statsDefinition": "modelled",
37
+ "methodModelDescription": ["Aggregated version", "Disaggragated version"]
38
+ }]
39
+ }
40
+ LOOKUPS = {
41
+ "inorganicFertiliser": ["IPCC_2019_FRACGASF_NH3-N", "IPCC_2019_FRACGASF_NH3-N-min", "IPCC_2019_FRACGASF_NH3-N-max"]
42
+ }
43
+ TERM_ID = 'nh3ToAirInorganicFertiliser'
44
+ TIER = EmissionMethodTier.TIER_1.value
45
+ TERM_TYPE = TermTermType.INORGANICFERTILISER
46
+ UNSPECIFIED_TERM_ID = 'inorganicNitrogenFertiliserUnspecifiedKgN'
47
+
48
+
49
+ def _emission(value: float, min: float, max: float, aggregated: bool = False):
50
+ emission = _new_emission(TERM_ID, MODEL)
51
+ emission['value'] = [value]
52
+ emission['min'] = [min]
53
+ emission['max'] = [max]
54
+ emission['methodTier'] = TIER
55
+ emission['statsDefinition'] = EmissionStatsDefinition.MODELLED.value
56
+ emission['methodModelDescription'] = 'Aggregated version' if aggregated else 'Disaggregated version'
57
+ return emission
58
+
59
+
60
+ def _input_values(input: dict):
61
+ N_total = list_sum(get_N_total([input]))
62
+ lookups = LOOKUPS[TERM_TYPE.value]
63
+ return {
64
+ 'id': input.get('term', {}).get('@id'),
65
+ 'N': N_total,
66
+ 'value': get_lookup_value(input.get('term', {}), lookups[0]),
67
+ 'min': get_lookup_value(input.get('term', {}), lookups[1]),
68
+ 'max': get_lookup_value(input.get('term', {}), lookups[2])
69
+ }
70
+
71
+
72
+ def _filter_input_values(values: list, key: str): return [value for value in values if value.get(key)]
73
+
74
+
75
+ def _run(cycle: dict):
76
+ inputs = filter_list_term_type(cycle.get('inputs', []), TERM_TYPE)
77
+ input_values = list(map(_input_values, inputs))
78
+
79
+ debugValues(cycle, model=MODEL, term=TERM_ID,
80
+ input_values=log_as_table(input_values))
81
+
82
+ value = list_sum([
83
+ v.get('N', 0) * v.get('value', 0) for v in _filter_input_values(input_values, 'value')
84
+ ]) * get_atomic_conversion(Units.KG_NH3, Units.TO_N)
85
+
86
+ min = list_sum([
87
+ v.get('N', 0) * v.get('min', 0) for v in _filter_input_values(input_values, 'min')
88
+ ]) * get_atomic_conversion(Units.KG_NH3, Units.TO_N)
89
+
90
+ max = list_sum([
91
+ v.get('N', 0) * v.get('max', 0) for v in _filter_input_values(input_values, 'max')
92
+ ]) * get_atomic_conversion(Units.KG_NH3, Units.TO_N)
93
+
94
+ aggregated = list_sum(find_term_match(inputs, UNSPECIFIED_TERM_ID).get('value', [0])) > 0
95
+
96
+ return [_emission(value, min, max, aggregated=aggregated)]
97
+
98
+
99
+ def _should_run(cycle: dict):
100
+ N_inorganic_fertiliser = get_inorganic_fertiliser_N_total(cycle)
101
+ fertiliser_complete = _is_term_type_complete(cycle, 'fertiliser')
102
+
103
+ logRequirements(cycle, model=MODEL, term=TERM_ID,
104
+ N_inorganic_fertiliser=N_inorganic_fertiliser,
105
+ term_type_fertiliser_complete=fertiliser_complete)
106
+
107
+ should_run = all([N_inorganic_fertiliser is not None, fertiliser_complete])
108
+ logShouldRun(cycle, MODEL, TERM_ID, should_run)
109
+ return should_run
110
+
111
+
112
+ def run(cycle: dict): return _run(cycle) if _should_run(cycle) else []
@@ -0,0 +1,107 @@
1
+ from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition, TermTermType
2
+ from hestia_earth.utils.model import filter_list_term_type
3
+ from hestia_earth.utils.tools import list_sum
4
+
5
+ from hestia_earth.models.log import logRequirements, logShouldRun, debugValues, log_as_table
6
+ from hestia_earth.models.utils.blank_node import get_N_total
7
+ from hestia_earth.models.utils.constant import Units, get_atomic_conversion
8
+ from hestia_earth.models.utils.completeness import _is_term_type_complete
9
+ from hestia_earth.models.utils.emission import _new_emission
10
+ from hestia_earth.models.utils.cycle import get_organic_fertiliser_N_total
11
+ from hestia_earth.models.utils.term import get_lookup_value
12
+ from . import MODEL
13
+
14
+ REQUIREMENTS = {
15
+ "Cycle": {
16
+ "completeness.fertiliser": "True",
17
+ "inputs": [
18
+ {
19
+ "@type": "Input",
20
+ "value": "",
21
+ "term.termType": "organicFertiliser",
22
+ "optional": {
23
+ "properties": [{"@type": "Property", "value": "", "term.@id": "nitrogenContent"}]
24
+ }
25
+ }
26
+ ]
27
+ }
28
+ }
29
+ RETURNS = {
30
+ "Emission": [{
31
+ "value": "",
32
+ "sd": "",
33
+ "min": "",
34
+ "max": "",
35
+ "methodTier": "tier 1",
36
+ "statsDefinition": "modelled",
37
+ "methodModelDescription": "Aggregated version"
38
+ }]
39
+ }
40
+ LOOKUPS = {
41
+ "organicFertiliser": ["IPCC_2019_FRACGASM_NH3-N", "IPCC_2019_FRACGASM_NH3-N-min", "IPCC_2019_FRACGASM_NH3-N-max"]
42
+ }
43
+ TERM_ID = 'nh3ToAirOrganicFertiliser'
44
+ TIER = EmissionMethodTier.TIER_1.value
45
+
46
+
47
+ def _emission(value: float, min: float, max: float):
48
+ emission = _new_emission(TERM_ID, MODEL)
49
+ emission['value'] = [value]
50
+ emission['min'] = [min]
51
+ emission['max'] = [max]
52
+ emission['methodTier'] = TIER
53
+ emission['statsDefinition'] = EmissionStatsDefinition.MODELLED.value
54
+ emission['methodModelDescription'] = 'Aggregated version'
55
+ return emission
56
+
57
+
58
+ def _input_values(input: dict):
59
+ N_total = list_sum(get_N_total([input]))
60
+ return {
61
+ 'id': input.get('term', {}).get('@id'),
62
+ 'N': N_total,
63
+ 'value': get_lookup_value(input.get('term', {}), LOOKUPS['organicFertiliser'][0]),
64
+ 'min': get_lookup_value(input.get('term', {}), LOOKUPS['organicFertiliser'][1]),
65
+ 'max': get_lookup_value(input.get('term', {}), LOOKUPS['organicFertiliser'][2])
66
+ }
67
+
68
+
69
+ def _filter_input_values(values: list, key: str): return [value for value in values if value.get(key)]
70
+
71
+
72
+ def _run(cycle: dict):
73
+ inputs = filter_list_term_type(cycle.get('inputs', []), TermTermType.ORGANICFERTILISER)
74
+ input_values = list(map(_input_values, inputs))
75
+
76
+ debugValues(cycle, model=MODEL, term=TERM_ID,
77
+ input_values=log_as_table(input_values))
78
+
79
+ value = list_sum([
80
+ v.get('N', 0) * v.get('value', 0) for v in _filter_input_values(input_values, 'value')
81
+ ]) * get_atomic_conversion(Units.KG_NH3, Units.TO_N)
82
+
83
+ min = list_sum([
84
+ v.get('N', 0) * v.get('min', 0) for v in _filter_input_values(input_values, 'min')
85
+ ]) * get_atomic_conversion(Units.KG_NH3, Units.TO_N)
86
+
87
+ max = list_sum([
88
+ v.get('N', 0) * v.get('max', 0) for v in _filter_input_values(input_values, 'max')
89
+ ]) * get_atomic_conversion(Units.KG_NH3, Units.TO_N)
90
+
91
+ return [_emission(value, min, max)]
92
+
93
+
94
+ def _should_run(cycle: dict):
95
+ N_organic_fertiliser = get_organic_fertiliser_N_total(cycle)
96
+ fertiliser_complete = _is_term_type_complete(cycle, 'fertiliser')
97
+
98
+ logRequirements(cycle, model=MODEL, term=TERM_ID,
99
+ N_organic_fertiliser=N_organic_fertiliser,
100
+ term_type_fertiliser_complete=fertiliser_complete)
101
+
102
+ should_run = all([N_organic_fertiliser is not None, fertiliser_complete])
103
+ logShouldRun(cycle, MODEL, TERM_ID, should_run)
104
+ return should_run
105
+
106
+
107
+ def run(cycle: dict): return _run(cycle) if _should_run(cycle) else []
@@ -0,0 +1,112 @@
1
+ from hestia_earth.schema import EmissionMethodTier, EmissionStatsDefinition, TermTermType
2
+ from hestia_earth.utils.model import filter_list_term_type, find_term_match
3
+ from hestia_earth.utils.tools import list_sum
4
+
5
+ from hestia_earth.models.log import logRequirements, logShouldRun, debugValues, log_as_table
6
+ from hestia_earth.models.utils.blank_node import get_N_total
7
+ from hestia_earth.models.utils.constant import Units, get_atomic_conversion
8
+ from hestia_earth.models.utils.completeness import _is_term_type_complete
9
+ from hestia_earth.models.utils.emission import _new_emission
10
+ from hestia_earth.models.utils.cycle import get_inorganic_fertiliser_N_total
11
+ from hestia_earth.models.utils.term import get_lookup_value
12
+ from . import MODEL
13
+
14
+ REQUIREMENTS = {
15
+ "Cycle": {
16
+ "completeness.fertiliser": "True",
17
+ "inputs": [
18
+ {
19
+ "@type": "Input",
20
+ "value": "",
21
+ "term.termType": "inorganicFertiliser",
22
+ "optional": {
23
+ "properties": [{"@type": "Property", "value": "", "term.@id": "nitrogenContent"}]
24
+ }
25
+ }
26
+ ]
27
+ }
28
+ }
29
+ RETURNS = {
30
+ "Emission": [{
31
+ "value": "",
32
+ "sd": "",
33
+ "min": "",
34
+ "max": "",
35
+ "methodTier": "tier 1",
36
+ "statsDefinition": "modelled",
37
+ "methodModelDescription": ["Aggregated version", "Disaggragated version"]
38
+ }]
39
+ }
40
+ LOOKUPS = {
41
+ "inorganicFertiliser": ["IPCC_2019_FRACGASF_NOx-N", "IPCC_2019_FRACGASF_NOx-N-min", "IPCC_2019_FRACGASF_NOx-N-max"]
42
+ }
43
+ TERM_ID = 'noxToAirInorganicFertiliser'
44
+ TIER = EmissionMethodTier.TIER_1.value
45
+ TERM_TYPE = TermTermType.INORGANICFERTILISER
46
+ UNSPECIFIED_TERM_ID = 'inorganicNitrogenFertiliserUnspecifiedKgN'
47
+
48
+
49
+ def _emission(value: float, min: float, max: float, aggregated: bool = False):
50
+ emission = _new_emission(TERM_ID, MODEL)
51
+ emission['value'] = [value]
52
+ emission['min'] = [min]
53
+ emission['max'] = [max]
54
+ emission['methodTier'] = TIER
55
+ emission['statsDefinition'] = EmissionStatsDefinition.MODELLED.value
56
+ emission['methodModelDescription'] = 'Aggregated version' if aggregated else 'Disaggregated version'
57
+ return emission
58
+
59
+
60
+ def _input_values(input: dict):
61
+ N_total = list_sum(get_N_total([input]))
62
+ lookups = LOOKUPS[TERM_TYPE.value]
63
+ return {
64
+ 'id': input.get('term', {}).get('@id'),
65
+ 'N': N_total,
66
+ 'value': get_lookup_value(input.get('term', {}), lookups[0]),
67
+ 'min': get_lookup_value(input.get('term', {}), lookups[1]),
68
+ 'max': get_lookup_value(input.get('term', {}), lookups[2])
69
+ }
70
+
71
+
72
+ def _filter_input_values(values: list, key: str): return [value for value in values if value.get(key)]
73
+
74
+
75
+ def _run(cycle: dict):
76
+ inputs = filter_list_term_type(cycle.get('inputs', []), TERM_TYPE)
77
+ input_values = list(map(_input_values, inputs))
78
+
79
+ debugValues(cycle, model=MODEL, term=TERM_ID,
80
+ input_values=log_as_table(input_values))
81
+
82
+ value = list_sum([
83
+ v.get('N', 0) * v.get('value', 0) for v in _filter_input_values(input_values, 'value')
84
+ ]) * get_atomic_conversion(Units.KG_NOX, Units.TO_N)
85
+
86
+ min = list_sum([
87
+ v.get('N', 0) * v.get('min', 0) for v in _filter_input_values(input_values, 'min')
88
+ ]) * get_atomic_conversion(Units.KG_NOX, Units.TO_N)
89
+
90
+ max = list_sum([
91
+ v.get('N', 0) * v.get('max', 0) for v in _filter_input_values(input_values, 'max')
92
+ ]) * get_atomic_conversion(Units.KG_NOX, Units.TO_N)
93
+
94
+ aggregated = list_sum(find_term_match(inputs, UNSPECIFIED_TERM_ID).get('value', [0])) > 0
95
+
96
+ return [_emission(value, min, max, aggregated=aggregated)]
97
+
98
+
99
+ def _should_run(cycle: dict):
100
+ N_inorganic_fertiliser = get_inorganic_fertiliser_N_total(cycle)
101
+ fertiliser_complete = _is_term_type_complete(cycle, 'fertiliser')
102
+
103
+ logRequirements(cycle, model=MODEL, term=TERM_ID,
104
+ N_inorganic_fertiliser=N_inorganic_fertiliser,
105
+ term_type_fertiliser_complete=fertiliser_complete)
106
+
107
+ should_run = all([N_inorganic_fertiliser is not None, fertiliser_complete])
108
+ logShouldRun(cycle, MODEL, TERM_ID, should_run)
109
+ return should_run
110
+
111
+
112
+ def run(cycle: dict): return _run(cycle) if _should_run(cycle) else []