Source code for bw2io.strategies.lcia

# -*- coding: utf-8 -*-
from bw2data import Database
from ..utils import activity_hash
import collections
import copy


[docs] def add_activity_hash_code(data): """Add ``code`` field to characterization factors using ``activity_hash``, if ``code`` not already present.""" for method in data: for cf in method["exchanges"]: if cf.get("code"): continue cf[u"code"] = activity_hash(cf) return data
[docs] def drop_unlinked_cfs(data): """Drop CFs which don't have ``input`` attribute""" for method in data: method[u"exchanges"] = [ cf for cf in method["exchanges"] if cf.get("input") is not None ] return data
[docs] def set_biosphere_type(data): """Set CF types to 'biosphere', to keep compatibility with LCI strategies. This will overwrite existing ``type`` values.""" for method in data: for cf in method["exchanges"]: cf[u"type"] = u"biosphere" return data
[docs] def rationalize_method_names(data): counts = collections.Counter() for obj in data: if isinstance(obj["name"], tuple): counts[obj["name"][:2]] += 1 for obj in data: if not isinstance(obj["name"], tuple): continue if " w/o LT" in obj["name"][0]: obj["name"] = tuple([o.replace(" w/o LT", "") for o in obj["name"]]) + ( "without long-term", ) if " no LT" in obj["name"][0]: obj["name"] = tuple([o.replace(" no LT", "") for o in obj["name"]]) + ( "without long-term", ) elif {o.lower() for o in obj["name"][1:]} == {"total"}: obj["name"] = obj["name"][:2] elif len(obj["name"]) > 2 and obj["name"][1].lower() == "total": obj["name"] = (obj["name"][0],) + obj["name"][2:] elif obj["name"][-1].lower() == "total" and counts[obj["name"][:2]] == 1: obj["name"] = obj["name"][:2] return data
[docs] def match_subcategories(data, biosphere_db_name, remove=True): """Given a characterization with a top-level category, e.g. ``('air',)``, find all biosphere flows with the same top-level categories, and add CFs for these flows as well. Doesn't replace CFs for existing flows with multi-level categories. If ``remove``, also delete the top-level CF, but only if it is unlinked.""" def add_amount(obj, amount): obj["amount"] = amount return obj def add_subcategories(obj, mapping): # Sorting needed for tests new_objs = sorted( mapping[(obj["categories"][0], obj["name"], obj["unit"],)], key=lambda x: tuple([x[key] for key in sorted(x.keys())]), ) # Need to create copies so data from later methods doesn't # clobber amount values return [add_amount(copy.deepcopy(elem), obj["amount"]) for elem in new_objs] mapping = collections.defaultdict(list) for flow in Database(biosphere_db_name): # Try to filter our industrial activities and their flows if not flow.get("type") in ("emission", "natural resource"): continue if len(flow.get("categories", [])) > 1: mapping[(flow["categories"][0], flow["name"], flow["unit"])].append( { "categories": flow["categories"], "database": flow["database"], "input": flow.key, "name": flow["name"], "unit": flow["unit"], } ) for method in data: already_have = {(obj["name"], obj["categories"]) for obj in method["exchanges"]} new_cfs = [] for obj in method["exchanges"]: if len(obj["categories"]) > 1: continue # Don't add subcategory flows which already have CFs subcat_cfs = [ x for x in add_subcategories(obj, mapping) if (x["name"], x["categories"]) not in already_have ] if subcat_cfs and remove and not obj.get("input"): obj["remove_me"] = True new_cfs.extend(subcat_cfs) method[u"exchanges"].extend(new_cfs) if remove: method[u"exchanges"] = [ obj for obj in method["exchanges"] if not obj.get("remove_me") ] return data
[docs] def fix_ecoinvent_38_lcia_implementation(data): """Ecoinvent 3.8 LCIA implmentation uses some flow names from 3.7. Update these when possible, delete when not.""" MAPPING = { ('Cyfluthrin', ('soil', 'agricultural')): "Beta-cyfluthrin", # Note: Not the same thing!!! ('Cyfluthrin', ('air', 'non-urban air or from high stacks')): "Beta-cyfluthrin", # Note: Not the same thing!!! ('Carfentrazone ethyl ester', ('soil', 'agricultural')): "[Deleted]Carfentrazone ethyl ester", # Note: Seriously, WTF!? ('Tri-allate', ('soil', 'agricultural')): "Triallate", # But now there is ALSO a flow called "[Deleted]Tri-allate" into agricultural soil! ('Thiophanat-methyl', ('soil', 'agricultural')): "Thiophanate-methyl" # Why not? Keep them on their toes! But please make sure to change it back in 3.9. } REMOVE = { ('Flurochloridone', ('soil', 'agricultural')), ('Chlorotoluron', ('soil', 'agricultural')), } for method in data: method['exchanges'] = [cf for cf in method['exchanges'] if (cf['name'], cf['categories']) not in REMOVE] for cf in method['exchanges']: try: cf['name'] = MAPPING[(cf['name'], cf['categories'])] except KeyError: pass return data