hestia-earth-aggregation 0.21.16__py3-none-any.whl → 0.21.18__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.
@@ -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
+ }
@@ -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 os.listdir(CONFIG_PATH)
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,
@@ -68,7 +68,7 @@ def _combine_mean_dates(cycles: list):
68
68
  def _aggregated_weights(weights: dict):
69
69
  description = format_weights(weights.values(), include_default_combinations=True)
70
70
  return (
71
- f"This aggregation uses the following weights on sub-systems: ({description})"
71
+ f"This aggregation uses the following weights on sub-systems: {description}"
72
72
  if description
73
73
  else ""
74
74
  )
@@ -177,9 +177,7 @@ def _format_results(
177
177
  "products": non_empty_list(map(_format_aggregate(new_product), products)),
178
178
  }
179
179
  # aggregate emissions after as it needs inputs and products
180
- cycle["emissions"] = non_empty_list(
181
- map(_format_aggregate(new_emission(product)), emissions)
182
- )
180
+ cycle["emissions"] = non_empty_list(map(_format_aggregate(new_emission), emissions))
183
181
 
184
182
  # set the primary product
185
183
  primary_product = find_term_match(cycle.get("products", []), product.get("@id"))
@@ -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 _include_emission(emission: dict, product: dict):
17
+ def include_emission(emission: dict, product: dict):
19
18
  return any(
20
19
  [
21
20
  emission.get("methodTier") != EmissionMethodTier.BACKGROUND.value,
22
- product.get("termType") not in _SKIP_BACKGROUND_EMISSIONS,
21
+ not should_recalculate(product),
23
22
  ]
24
23
  )
25
24
 
26
25
 
27
- def new_emission(product: dict):
28
- def emission(data: dict):
29
- term = data.get("term", {})
30
- # only add emissions included in the System Boundary
31
- if is_in_system_boundary(term.get("@id")):
32
- node = {"@type": SchemaType.EMISSION.value}
33
- node["term"] = linked_node(term)
34
- value = data.get("value")
35
- if value is not None:
36
- node["value"] = [value]
37
- node["statsDefinition"] = EmissionStatsDefinition.CYCLES.value
38
-
39
- node["methodTier"] = data.get("methodTier") or _DEFAULT_TIER
40
- node["methodModel"] = data.get("methodModel") or METHOD_MODEL
41
-
42
- inputs = data.get("inputs", [])
43
- # compute list of unique inputs, required for `background` emissions
44
- if inputs:
45
- _set_dict_single(
46
- node,
47
- "inputs",
48
- list(map(linked_node, _unique_nodes(inputs))),
49
- strict=True,
50
- )
51
-
52
- if node.get("methodTier") != EmissionMethodTier.NOT_RELEVANT.value:
53
- _set_dict_single(
54
- node, "distribution", data.get("distribution"), strict=True
55
- )
56
-
57
- _set_dict_single(node, "description", data.get("description"), strict=True)
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):
@@ -1,6 +1,7 @@
1
1
  from hestia_earth.schema import ManagementJSONLD
2
2
  from hestia_earth.utils.model import linked_node
3
- from hestia_earth.utils.tools import safe_parse_date
3
+ from hestia_earth.utils.tools import safe_parse_date, flatten
4
+ from hestia_earth.utils.date import gapfill_datestr
4
5
 
5
6
  from . import match_dates, _set_dict_single
6
7
  from .queries import TIME_PERIOD, _get_time_ranges, _current_date
@@ -45,6 +46,34 @@ def aggregated_dates(blank_node: dict):
45
46
  )
46
47
 
47
48
 
49
+ def split_by_dates(blank_nodes: list, start_year: int):
50
+ # if the blank_node overlaps with the start period of the aggregation, we need to split it in 2 parts
51
+ def split_data(blank_node: dict):
52
+ start_date = safe_parse_date(blank_node.get("startDate"), default=None)
53
+ end_date = safe_parse_date(blank_node.get("endDate"), default=None)
54
+ is_overlapping = all([start_date is not None, end_date is not None]) and all(
55
+ [start_date.year < start_year, start_year < end_date.year]
56
+ )
57
+ return (
58
+ [
59
+ blank_node
60
+ | {
61
+ "startDate": blank_node.get("startDate"),
62
+ "endDate": gapfill_datestr(start_year - 1, "end"),
63
+ },
64
+ blank_node
65
+ | {
66
+ "startDate": gapfill_datestr(start_year, "start"),
67
+ "endDate": blank_node.get("endDate"),
68
+ },
69
+ ]
70
+ if is_overlapping
71
+ else blank_node
72
+ )
73
+
74
+ return flatten(map(split_data, blank_nodes))
75
+
76
+
48
77
  def filter_management(blank_nodes: list, start_year: int = None, end_year: int = None):
49
78
  def update_dates(blank_node: dict):
50
79
  start_date = safe_parse_date(blank_node.get("startDate"), default=None)
@@ -72,7 +101,9 @@ def filter_management(blank_nodes: list, start_year: int = None, end_year: int =
72
101
  """
73
102
  return [
74
103
  update_dates(v)
75
- for v in blank_nodes
104
+ for v in (
105
+ split_by_dates(blank_nodes, start_year) if start_year else blank_nodes
106
+ )
76
107
  if not start_year
77
108
  or not end_year
78
109
  or match_dates(v, start_year - TIME_PERIOD, end_year)
@@ -15,7 +15,7 @@ from hestia_earth.aggregation.log import logger
15
15
  from . import HestiaError, _save_json, pick
16
16
  from .term import DEFAULT_COUNTRY_NAME, _fetch_countries, is_global as is_global_country
17
17
 
18
- SEARCH_LIMIT = 10000
18
+ SEARCH_LIMIT = int(os.getenv("SEARCH_LIMIT", "10000"))
19
19
  _MATCH_AGGREGATED_QUERY = {"match": {"aggregated": "true"}}
20
20
  _MATCH_AGGREGATED_VALIDATED_QUERY = {"match": {"aggregatedDataValidated": "true"}}
21
21
  # enable matching any product
@@ -1 +1 @@
1
- VERSION = "0.21.16"
1
+ VERSION = "0.21.18"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hestia_earth_aggregation
3
- Version: 0.21.16
3
+ Version: 0.21.18
4
4
  Summary: HESTIA's aggregation engine.
5
5
  Home-page: https://gitlab.com/hestia-earth/hestia-aggregation-engine
6
6
  Author: HESTIA Team
@@ -1,35 +1,36 @@
1
1
  hestia_earth/aggregation/__init__.py,sha256=kSK6RYcK0YnRGx6TknaukhuhbnxRHofLI_8PA0-k8Yg,3339
2
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=xCO_tj5BAC407vZ36EVuxeOBmX2y82EXRrTx5W6g4CY,484
5
- hestia_earth/aggregation/version.py,sha256=Mlni8p7cuSE5CwxrazB-rArGWlKBFeBsDeVs2L8bT_E,20
4
+ hestia_earth/aggregation/recalculate_cycles.py,sha256=igMxKd7_K0MFlAt3Q_OynvHxDo3ldTixWbXjaC4M71c,510
5
+ hestia_earth/aggregation/version.py,sha256=l0WM7ge0CXaUMWDGZjVN-Bv5P4kpSeFzwkayyG9kADw,20
6
+ hestia_earth/aggregation/config/Cycle/crop.json,sha256=OBYXxleifxg9EJfZsqR1dgCxlEe2lIrCBqMe_Jo5XE4,1387
6
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=FkfiOcWIE9a8duowZgOtFiyr4m-UwnawXRiZ-geRrTY,27924
9
+ hestia_earth/aggregation/utils/aggregate_country_nodes.py,sha256=RIJYaWNNdnlCif6EgF-mG_HsfwuchSOHEgvE8eYl-NU,28116
9
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=d65RvgqJiq4sr12SShLKjM50MO95V07I88LU7p__Ixc,16496
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=2roXjGmDuS7a3muPJoEOqg7E-TZyQsnoavhU6b3B-Z8,2983
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
20
- hestia_earth/aggregation/utils/management.py,sha256=wrgNHhWuDTWmpRdKNi9BKg7GQRL8CJVAjcW1aeRaiyM,2891
21
+ hestia_earth/aggregation/utils/management.py,sha256=tr46zD8HrmRjEQnhMJ5s9eYapd8CKs4Gr99aZGLo1kY,4117
21
22
  hestia_earth/aggregation/utils/measurement.py,sha256=tdQwjo1hPb3iAaboBQiua832q27xZb_a9KqIp3iQkuE,1463
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
26
  hestia_earth/aggregation/utils/quality_score.py,sha256=PPNRW1wEkVqP7QExyu5dcr8R_Z_DWkmT3zmQG9u470Y,8914
26
- hestia_earth/aggregation/utils/queries.py,sha256=kzob6CHL1a60CRJdGICiWS98LKJRyq3uaToyuQyl9RI,17564
27
+ hestia_earth/aggregation/utils/queries.py,sha256=S9JZ3km_7EkbPDV0piQxfXMDF0qa2eXKdN0mz7oIkf8,17598
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
31
  hestia_earth/aggregation/utils/weights.py,sha256=Qk5hCr_K24DzkeE4Sa241pGb6m00iaWHIXFQAJ-cDGc,7518
31
- hestia_earth_aggregation-0.21.16.dist-info/licenses/LICENSE,sha256=TD25LoiRJsA5CPUNrcyt1PXlGcbUGFMAeZoBcfCrCNE,1154
32
- hestia_earth_aggregation-0.21.16.dist-info/METADATA,sha256=38XSLUkdQu3ePpK38m0b_ZjiLPjWqANxTFmEk9dshCs,2481
33
- hestia_earth_aggregation-0.21.16.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
34
- hestia_earth_aggregation-0.21.16.dist-info/top_level.txt,sha256=q0QxKEYx9uLpAD5ZtC7Ypq29smEPfOzEAn7Xv8XHGOQ,13
35
- hestia_earth_aggregation-0.21.16.dist-info/RECORD,,
32
+ hestia_earth_aggregation-0.21.18.dist-info/licenses/LICENSE,sha256=TD25LoiRJsA5CPUNrcyt1PXlGcbUGFMAeZoBcfCrCNE,1154
33
+ hestia_earth_aggregation-0.21.18.dist-info/METADATA,sha256=1WmgTNGYc4EQFS6ltVH_UQkThgZAm1gM2z84cuCiDLk,2481
34
+ hestia_earth_aggregation-0.21.18.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
35
+ hestia_earth_aggregation-0.21.18.dist-info/top_level.txt,sha256=q0QxKEYx9uLpAD5ZtC7Ypq29smEPfOzEAn7Xv8XHGOQ,13
36
+ hestia_earth_aggregation-0.21.18.dist-info/RECORD,,