hestia-earth-aggregation 0.21.15__py3-none-any.whl → 0.21.17__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.
- hestia_earth/aggregation/__init__.py +3 -1
- hestia_earth/aggregation/aggregate_cycles.py +4 -1
- hestia_earth/aggregation/config/Cycle/crop.json +63 -0
- hestia_earth/aggregation/config/Cycle/processedFood.json +15 -3
- hestia_earth/aggregation/recalculate_cycles.py +2 -1
- hestia_earth/aggregation/utils/aggregate_country_nodes.py +9 -32
- hestia_earth/aggregation/utils/aggregate_weighted.py +0 -6
- hestia_earth/aggregation/utils/cycle.py +28 -14
- hestia_earth/aggregation/utils/emission.py +34 -38
- hestia_earth/aggregation/utils/quality_score.py +6 -2
- hestia_earth/aggregation/utils/weights.py +30 -10
- hestia_earth/aggregation/version.py +1 -1
- {hestia_earth_aggregation-0.21.15.dist-info → hestia_earth_aggregation-0.21.17.dist-info}/METADATA +1 -1
- {hestia_earth_aggregation-0.21.15.dist-info → hestia_earth_aggregation-0.21.17.dist-info}/RECORD +17 -16
- {hestia_earth_aggregation-0.21.15.dist-info → hestia_earth_aggregation-0.21.17.dist-info}/WHEEL +0 -0
- {hestia_earth_aggregation-0.21.15.dist-info → hestia_earth_aggregation-0.21.17.dist-info}/licenses/LICENSE +0 -0
- {hestia_earth_aggregation-0.21.15.dist-info → hestia_earth_aggregation-0.21.17.dist-info}/top_level.txt +0 -0
|
@@ -88,12 +88,14 @@ def aggregate(
|
|
|
88
88
|
filter_by_country=filter_by_country,
|
|
89
89
|
include_covariance=include_covariance,
|
|
90
90
|
)
|
|
91
|
-
logger.info("time=%s, unit=ms", current_time_ms() - now)
|
|
91
|
+
logger.info("Aggregations finished. time=%s, unit=ms", current_time_ms() - now)
|
|
92
|
+
now = current_time_ms()
|
|
92
93
|
aggregations = (
|
|
93
94
|
[recalculate(agg, product) for agg in aggregations]
|
|
94
95
|
if should_recalculate(product)
|
|
95
96
|
else aggregations
|
|
96
97
|
)
|
|
98
|
+
logger.info("Recalculations finished. time=%s, unit=ms", current_time_ms() - now)
|
|
97
99
|
aggregations = [
|
|
98
100
|
calculate_score(cycle=agg, countries=countries) for agg in aggregations
|
|
99
101
|
]
|
|
@@ -157,7 +157,10 @@ def aggregate_country(
|
|
|
157
157
|
functional_unit = cycles_aggregated[0].get("functionalUnit")
|
|
158
158
|
include_matrix = aggregate_with_matrix(product)
|
|
159
159
|
cycles_aggregated = non_empty_list(
|
|
160
|
-
[
|
|
160
|
+
[
|
|
161
|
+
format_terms_results(cycle, product, country, start_year, end_year)
|
|
162
|
+
for cycle in cycles_aggregated
|
|
163
|
+
]
|
|
161
164
|
)
|
|
162
165
|
cycles_aggregated = non_empty_list(
|
|
163
166
|
map(
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"models": [
|
|
3
|
+
{
|
|
4
|
+
"key": "inputs",
|
|
5
|
+
"model": "cycle",
|
|
6
|
+
"value": "input.hestiaAggregatedData",
|
|
7
|
+
"runStrategy": "always",
|
|
8
|
+
"mergeStrategy": "list"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"key": "emissions",
|
|
12
|
+
"model": "linkedImpactAssessment",
|
|
13
|
+
"value": "emissions",
|
|
14
|
+
"runStrategy": "always",
|
|
15
|
+
"mergeStrategy": "list",
|
|
16
|
+
"mergeArgs": {
|
|
17
|
+
"replaceThreshold": ["value", 0.01]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"key": "emissions",
|
|
22
|
+
"model": "ecoalimV9",
|
|
23
|
+
"value": "cycle",
|
|
24
|
+
"runStrategy": "always",
|
|
25
|
+
"mergeStrategy": "list",
|
|
26
|
+
"mergeArgs": {
|
|
27
|
+
"replaceThreshold": ["value", 0.01]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"key": "emissions",
|
|
32
|
+
"model": "worldSteel",
|
|
33
|
+
"value": "cycle",
|
|
34
|
+
"runStrategy": "always",
|
|
35
|
+
"mergeStrategy": "list",
|
|
36
|
+
"mergeArgs": {
|
|
37
|
+
"replaceThreshold": ["value", 0.01]
|
|
38
|
+
},
|
|
39
|
+
"stage": 2
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"key": "emissions",
|
|
43
|
+
"model": "bafu2025",
|
|
44
|
+
"value": "cycle",
|
|
45
|
+
"runStrategy": "always",
|
|
46
|
+
"mergeStrategy": "list",
|
|
47
|
+
"mergeArgs": {
|
|
48
|
+
"replaceThreshold": ["value", 0.01]
|
|
49
|
+
},
|
|
50
|
+
"stage": 2
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"key": "emissions",
|
|
54
|
+
"model": "ecoinventV3AndEmberClimate",
|
|
55
|
+
"value": "cycle",
|
|
56
|
+
"runStrategy": "always",
|
|
57
|
+
"mergeStrategy": "list",
|
|
58
|
+
"mergeArgs": {
|
|
59
|
+
"replaceThreshold": ["value", 0.01]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
@@ -29,17 +29,29 @@
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"key": "emissions",
|
|
32
|
-
"model": "
|
|
32
|
+
"model": "worldSteel",
|
|
33
33
|
"value": "cycle",
|
|
34
34
|
"runStrategy": "always",
|
|
35
35
|
"mergeStrategy": "list",
|
|
36
36
|
"mergeArgs": {
|
|
37
37
|
"replaceThreshold": ["value", 0.01]
|
|
38
|
-
}
|
|
38
|
+
},
|
|
39
|
+
"stage": 2
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
42
|
"key": "emissions",
|
|
42
|
-
"model": "
|
|
43
|
+
"model": "bafu2025",
|
|
44
|
+
"value": "cycle",
|
|
45
|
+
"runStrategy": "always",
|
|
46
|
+
"mergeStrategy": "list",
|
|
47
|
+
"mergeArgs": {
|
|
48
|
+
"replaceThreshold": ["value", 0.01]
|
|
49
|
+
},
|
|
50
|
+
"stage": 2
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"key": "emissions",
|
|
54
|
+
"model": "ecoinventV3AndEmberClimate",
|
|
43
55
|
"value": "cycle",
|
|
44
56
|
"runStrategy": "always",
|
|
45
57
|
"mergeStrategy": "list",
|
|
@@ -4,10 +4,11 @@ from hestia_earth.orchestrator import run
|
|
|
4
4
|
|
|
5
5
|
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
6
6
|
CONFIG_PATH = os.path.join(CURRENT_DIR, "config", "Cycle")
|
|
7
|
+
_TERM_TYPES = os.listdir(CONFIG_PATH)
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def should_recalculate(product: dict):
|
|
10
|
-
return f"{product.get('termType')}.json" in
|
|
11
|
+
return f"{product.get('termType')}.json" in _TERM_TYPES
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
def recalculate(cycle: dict, product: dict):
|
|
@@ -65,6 +65,7 @@ from .emission import (
|
|
|
65
65
|
get_method_tier,
|
|
66
66
|
get_method_model,
|
|
67
67
|
has_value_without_transformation,
|
|
68
|
+
include_emission,
|
|
68
69
|
)
|
|
69
70
|
from .property import aggregate_properties
|
|
70
71
|
from .distribution import generate_blank_node_distribution
|
|
@@ -205,6 +206,10 @@ def _group_cycle_blank_node(cycle: dict, product: dict, product_value: float):
|
|
|
205
206
|
term_id = term.get("@id")
|
|
206
207
|
group_key = blank_node_group_key(blank_node)
|
|
207
208
|
|
|
209
|
+
# skip background emissions when recalculated
|
|
210
|
+
if node_type == "Emission" and not include_emission(blank_node, product):
|
|
211
|
+
return group
|
|
212
|
+
|
|
208
213
|
is_aggregated_product = node_type == "Product" and term_id == product.get("@id")
|
|
209
214
|
|
|
210
215
|
site_type = cycle.get("site", {}).get("siteType")
|
|
@@ -223,9 +228,9 @@ def _group_cycle_blank_node(cycle: dict, product: dict, product_value: float):
|
|
|
223
228
|
is_aggregated_product=is_aggregated_product,
|
|
224
229
|
)
|
|
225
230
|
|
|
226
|
-
# only primary data can be incomplete, otherwise skip the blank node
|
|
227
231
|
if all(
|
|
228
232
|
[
|
|
233
|
+
# only primary data can be incomplete, otherwise skip the blank node
|
|
229
234
|
complete is False,
|
|
230
235
|
not blank_node_data.get("primary"),
|
|
231
236
|
blank_node_data.get("primaryPercent", 0) <= 0,
|
|
@@ -301,7 +306,6 @@ def _group_cycle_blank_nodes(
|
|
|
301
306
|
end_year: int = None,
|
|
302
307
|
):
|
|
303
308
|
def grouper(group: dict, list_key: str) -> Dict[str, Dict[str, BlankNodeFormatted]]:
|
|
304
|
-
now = current_time_ms()
|
|
305
309
|
blank_nodes = _filter_blank_nodes(cycle, list_key, start_year, end_year)
|
|
306
310
|
values = reduce(
|
|
307
311
|
_group_cycle_blank_node(cycle, product, product_value), blank_nodes, {}
|
|
@@ -312,11 +316,6 @@ def _group_cycle_blank_nodes(
|
|
|
312
316
|
for k, v in values.items()
|
|
313
317
|
if list_key != "emissions" or has_value_without_transformation(v)
|
|
314
318
|
}
|
|
315
|
-
logger.debug(
|
|
316
|
-
"function=_group_cycle_blank_nodes, list_key=%s, time=%s",
|
|
317
|
-
list_key,
|
|
318
|
-
current_time_ms() - now,
|
|
319
|
-
)
|
|
320
319
|
return group
|
|
321
320
|
|
|
322
321
|
return grouper
|
|
@@ -333,6 +332,7 @@ def _format_cycle(
|
|
|
333
332
|
Returns the list of formatted Cycles, and the list of Site ids to be downloaded.
|
|
334
333
|
Note: if a Site does not have an `@id`, it means it's nested within the Cycle.
|
|
335
334
|
"""
|
|
335
|
+
now = current_time_ms()
|
|
336
336
|
product_value = _cycle_product_value(cycle, product)
|
|
337
337
|
data: CycleFormatted = (
|
|
338
338
|
(
|
|
@@ -365,8 +365,9 @@ def _format_cycle(
|
|
|
365
365
|
)
|
|
366
366
|
if data:
|
|
367
367
|
logger.debug(
|
|
368
|
-
"id=%s, yield=%s, organic=%s, irrigated=%s",
|
|
368
|
+
"id=%s, time=%sms, yield=%s, organic=%s, irrigated=%s",
|
|
369
369
|
cycle.get("@id"),
|
|
370
|
+
current_time_ms() - now,
|
|
370
371
|
product_value,
|
|
371
372
|
data["organic"],
|
|
372
373
|
data["irrigated"],
|
|
@@ -422,7 +423,6 @@ def _combine_cycle_blank_nodes(
|
|
|
422
423
|
cycles: List[CycleFormatted], completeness: Dict[str, int], cycle_count: int
|
|
423
424
|
):
|
|
424
425
|
def combine(group: dict, list_key: str):
|
|
425
|
-
now = current_time_ms()
|
|
426
426
|
# get all possible keys first, then group each key values into a single blank node
|
|
427
427
|
keys = set(flatten([list(cycle.get(list_key, {}).keys()) for cycle in cycles]))
|
|
428
428
|
group[list_key] = reduce(
|
|
@@ -430,11 +430,6 @@ def _combine_cycle_blank_nodes(
|
|
|
430
430
|
keys,
|
|
431
431
|
{},
|
|
432
432
|
)
|
|
433
|
-
logger.debug(
|
|
434
|
-
"function=_combine_cycle_blank_nodes, list_key=%s, time=%s",
|
|
435
|
-
list_key,
|
|
436
|
-
current_time_ms() - now,
|
|
437
|
-
)
|
|
438
433
|
return group
|
|
439
434
|
|
|
440
435
|
return combine
|
|
@@ -534,14 +529,8 @@ def _group_site_blank_nodes(
|
|
|
534
529
|
site: SiteJSONLD, start_year: int = None, end_year: int = None
|
|
535
530
|
):
|
|
536
531
|
def grouper(group: dict, list_key: str) -> Dict[str, BlankNodeFormatted]:
|
|
537
|
-
now = current_time_ms()
|
|
538
532
|
blank_nodes = _filter_blank_nodes(site, list_key, start_year, end_year)
|
|
539
533
|
group[list_key] = reduce(_group_site_blank_node(), blank_nodes, {})
|
|
540
|
-
logger.debug(
|
|
541
|
-
"function=_group_site_blank_nodes, list_key=%s, time=%s",
|
|
542
|
-
list_key,
|
|
543
|
-
current_time_ms() - now,
|
|
544
|
-
)
|
|
545
534
|
return group
|
|
546
535
|
|
|
547
536
|
return grouper
|
|
@@ -588,15 +577,9 @@ def _combine_site_blank_node(sites: List[SiteFormatted], list_key: str):
|
|
|
588
577
|
|
|
589
578
|
def _combine_site_blank_nodes(sites: List[SiteFormatted]):
|
|
590
579
|
def combine(group: dict, list_key: str):
|
|
591
|
-
now = current_time_ms()
|
|
592
580
|
# get all possible keys first, then group each key values into a single blank node
|
|
593
581
|
keys = set(flatten([list(site.get(list_key, {}).keys()) for site in sites]))
|
|
594
582
|
group[list_key] = reduce(_combine_site_blank_node(sites, list_key), keys, {})
|
|
595
|
-
logger.debug(
|
|
596
|
-
"function=_combine_site_blank_nodes, list_key=%s, time=%s",
|
|
597
|
-
list_key,
|
|
598
|
-
current_time_ms() - now,
|
|
599
|
-
)
|
|
600
583
|
return group
|
|
601
584
|
|
|
602
585
|
return combine
|
|
@@ -682,15 +665,9 @@ def _aggregate_formatted(
|
|
|
682
665
|
data: Union[CycleFormatted, SiteFormatted], aggregated_keys: List[str]
|
|
683
666
|
):
|
|
684
667
|
def aggregate(key: str):
|
|
685
|
-
now = current_time_ms()
|
|
686
668
|
values = data.get(key, {}).values()
|
|
687
669
|
logger.debug(f"Aggregating {len(values)} {key}...")
|
|
688
670
|
values = list(map(_aggregate_blank_node, values))
|
|
689
|
-
logger.debug(
|
|
690
|
-
"function=_aggregate_formatted, key=%s, time=%s",
|
|
691
|
-
key,
|
|
692
|
-
current_time_ms() - now,
|
|
693
|
-
)
|
|
694
671
|
return values
|
|
695
672
|
|
|
696
673
|
return reduce(lambda group, key: group | {key: aggregate(key)}, aggregated_keys, {})
|
|
@@ -6,11 +6,9 @@ from hestia_earth.utils.tools import (
|
|
|
6
6
|
list_sum,
|
|
7
7
|
list_average,
|
|
8
8
|
is_boolean,
|
|
9
|
-
current_time_ms,
|
|
10
9
|
)
|
|
11
10
|
from hestia_earth.utils.blank_node import get_node_value
|
|
12
11
|
|
|
13
|
-
from hestia_earth.aggregation.log import logger
|
|
14
12
|
from . import weighted_average, _min, _max, _sd, format_evs, pick
|
|
15
13
|
from .emission import get_method_tier, get_method_model
|
|
16
14
|
from .property import aggregate_properties
|
|
@@ -190,7 +188,6 @@ def _aggregate_nodes(
|
|
|
190
188
|
aggregate_keys: List[str], data: dict, weights: dict, missing_weights_node_id_func
|
|
191
189
|
):
|
|
192
190
|
def aggregate_single(key: str):
|
|
193
|
-
now = current_time_ms()
|
|
194
191
|
aggregates_map: dict = data.get(key)
|
|
195
192
|
terms = aggregates_map.keys()
|
|
196
193
|
values = non_empty_list(
|
|
@@ -199,9 +196,6 @@ def _aggregate_nodes(
|
|
|
199
196
|
terms,
|
|
200
197
|
)
|
|
201
198
|
)
|
|
202
|
-
logger.debug(
|
|
203
|
-
"function=_aggregate_nodes, key=%s, time=%s", key, current_time_ms() - now
|
|
204
|
-
)
|
|
205
199
|
return values
|
|
206
200
|
|
|
207
201
|
return reduce(
|
|
@@ -41,15 +41,18 @@ from .practice import new_practice, organic_practice
|
|
|
41
41
|
from .product import new_product
|
|
42
42
|
from .weights import format_weights
|
|
43
43
|
|
|
44
|
-
_MEAN_DATE_DESCRIPTION = (
|
|
45
|
-
"Additional notes: the mean endDate of all aggregated Cycles is "
|
|
46
|
-
)
|
|
47
|
-
|
|
48
44
|
|
|
49
45
|
def _timestamp():
|
|
50
46
|
return datetime.now().strftime("%Y%m%d")
|
|
51
47
|
|
|
52
48
|
|
|
49
|
+
def _mean_date_description(start: int, end: int, average: int):
|
|
50
|
+
return (
|
|
51
|
+
f"While the aggregation is for the period {start} - {end}, "
|
|
52
|
+
+ f"the average end date of all aggregated Cycles is {average}."
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
53
56
|
def _mean_date(dates: list):
|
|
54
57
|
years = [int(d.split("-")[0]) for d in dates]
|
|
55
58
|
return str(round(mean(years))) if years else ""
|
|
@@ -58,13 +61,17 @@ def _mean_date(dates: list):
|
|
|
58
61
|
def _combine_mean_dates(cycles: list):
|
|
59
62
|
# parse the mean date from the description of sub-country nodes
|
|
60
63
|
descriptions = non_empty_list(map(lambda c: c.get("description"), cycles))
|
|
61
|
-
dates = [v
|
|
64
|
+
dates = [v[-5:-1] for v in descriptions]
|
|
62
65
|
return _mean_date(dates)
|
|
63
66
|
|
|
64
67
|
|
|
65
68
|
def _aggregated_weights(weights: dict):
|
|
66
|
-
description = format_weights(weights.values())
|
|
67
|
-
return (
|
|
69
|
+
description = format_weights(weights.values(), include_default_combinations=True)
|
|
70
|
+
return (
|
|
71
|
+
f"This aggregation uses the following weights on sub-systems: {description}"
|
|
72
|
+
if description
|
|
73
|
+
else ""
|
|
74
|
+
)
|
|
68
75
|
|
|
69
76
|
|
|
70
77
|
def is_organic(cycle: dict):
|
|
@@ -170,9 +177,7 @@ def _format_results(
|
|
|
170
177
|
"products": non_empty_list(map(_format_aggregate(new_product), products)),
|
|
171
178
|
}
|
|
172
179
|
# aggregate emissions after as it needs inputs and products
|
|
173
|
-
cycle["emissions"] = non_empty_list(
|
|
174
|
-
map(_format_aggregate(new_emission(product)), emissions)
|
|
175
|
-
)
|
|
180
|
+
cycle["emissions"] = non_empty_list(map(_format_aggregate(new_emission), emissions))
|
|
176
181
|
|
|
177
182
|
# set the primary product
|
|
178
183
|
primary_product = find_term_match(cycle.get("products", []), product.get("@id"))
|
|
@@ -183,7 +188,9 @@ def _format_results(
|
|
|
183
188
|
return {}
|
|
184
189
|
|
|
185
190
|
|
|
186
|
-
def format_terms_results(
|
|
191
|
+
def format_terms_results(
|
|
192
|
+
data: dict, product: dict, country: dict, start_year: int, end_year: int
|
|
193
|
+
):
|
|
187
194
|
inputs = data.get("inputs", [])
|
|
188
195
|
practices = data.get("practices", [])
|
|
189
196
|
products = data.get("products", [])
|
|
@@ -193,8 +200,11 @@ def format_terms_results(data: dict, product: dict, country: dict):
|
|
|
193
200
|
cycle = _format_results(
|
|
194
201
|
cycle=_create_cycle(
|
|
195
202
|
{
|
|
196
|
-
"description":
|
|
197
|
-
|
|
203
|
+
"description": _mean_date_description(
|
|
204
|
+
start=start_year,
|
|
205
|
+
end=end_year,
|
|
206
|
+
average=_mean_date(data.get("endDate")),
|
|
207
|
+
)
|
|
198
208
|
}
|
|
199
209
|
),
|
|
200
210
|
product=product,
|
|
@@ -259,7 +269,11 @@ def format_country_results(
|
|
|
259
269
|
non_empty_list(
|
|
260
270
|
[
|
|
261
271
|
_aggregated_weights(weights),
|
|
262
|
-
|
|
272
|
+
_mean_date_description(
|
|
273
|
+
start=cycle.get("startDate"),
|
|
274
|
+
end=cycle.get("endDate"),
|
|
275
|
+
average=_combine_mean_dates(cycles),
|
|
276
|
+
),
|
|
263
277
|
]
|
|
264
278
|
)
|
|
265
279
|
),
|
|
@@ -2,62 +2,58 @@ from hestia_earth.schema import (
|
|
|
2
2
|
EmissionMethodTier,
|
|
3
3
|
SchemaType,
|
|
4
4
|
EmissionStatsDefinition,
|
|
5
|
-
TermTermType,
|
|
6
5
|
)
|
|
7
6
|
from hestia_earth.utils.model import linked_node
|
|
8
7
|
from hestia_earth.utils.lookup_utils import is_in_system_boundary
|
|
9
8
|
from hestia_earth.utils.tools import flatten, non_empty_list
|
|
10
9
|
|
|
10
|
+
from hestia_earth.aggregation.recalculate_cycles import should_recalculate
|
|
11
11
|
from . import _unique_nodes, _set_dict_single
|
|
12
12
|
from .term import METHOD_MODEL
|
|
13
13
|
|
|
14
14
|
_DEFAULT_TIER = EmissionMethodTier.TIER_1.value
|
|
15
|
-
_SKIP_BACKGROUND_EMISSIONS = [TermTermType.PROCESSEDFOOD.value]
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
def
|
|
17
|
+
def include_emission(emission: dict, product: dict):
|
|
19
18
|
return any(
|
|
20
19
|
[
|
|
21
20
|
emission.get("methodTier") != EmissionMethodTier.BACKGROUND.value,
|
|
22
|
-
product
|
|
21
|
+
not should_recalculate(product),
|
|
23
22
|
]
|
|
24
23
|
)
|
|
25
24
|
|
|
26
25
|
|
|
27
|
-
def new_emission(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return node if _include_emission(node, product) else None
|
|
59
|
-
|
|
60
|
-
return emission
|
|
26
|
+
def new_emission(data: dict):
|
|
27
|
+
term = data.get("term", {})
|
|
28
|
+
# only add emissions included in the System Boundary
|
|
29
|
+
if is_in_system_boundary(term.get("@id")):
|
|
30
|
+
node = {"@type": SchemaType.EMISSION.value}
|
|
31
|
+
node["term"] = linked_node(term)
|
|
32
|
+
value = data.get("value")
|
|
33
|
+
if value is not None:
|
|
34
|
+
node["value"] = [value]
|
|
35
|
+
node["statsDefinition"] = EmissionStatsDefinition.CYCLES.value
|
|
36
|
+
|
|
37
|
+
node["methodTier"] = data.get("methodTier") or _DEFAULT_TIER
|
|
38
|
+
node["methodModel"] = data.get("methodModel") or METHOD_MODEL
|
|
39
|
+
|
|
40
|
+
inputs = data.get("inputs", [])
|
|
41
|
+
# compute list of unique inputs, required for `background` emissions
|
|
42
|
+
if inputs:
|
|
43
|
+
_set_dict_single(
|
|
44
|
+
node,
|
|
45
|
+
"inputs",
|
|
46
|
+
list(map(linked_node, _unique_nodes(inputs))),
|
|
47
|
+
strict=True,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if node.get("methodTier") != EmissionMethodTier.NOT_RELEVANT.value:
|
|
51
|
+
_set_dict_single(
|
|
52
|
+
node, "distribution", data.get("distribution"), strict=True
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
_set_dict_single(node, "description", data.get("description"), strict=True)
|
|
56
|
+
return node
|
|
61
57
|
|
|
62
58
|
|
|
63
59
|
def get_method_tier(emissions: list):
|
|
@@ -175,16 +175,19 @@ def _calculate_score_emissions_system_boundary(cycle: dict, *args):
|
|
|
175
175
|
# get all emissions in the system boundary
|
|
176
176
|
all_emissions_ids = cycle_emissions_in_system_boundary(cycle)
|
|
177
177
|
# ignore emissions that should be skipped in aggregation
|
|
178
|
-
|
|
178
|
+
skipped_emission_ids = [
|
|
179
179
|
id
|
|
180
180
|
for id in all_emissions_ids
|
|
181
|
-
if should_aggregate_blank_node(
|
|
181
|
+
if not should_aggregate_blank_node(
|
|
182
182
|
{
|
|
183
183
|
"@type": SchemaType.EMISSION.value,
|
|
184
184
|
"term": {"@id": id, "termType": TermTermType.EMISSION.value},
|
|
185
185
|
}
|
|
186
186
|
)
|
|
187
187
|
]
|
|
188
|
+
all_emissions_ids = [
|
|
189
|
+
id for id in all_emissions_ids if id not in skipped_emission_ids
|
|
190
|
+
]
|
|
188
191
|
|
|
189
192
|
# get all emissions in the Cycle that are in the system boundary
|
|
190
193
|
emissions_ids = list(
|
|
@@ -207,6 +210,7 @@ def _calculate_score_emissions_system_boundary(cycle: dict, *args):
|
|
|
207
210
|
included_emissions=len(emissions_ids),
|
|
208
211
|
all_included=all_included,
|
|
209
212
|
missing_emissions=";".join(missing_emissions),
|
|
213
|
+
excluded_emissions=";".join(skipped_emission_ids),
|
|
210
214
|
)
|
|
211
215
|
|
|
212
216
|
return all_included
|
|
@@ -16,18 +16,40 @@ from .term import (
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
def _weight_to_key(weights: list):
|
|
20
|
+
return "_".join(non_empty_list(weights))
|
|
21
|
+
|
|
22
|
+
|
|
19
23
|
def _format_weight_key(key: str):
|
|
20
24
|
return ", ".join(key.split("_")).capitalize()
|
|
21
25
|
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
_WEIGHTS_KEYS = [["organic", "conventional"], ["irrigated", "non-irrigated"]]
|
|
28
|
+
_WEIGHTS_COMBINATIONS = [
|
|
29
|
+
_weight_to_key([organic_key, irrigated_key])
|
|
30
|
+
for organic_key in _WEIGHTS_KEYS[0]
|
|
31
|
+
for irrigated_key in _WEIGHTS_KEYS[1]
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def format_weights(weights: list, include_default_combinations: bool = False):
|
|
24
36
|
total = list_sum(non_empty_list([w.get("weight") for w in weights]))
|
|
25
|
-
|
|
37
|
+
included_keys = non_empty_list([weight.get("key") for weight in weights])
|
|
38
|
+
return "; ".join(
|
|
26
39
|
[
|
|
27
|
-
f"{_format_weight_key(weight.get('key'))}: {round(weight.get('weight') * 100 / total, 2)}"
|
|
40
|
+
f"{_format_weight_key(weight.get('key'))}: {round(weight.get('weight') * 100 / total, 2)}%"
|
|
28
41
|
for weight in weights
|
|
29
42
|
if weight.get("key")
|
|
30
43
|
]
|
|
44
|
+
+ (
|
|
45
|
+
[
|
|
46
|
+
f"{_format_weight_key(key)}: 0%"
|
|
47
|
+
for key in _WEIGHTS_COMBINATIONS
|
|
48
|
+
if key not in included_keys
|
|
49
|
+
]
|
|
50
|
+
if include_default_combinations and included_keys
|
|
51
|
+
else []
|
|
52
|
+
)
|
|
31
53
|
)
|
|
32
54
|
|
|
33
55
|
|
|
@@ -119,13 +141,11 @@ def _country_weights(
|
|
|
119
141
|
weight = (organic_weight if node.get("organic", False) else 1 - organic_weight) * (
|
|
120
142
|
irrigated_weight if node.get("irrigated", False) else 1 - irrigated_weight
|
|
121
143
|
)
|
|
122
|
-
key =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
]
|
|
128
|
-
)
|
|
144
|
+
key = _weight_to_key(
|
|
145
|
+
[
|
|
146
|
+
"organic" if node.get("organic", False) else "conventional",
|
|
147
|
+
"irrigated" if node.get("irrigated", False) else "non-irrigated",
|
|
148
|
+
]
|
|
129
149
|
)
|
|
130
150
|
return {node_id: {"weight": weight, "completeness": completeness, "key": key}}
|
|
131
151
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
VERSION = "0.21.
|
|
1
|
+
VERSION = "0.21.17"
|
{hestia_earth_aggregation-0.21.15.dist-info → hestia_earth_aggregation-0.21.17.dist-info}/RECORD
RENAMED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
hestia_earth/aggregation/__init__.py,sha256=
|
|
2
|
-
hestia_earth/aggregation/aggregate_cycles.py,sha256=
|
|
1
|
+
hestia_earth/aggregation/__init__.py,sha256=kSK6RYcK0YnRGx6TknaukhuhbnxRHofLI_8PA0-k8Yg,3339
|
|
2
|
+
hestia_earth/aggregation/aggregate_cycles.py,sha256=MR-SseQRMGFUOKiBJcLVysjdjw5J-QfJ258VxGhasFw,7868
|
|
3
3
|
hestia_earth/aggregation/log.py,sha256=0CibXDtKqFfE-R86qziM2uH7ATUZ6I9p_bVpRSn_e_o,2351
|
|
4
|
-
hestia_earth/aggregation/recalculate_cycles.py,sha256=
|
|
5
|
-
hestia_earth/aggregation/version.py,sha256=
|
|
6
|
-
hestia_earth/aggregation/config/Cycle/
|
|
4
|
+
hestia_earth/aggregation/recalculate_cycles.py,sha256=igMxKd7_K0MFlAt3Q_OynvHxDo3ldTixWbXjaC4M71c,510
|
|
5
|
+
hestia_earth/aggregation/version.py,sha256=hcVLcttb0pemu91UT65kphAN_tKjRCwH4PaeO6euVl8,20
|
|
6
|
+
hestia_earth/aggregation/config/Cycle/crop.json,sha256=OBYXxleifxg9EJfZsqR1dgCxlEe2lIrCBqMe_Jo5XE4,1387
|
|
7
|
+
hestia_earth/aggregation/config/Cycle/processedFood.json,sha256=OBYXxleifxg9EJfZsqR1dgCxlEe2lIrCBqMe_Jo5XE4,1387
|
|
7
8
|
hestia_earth/aggregation/utils/__init__.py,sha256=nVVLgVFZ4415CgQAqgv4jDamA7gDmzOWk5SY4vshAQs,6583
|
|
8
|
-
hestia_earth/aggregation/utils/aggregate_country_nodes.py,sha256=
|
|
9
|
-
hestia_earth/aggregation/utils/aggregate_weighted.py,sha256=
|
|
9
|
+
hestia_earth/aggregation/utils/aggregate_country_nodes.py,sha256=RIJYaWNNdnlCif6EgF-mG_HsfwuchSOHEgvE8eYl-NU,28116
|
|
10
|
+
hestia_earth/aggregation/utils/aggregate_weighted.py,sha256=OzrYhbL7g-X_1x7BLEwkxqLlDOLQ7CdFV8UuQTzQEz4,6817
|
|
10
11
|
hestia_earth/aggregation/utils/blank_node.py,sha256=f8JBcd5_SLqW8juzFAfbZysAESaZXj8JX6C7rDkLEoc,16812
|
|
11
12
|
hestia_earth/aggregation/utils/combine.py,sha256=EmXUZksdkrtQ6o1gMOG5WMivUhL28NKSM9D4cPohJiE,4904
|
|
12
13
|
hestia_earth/aggregation/utils/completeness.py,sha256=eZ759PAdOSshhys-YKKPEpAYxR3sTrEjI--WJTEwmus,4633
|
|
13
14
|
hestia_earth/aggregation/utils/covariance.py,sha256=2VaNGPvyD4ub3rR-OBn8VIEIeAz4JOefl6ZlAtXKj4U,5884
|
|
14
|
-
hestia_earth/aggregation/utils/cycle.py,sha256=
|
|
15
|
+
hestia_earth/aggregation/utils/cycle.py,sha256=ohFc2rtzi7cJZatBll8JFoAFK0PB7CzVtccnyvzkfsU,16471
|
|
15
16
|
hestia_earth/aggregation/utils/distribution.py,sha256=2XQKXVu-1XUy1zEHgThERupaj4RizXKO5F-VY-QQlMo,6935
|
|
16
|
-
hestia_earth/aggregation/utils/emission.py,sha256=
|
|
17
|
+
hestia_earth/aggregation/utils/emission.py,sha256=fmzi2GHhG1E5Ioi00D1vVIPZwqaDB7P4-NxGwX64KyI,2745
|
|
17
18
|
hestia_earth/aggregation/utils/group.py,sha256=qU9sAuJu0RG80yLs90nsyoOcU57Pb6M1WKwT1TlJEkM,4765
|
|
18
19
|
hestia_earth/aggregation/utils/input.py,sha256=pZ1bcdHR3y4S-3b0JZllbEUWdEyVZbltxv-07j7SucI,1092
|
|
19
20
|
hestia_earth/aggregation/utils/lookup.py,sha256=osJiXTRns5KeBMz3mRsanmFQTATrwcMVBzB07xrb71M,2046
|
|
@@ -22,14 +23,14 @@ hestia_earth/aggregation/utils/measurement.py,sha256=tdQwjo1hPb3iAaboBQiua832q27
|
|
|
22
23
|
hestia_earth/aggregation/utils/practice.py,sha256=MXZsQoeSXxe2vmdjvyS58HZN9jejPZNbVnczTc3HxxU,2252
|
|
23
24
|
hestia_earth/aggregation/utils/product.py,sha256=dEUCy0eakyKyD2vu1RRnF4bdAI-jpS-qePNF8ZGhHFE,886
|
|
24
25
|
hestia_earth/aggregation/utils/property.py,sha256=n_aHZ4qASv_wcDJ_HrA1T2kFX8R2zUEo91LCPL5xWkw,917
|
|
25
|
-
hestia_earth/aggregation/utils/quality_score.py,sha256=
|
|
26
|
+
hestia_earth/aggregation/utils/quality_score.py,sha256=PPNRW1wEkVqP7QExyu5dcr8R_Z_DWkmT3zmQG9u470Y,8914
|
|
26
27
|
hestia_earth/aggregation/utils/queries.py,sha256=kzob6CHL1a60CRJdGICiWS98LKJRyq3uaToyuQyl9RI,17564
|
|
27
28
|
hestia_earth/aggregation/utils/site.py,sha256=nc1N4IRiTki69IbCX4G6lagQ5U7IpsOsqiPuHwbl1HM,5455
|
|
28
29
|
hestia_earth/aggregation/utils/source.py,sha256=SOiE-jB5WNtbRxreUWQ8c04ywzrwICy1aGyRL3-L0RY,686
|
|
29
30
|
hestia_earth/aggregation/utils/term.py,sha256=uVAfBYnxNkcTNfzuwwHur6JGBahNrPwR2pN-__sj9zk,2758
|
|
30
|
-
hestia_earth/aggregation/utils/weights.py,sha256=
|
|
31
|
-
hestia_earth_aggregation-0.21.
|
|
32
|
-
hestia_earth_aggregation-0.21.
|
|
33
|
-
hestia_earth_aggregation-0.21.
|
|
34
|
-
hestia_earth_aggregation-0.21.
|
|
35
|
-
hestia_earth_aggregation-0.21.
|
|
31
|
+
hestia_earth/aggregation/utils/weights.py,sha256=Qk5hCr_K24DzkeE4Sa241pGb6m00iaWHIXFQAJ-cDGc,7518
|
|
32
|
+
hestia_earth_aggregation-0.21.17.dist-info/licenses/LICENSE,sha256=TD25LoiRJsA5CPUNrcyt1PXlGcbUGFMAeZoBcfCrCNE,1154
|
|
33
|
+
hestia_earth_aggregation-0.21.17.dist-info/METADATA,sha256=fgZq8hdf22iumAqR_xOGtVJcOoKfSKnaexEakj6H7YA,2481
|
|
34
|
+
hestia_earth_aggregation-0.21.17.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
35
|
+
hestia_earth_aggregation-0.21.17.dist-info/top_level.txt,sha256=q0QxKEYx9uLpAD5ZtC7Ypq29smEPfOzEAn7Xv8XHGOQ,13
|
|
36
|
+
hestia_earth_aggregation-0.21.17.dist-info/RECORD,,
|
{hestia_earth_aggregation-0.21.15.dist-info → hestia_earth_aggregation-0.21.17.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|