brightway-lca / brightway2-data

Tools for the management of inventory databases and impact assessment methods. Part of the Brightway LCA framework.
https://docs.brightway.dev/
BSD 3-Clause "New" or "Revised" License
11 stars 25 forks source link

SimaPro import - Flip sign on waste treatment exchanges linking to ecoinvent #66

Closed aleksandra-kim closed 3 years ago

aleksandra-kim commented 5 years ago

Original report by Pascal Lesage (Bitbucket: MPa, ).


The ecoinvent database uses a convention by which waste and waste treatment exchanges are negative (both for technosphere and production exchanges).

SimaPro does not follow this convention and, from the looks of it, actually flipped the sign of these exchanges.

When importing a SimaPro csv, therefore, the sign of waste exchanges linking to ecoinvent are wrong: they are positive, they link to activities with negative production exchanges, which results in the LCI and LCIA associated with wastes being the wrong sign.

I fix this with an “additional strategy”, as follows (line 6 and forward):

sp = SimaProCSVImporter("my_csv_path.csv", 'db_name')
sp.migrate('simapro-ecoinvent-3.4')
sp.apply_strategies()
sp.match_database("ecoinvent_db_name",fields=["name", "location", "reference product"])

# Additional strategy
for act in sp.data:
    for exc in act['exchanges']:
        if exc['input'][0]=='ecoinvent_db_name':
            upstream = get_activity(exc['input'])
            if upstream['production amount']<0:
                exc['amount']=-exc['amount']

This works well, but it would be great to include the “additional strategy” (lines 6 and forward) in actual applied strategies (line 3). However, for the code to work, the database must have been matched (line 4).

If anyone can figure out how to include this as an actual strategy, I’ll write it up.

aleksandra-kim commented 5 years ago

Original comment by Chris Mutel (Bitbucket: cmutel, GitHub: cmutel).


This looks pretty good right now! Just needs to be wrapped as a function:

from bw2io.utils import rescale_exchange

def flip_sign_on_waste_treatment_simapro_compatibility(data, other):
    """Describe function here"""
    flip_needed = {ds.key for ds in Database(other)
                   if ds.get('production amount', 0) < 0}

    for ds in data:
        for exc in ds.get('exchanges', []):
            if exc['input'] in flip_needed:
                rescale_exchange(exc, -1)

Apply like:

from functools import partial

importer.apply_strategy(functools.partial(
    flip_sign_on_waste_treatment_simapro_compatibility,
    other="some database name")
)

But if you make a PR (and I hope you do!), please make sure to include tests with real-world examples.

aleksandra-kim commented 5 years ago

Original comment by Pascal Lesage (Bitbucket: MPa, ).


Can do, and I would have made the PR from the get-go except I can’t figure out when this function gets called. It can’t be part of the list of strategies that get applied because “other” is not defined.

PascalLesage commented 4 years ago

@cmutel I'm doing this today. If you can figure out the best approach to applying a strategy after matching, let me know. Else, I'll just leave it to the user to know they should call this themselves after matching.

cmutel commented 3 years ago

Fixed in https://github.com/brightway-lca/brightway2-io/commit/235f92242558db4976e3131af9338961ccde27f6.