hestia-earth-models 0.60.0__py3-none-any.whl → 0.61.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.

Potentially problematic release.


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

Files changed (57) hide show
  1. hestia_earth/models/cache_sites.py +41 -19
  2. hestia_earth/models/cycle/cycleDuration.py +61 -22
  3. hestia_earth/models/cycle/startDate.py +16 -11
  4. hestia_earth/models/cycle/startDateDefinition.py +69 -0
  5. hestia_earth/models/impact_assessment/emissions.py +1 -3
  6. hestia_earth/models/ipcc2019/pastureGrass.py +1 -1
  7. hestia_earth/models/linkedImpactAssessment/__init__.py +8 -162
  8. hestia_earth/models/linkedImpactAssessment/emissions.py +168 -0
  9. hestia_earth/models/{impact_assessment → linkedImpactAssessment}/utils.py +1 -1
  10. hestia_earth/models/mocking/search-results.json +257 -229
  11. hestia_earth/models/{impact_assessment → pooreNemecek2018}/freshwaterWithdrawalsDuringCycle.py +1 -1
  12. hestia_earth/models/site/brackishWater.py +43 -0
  13. hestia_earth/models/site/freshWater.py +43 -0
  14. hestia_earth/models/site/pre_checks/cache_geospatialDatabase.py +2 -2
  15. hestia_earth/models/site/salineWater.py +43 -0
  16. hestia_earth/models/utils/__init__.py +3 -3
  17. hestia_earth/models/version.py +1 -1
  18. {hestia_earth_models-0.60.0.dist-info → hestia_earth_models-0.61.0.dist-info}/METADATA +2 -2
  19. {hestia_earth_models-0.60.0.dist-info → hestia_earth_models-0.61.0.dist-info}/RECORD +52 -44
  20. tests/models/cycle/test_cycleDuration.py +15 -27
  21. tests/models/cycle/test_startDate.py +7 -7
  22. tests/models/cycle/test_startDateDefinition.py +31 -0
  23. tests/models/linkedImpactAssessment/__init__.py +0 -0
  24. tests/models/linkedImpactAssessment/test_emissions.py +22 -0
  25. tests/models/{impact_assessment → linkedImpactAssessment}/test_freshwaterWithdrawalsInputsProduction.py +4 -4
  26. tests/models/{impact_assessment → linkedImpactAssessment}/test_landOccupationInputsProduction.py +4 -4
  27. tests/models/{impact_assessment → linkedImpactAssessment}/test_landTransformationFromCropland100YearAverageInputsProduction.py +4 -4
  28. tests/models/{impact_assessment → linkedImpactAssessment}/test_landTransformationFromCropland20YearAverageInputsProduction.py +4 -4
  29. tests/models/{impact_assessment → linkedImpactAssessment}/test_landTransformationFromForest100YearAverageInputsProduction.py +4 -4
  30. tests/models/{impact_assessment → linkedImpactAssessment}/test_landTransformationFromForest20YearAverageInputsProduction.py +4 -4
  31. tests/models/{impact_assessment → linkedImpactAssessment}/test_landTransformationFromOtherNaturalVegetation100YearAverageInputsProduction.py +4 -4
  32. tests/models/{impact_assessment → linkedImpactAssessment}/test_landTransformationFromOtherNaturalVegetation20YearAverageInputsProduction.py +4 -4
  33. tests/models/linkedImpactAssessment/test_landTransformationFromPermanentPasture100YearAverageInputsProduction.py +24 -0
  34. tests/models/linkedImpactAssessment/test_landTransformationFromPermanentPasture20YearAverageInputsProduction.py +24 -0
  35. tests/models/{impact_assessment → pooreNemecek2018}/test_freshwaterWithdrawalsDuringCycle.py +1 -1
  36. tests/models/site/test_brackishWater.py +32 -0
  37. tests/models/site/test_freshWater.py +32 -0
  38. tests/models/site/test_salineWater.py +32 -0
  39. tests/models/test_cache_sites.py +0 -12
  40. hestia_earth/models/cycle/endDate.py +0 -50
  41. tests/models/cycle/test_endDate.py +0 -24
  42. tests/models/impact_assessment/test_landTransformationFromPermanentPasture100YearAverageInputsProduction.py +0 -23
  43. tests/models/impact_assessment/test_landTransformationFromPermanentPasture20YearAverageInputsProduction.py +0 -23
  44. tests/models/test_linkedImpactAssessment.py +0 -33
  45. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/freshwaterWithdrawalsInputsProduction.py +0 -0
  46. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landOccupationInputsProduction.py +0 -0
  47. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landTransformationFromCropland100YearAverageInputsProduction.py +0 -0
  48. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landTransformationFromCropland20YearAverageInputsProduction.py +0 -0
  49. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landTransformationFromForest100YearAverageInputsProduction.py +0 -0
  50. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landTransformationFromForest20YearAverageInputsProduction.py +0 -0
  51. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landTransformationFromOtherNaturalVegetation100YearAverageInputsProduction.py +0 -0
  52. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landTransformationFromOtherNaturalVegetation20YearAverageInputsProduction.py +0 -0
  53. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landTransformationFromPermanentPasture100YearAverageInputsProduction.py +0 -0
  54. /hestia_earth/models/{impact_assessment → linkedImpactAssessment}/landTransformationFromPermanentPasture20YearAverageInputsProduction.py +0 -0
  55. {hestia_earth_models-0.60.0.dist-info → hestia_earth_models-0.61.0.dist-info}/LICENSE +0 -0
  56. {hestia_earth_models-0.60.0.dist-info → hestia_earth_models-0.61.0.dist-info}/WHEEL +0 -0
  57. {hestia_earth_models-0.60.0.dist-info → hestia_earth_models-0.61.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,168 @@
1
+ """
2
+ Emissions
3
+
4
+ A model which takes recalculated data from an Impact Assessment linked to an Input in a Cycle.
5
+ """
6
+ from functools import reduce
7
+ from hestia_earth.schema import EmissionMethodTier
8
+ from hestia_earth.utils.lookup import download_lookup, get_table_value, column_name
9
+ from hestia_earth.utils.tools import flatten, list_sum
10
+
11
+ from hestia_earth.models.log import debugValues, logRequirements, logShouldRun, log_as_table
12
+ from hestia_earth.models.utils.emission import _new_emission
13
+ from hestia_earth.models.utils.input import load_impacts
14
+ from hestia_earth.models.utils.blank_node import group_by_keys
15
+ from . import MODEL
16
+
17
+ REQUIREMENTS = {
18
+ "Cycle": {
19
+ "inputs": [{
20
+ "@type": "Input",
21
+ "value": "> 0",
22
+ "impactAssessment": {
23
+ "@type": "ImpactAssessment",
24
+ "emissionsResourceUse": [{"@type": "Indicator", "value": ""}]
25
+ }
26
+ }],
27
+ "optional": {
28
+ "animals": [{
29
+ "@type": "Animal",
30
+ "inputs": [{
31
+ "@type": "Input",
32
+ "value": "> 0",
33
+ "impactAssessment": {
34
+ "@type": "ImpactAssessment",
35
+ "emissionsResourceUse": [{"@type": "Indicator", "value": ""}]
36
+ }
37
+ }]
38
+ }]
39
+ }
40
+ }
41
+ }
42
+ RETURNS = {
43
+ "Emission": [{
44
+ "value": "",
45
+ "methodTier": "background",
46
+ "inputs": "",
47
+ "operation": "",
48
+ "animals": ""
49
+ }]
50
+ }
51
+ MODEL_KEY = 'emissions'
52
+ MODEL_AGGREGATED = 'hestiaAggregatedData'
53
+ TIER = EmissionMethodTier.BACKGROUND.value
54
+
55
+
56
+ def _emission(model: str, term_id: str, value: float, input: dict, operation={}, animal={}):
57
+ emission = _new_emission(term_id, model)
58
+ emission['value'] = [value]
59
+ emission['methodTier'] = TIER
60
+ emission['inputs'] = [input]
61
+ if operation:
62
+ emission['operation'] = operation
63
+ if animal:
64
+ emission['animals'] = [animal]
65
+ return emission
66
+
67
+
68
+ def _run_emission(cycle: dict, term_id: str, data: dict):
69
+ def run_input(values: dict):
70
+ value = values.get('value', 0)
71
+ term = values.get('term', {})
72
+ operation = values.get('operation', {})
73
+ animal = values.get('animal', {})
74
+ is_aggregated = any(values.get('aggregated', []))
75
+ model = MODEL_AGGREGATED if is_aggregated else MODEL
76
+
77
+ details = values.get('details', {})
78
+ logRequirements(cycle, model=model, term=term_id, key=MODEL_KEY,
79
+ values=log_as_table([{'impact-assessment-id': key} | value for key, value in details.items()]))
80
+
81
+ logShouldRun(cycle, model, term_id, True, methodTier=TIER, key=MODEL_KEY,
82
+ input=term.get('@id'),
83
+ operation=operation.get('@id'),
84
+ animal=animal.get('@id'))
85
+
86
+ return _emission(model, term_id, value, input=term, operation=operation, animal=animal)
87
+
88
+ return list(map(run_input, data.values()))
89
+
90
+
91
+ def _emission_group(term_id: str):
92
+ lookup = download_lookup('emission.csv', True)
93
+ return get_table_value(lookup, 'termid', term_id, column_name('inputProductionGroupId'))
94
+
95
+
96
+ def _group_emissions(impact: dict):
97
+ def _group_by(group: dict, emission: dict):
98
+ term_id = emission.get('term', {}).get('@id')
99
+ grouping = _emission_group(term_id)
100
+ value = emission.get('value') or 0
101
+ if grouping:
102
+ group[grouping] = group.get(grouping, 0) + value
103
+ return group
104
+
105
+ emissions = impact.get('emissionsResourceUse', [])
106
+ return reduce(_group_by, emissions, {})
107
+
108
+
109
+ def _animal_inputs(animal: dict):
110
+ inputs = load_impacts(animal.get('inputs', []))
111
+ return [(input | {'animal': animal.get('term', {})}) for input in inputs]
112
+
113
+
114
+ def _group_input_emissions(input: dict):
115
+ impact = input.get('impactAssessment')
116
+ emissions = _group_emissions(impact)
117
+ return input | {'emissions': emissions}
118
+
119
+
120
+ def _group_inputs(group: dict, values: tuple):
121
+ # input_group_key = 'group-id'
122
+ # inputs = [{'term': {}, 'value':[], 'impactAssessment': {}, 'emissions': {'co2ToAirInputsProduction': 10}}]
123
+ input_group_key, inputs = values
124
+ for input in inputs:
125
+ input_value = list_sum(input.get('value'))
126
+ emissions = input.get('emissions', {})
127
+ for emission_term_id, emission_value in emissions.items():
128
+ group[emission_term_id] = group.get(emission_term_id, {})
129
+
130
+ grouped_inputs = group[emission_term_id].get(input_group_key, {
131
+ 'term': input.get('term', {}),
132
+ 'operation': input.get('operation', {}),
133
+ 'animal': input.get('animal', {}),
134
+ 'value': 0,
135
+ 'aggregated': [],
136
+ 'details': {}
137
+ })
138
+ grouped_inputs['aggregated'].append(input.get('impactAssessment', {}).get('agregated', False))
139
+ grouped_inputs['value'] = grouped_inputs['value'] + (emission_value * input_value)
140
+ # for logging
141
+ grouped_inputs['details'][input.get('impactAssessment', {}).get('@id')] = {
142
+ 'emission-value': emission_value,
143
+ 'input-value': input_value
144
+ }
145
+ group[emission_term_id][input_group_key] = grouped_inputs
146
+ return group
147
+
148
+
149
+ def run(cycle: dict):
150
+ inputs = flatten(
151
+ load_impacts(cycle.get('inputs', [])) +
152
+ list(map(_animal_inputs, cycle.get('animals', [])))
153
+ )
154
+ inputs = [i for i in inputs if list_sum(i.get('value', [])) > 0]
155
+
156
+ # group inputs with same term/operation/animal to avoid adding emissions twice
157
+ # inputs = {'group-id': [{'term': {},'value':[10],'impactAssessment': {}}]}
158
+ inputs = reduce(group_by_keys(['term', 'operation', 'animal']), inputs, {})
159
+ inputs = {key: list(map(_group_input_emissions, value)) for key, value in inputs.items()}
160
+
161
+ debugValues(cycle, model=MODEL, key=MODEL_KEY,
162
+ nb_inputs=len(inputs))
163
+
164
+ # finally group everything by emission so we can log inputs together
165
+ # emissions = {'co2ToAirInputsProduct': {'group-id':{'term':{},'value':10,'details':{}}}}
166
+ emissions = reduce(_group_inputs, inputs.items(), {})
167
+
168
+ return flatten([_run_emission(cycle, term_id, data) for term_id, data in emissions.items()])
@@ -9,7 +9,7 @@ from . import MODEL
9
9
 
10
10
 
11
11
  def _indicator(term_id: str, value: float):
12
- indicator = _new_indicator(term_id)
12
+ indicator = _new_indicator(term_id, MODEL)
13
13
  indicator['value'] = value
14
14
  return indicator
15
15