Skip to main content

edges: Edge-based life cycle impact assessment

PyPI version

edges is a library allowing flexible Life Cycle Impact Assessment (LCIA) for the brightway2/brightway25 LCA framework.

Unlike traditional LCIA methods that apply characterization factors (CFs) solely to nodes (e.g., elementary flows), edges applies CFs directly on the edges — the exchanges between suppliers and consumers — allowing for more precise and context-sensitive impact characterization.

This approach enables LCIA factors to reflect the specific context of each exchange, including parameters such as:

  • Geographic region of production and consumption
  • Magnitude of flows
  • Scenario-based parameters (e.g., changing atmospheric conditions)

The edges Python library offers a novel approach to applying characterization factors (CFs) during the impact assessment phase of Life Cycle Assessment (LCA). Unlike conventional methods that uniformly assign CFs to nodes (e.g., processes like Water, from well in the brightway2 ecosystem), edges shifts the focus to the edges—the exchanges or relationships between nodes. This allows CFs to be conditioned based on the specific context of each exchange. Essentially, edges introduces unique values in the characterization matrix tailored to the characteristics of each edge.

By focusing on edges, the library incorporates contextual information such as the attributes of both the supplier and the consumer (e.g., geographic location, ISIC classification, amount exchanged, etc.). This enables a more detailed and flexible impact characterization, accommodating parameters like the location of the consumer and the magnitude of the exchange.

When necessary, custom CF definitions can also match on unit to distinguish flows that would otherwise share the same name, location, categories, or reference product.

Furthermore, edges supports the calculation of weighted CFs for both static regions (e.g., RER) and dynamic regions (e.g., RoW), enhancing its ability to model complex and region-specific scenarios.

Key Features

  • Edge-based CFs: Assign CFs specifically to individual exchanges between processes.
  • Geographic resolution: Supports 346 national and sub-national regions.
  • Scenario-based flexibility: Incorporate parameters (e.g., CO₂ atmospheric concentration) directly in CF calculations, enabling dynamic scenario analysis.
  • Efficient workflow: Clearly separates expensive exchange-mapping tasks (performed once) from inexpensive scenario-based numeric CF evaluations.
  • Transparent reporting: Can expand weighted fallback consumer regions into country-specific rows in the detailed CF table for deterministic runs.
  • Mixed supplier matrices: Supports method files that combine biosphere-technosphere and technosphere-technosphere CF rows in one JSON file.

Currently, the library provides regionalized CFs for:

  • AWARE 2.0 (water scarcity impacts)
  • ImpactWorld+ 2.1
  • GeoPolRisk 1.0
  • GLAM3 Land use impacts on biodiversity
  • IBIF v2 biodiversity intactness (CO2, NH3, NOx, land occupation, roads, and all pressures)
  • Swiss Ecological Scarcity 2021 (UBP total and all 20 categories, including Noise)

For UBP comparisons across software, see the SimaPro comparison evidence and modelling differences. Agreement with another implementation is a diagnostic check, not proof of correctness.

[!NOTE] Mixed CF methods combining both biosphere and technosphere supplier matrices in a single method file are supported. lci() builds both edge families, lcia() sums both contributions, and generate_cf_table() reports supplier matrix and direction columns so mixed results remain inspectable.

[!NOTE] The exchange matcher backend is CLIPSpy (matcher_backend="clips"), the Python wrapper for CLIPS.

Installation

You can install the library using pip:

pip install edges

[!NOTE] The library is compatible with both brightway2 and brightway25. Please ensure you have one of these frameworks installed in your Python environment.

Documentation

Getting Started

Check out the examples' notebook.

Check available methods from edges

    
from edges import get_available_methods

# Get the available methods
methods = get_available_methods()
print(methods)

Perform edge-based LCIA with edges

import bw2data
from edges import EdgeLCIA

# Select an activity from the LCA database
act = bw2data.Database("ecoinvent-3.10-cutoff").random()

# Define a method
method = ('AWARE 2.0', 'Country', 'unspecified', 'yearly')
# Prospective variant: ('AWARE 2.0 prospective', 'Country', 'all', 'yearly')
# Swiss Ecological Scarcity total: ('Ecological Scarcity 2021', 'total', 'UBP')

# Initialize the LCA object
LCA = EdgeLCIA({act: 1}, method)
LCA.lci()

# Map CFs to exchanges: apply suggested strategies
LCA.apply_strategies()

# or apply these strategies manually
#LCA.map_exchanges()

# If needed, extend the mapping to aggregated and `dynamic` regions (e.g., RoW)
#LCA.map_aggregate_locations()
#LCA.map_dynamic_locations()
#LCA.map_contained_locations()

# add global CFs to exchanges missing a CF
#LCA.map_remaining_locations_to_global()

# Evaluate CFs
LCA.evaluate_cfs()

# Perform the LCIA calculation
LCA.lcia()
print(LCA.score)

# Optional but recommended: print a dataframe with the characterization factors used
# this allows you to check whether exchanges have been given the correct CFs
# include_unmatched=True allows you to see which exchanges were not matched (and if some should have been)
# split_aggregate_consumers=True expands weighted consumer fallback rows
# (e.g. RER, GLO, RoW, RoE) into country rows in deterministic runs
LCA.generate_cf_table(split_aggregate_consumers=True)

For deterministic regionalized runs, generate_cf_table(split_aggregate_consumers=True) replaces weighted fallback rows for aggregate or dynamic consumer regions with country-specific rows whose amount and impact sum back to the original row. The raw split used for each exchange is also available after evaluate_cfs() via lca.scenario_cfs[*]["reporting_split"].

When a method mixes biosphere- and technosphere-supplier CFs, the exported table includes supplier matrix and direction columns so you can tell which contributions came from biosphere-technosphere versus technosphere-technosphere matches.

Perform parameter-based LCIA

Consider the following LCIA data file (saved under gwp_example.json)`:

{
  "name": "Example LCIA Method",
    "version": "1.0",
    "description": "Example LCIA method for greenhouse gas emissions",
    "unit": "kg CO2e",
    "exchanges": [
      {
        "supplier": {
          "name": "Carbon dioxide",
          "operator": "startswith",
          "matrix": "biosphere"
        },
        "consumer": {
          "matrix": "technosphere",
          "type": "process"
        },
        "value": "1.0"
      },
      {
        "supplier": {
          "name": "Methane, fossil",
          "operator": "contains",
          "matrix": "biosphere"
        },
        "consumer": {
          "matrix": "technosphere",
          "type": "process"
        },
        "value": "28 * (1 + 0.001 * (co2ppm - 410))"
      },
      {
        "supplier": {
          "name": "Dinitrogen monoxide",
          "operator": "equals",
          "matrix": "biosphere"
        },
        "consumer": {
          "matrix": "technosphere",
          "type": "process"
        },
        "value": "265 * (1 + 0.0005 * (co2ppm - 410))"
      }
  ]
}

Symbolic CF expressions are intentionally narrow: arithmetic, parameter names, literal values, and bare allowlisted function calls. Arbitrary Python syntax such as attribute access, subscripting, comprehensions, imports, or method calls is rejected. Functions passed through allowed_functions remain trusted Python code.

We can perform a parameter-based LCIA calculation as follows:

import bw2data
from edges import EdgeLCIA

# Select an activity from the LCA database
bw2data.projects.set_current("ecoinvent-3.10.1-cutoff")
act = bw2data.Database("ecoinvent-3.10.1-cutoff").random()
print(act)

# Define scenario parameters (e.g., atmospheric CO₂ concentration and time horizon)
params = {
    "some scenario": {
         "co2ppm": {"2020": 410, "2050": 450, "2100": 500}, "h": {"2020": 100, "2050": 100, "2100": 100}
    }
}

# Define an LCIA method (symbolic CF expressions stored in JSON)
method = ('GWP', 'scenario-dependent', '100 years')

# Initialize LCIA
lcia = EdgeLCIA(
   demand={act: 1},
   filepath="lcia_example_3.json",
   parameters=params
)

# Perform inventory calculations (once)
lcia.lci()

# Map exchanges to CF entries (once)
lcia.map_exchanges()

# Optionally, resolve geographic overlaps and disaggregations (once)
lcia.map_aggregate_locations()
lcia.map_dynamic_locations()
lcia.map_remaining_locations_to_global()

# Run scenarios efficiently
results = []
for idx in {"2020", "2050", "2100"}:
    lcia.evaluate_cfs(idx)
    lcia.lcia()
    df = lcia.generate_cf_table(split_aggregate_consumers=True)

    scenario_result = {
        "scenario": idx,
        "co2ppm": params["some scenario"]["co2ppm"][idx],
        "score": lcia.score,
        "CF_table": df
    }
    results.append(scenario_result)

    print(f"Scenario (CO₂ {params['some scenario']['co2ppm'][idx]} ppm): Impact = {lcia.score}")

Scenario-dependent methods can store expressions directly in value, as older method files do, or keep a numeric baseline value and use value_expression for the dynamic scenario/year value. Regionalized methods can similarly pair numeric weight with weight_expression; aggregate fallback shares are recomputed from evaluated dynamic weights during evaluate_cfs(...). If the method declares an interpolation policy with method: "linear" and extrapolation: "nearest", missing numeric years are linearly interpolated and out-of-range years use the closest available endpoint. Methods without this metadata keep the legacy exact-or-last parameter fallback.

Data Sources

See Methods from Documentation.

Methodology

See Theory from Documentation.

Contributing

Contributions are welcome! Please follow these steps to contribute:

  1. Fork the repository.
  2. Create a new branch for your feature or fix.
  3. Commit your changes.
  4. Submit a pull request.

License

This project is licensed under the MIT License. See the LICENSE.md file for more information.

Contact

For any questions or inquiries, please contact the project maintainer at romain.sacchi@psi.ch.

For questions or issues around the use of edges, you can also join the discussion group at https://premise.groups.io/g/edgese.

Contributors

Acknowledgments

The development of this library was supported by the French agency for Energy ADEME, via the financing of the HySPI project. The HySPI project aims to provide a methodological framework to analyze and quantify, in a systemic and prospective manner, the environmental impacts of the decarbonization strategy of hydrogen production used by the industry in France. We also acknowledge financial support from the Europe Horizon project RAWCLIC as well as the Europe Horizon project PRISMA.

Metadata

Release files for edges 1.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for edges 1.4.1
File Size Uploaded
edges-1.4.1.tar.gz 37.8 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for edges 1.4.1
File Interpreter ABI Platform
edges-1.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 77.0 MB

Release files / edges-1.4.1.tar.gz

Download URL edges-1.4.1.tar.gz
Size 37.8 MB
Tags Source
SHA-256 checksum
How to use checksums
ecd116e3effcb29896a6d4a7af900a3165927acd3c2389aacebd05f1ac9bd3b3
BLAKE2b-256 checksum
How to use checksums
b258b63490b0469a8fb9ae270817c3eee9f37bc73b2f8b79ae725fab7aef6fa4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / edges-1.4.1-py3-none-any.whl

Download URL edges-1.4.1-py3-none-any.whl
Size 39.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
642141ed8e220db83877ae594b13f1b3ffb8476d3aeab7f0e57c0615066ecb6e
BLAKE2b-256 checksum
How to use checksums
fa5be33e260698823fa963ec1c14ba36953280e2da18b053effe1d3900abafc8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

1.4.1 This release

2 release files

1.4.0

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.2.9

2 release files

1.2.8

2 release files

1.2.6

2 release files

1.2.5

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page