def lci_matrices_to_excel(database_name, include_descendants=True): """Fake docstring""" from bw2calc import LCA print("Starting Excel export. This can be slow for large matrices!") safe_name = safe_filename(database_name, False) filepath = os.path.join(projects.output_dir, safe_name + ".xlsx") lca = LCA({Database(database_name).random(): 1}) lca.load_lci_data() lca.fix_dictionaries() if not include_descendants: lca.activity_dict = { key: value for key, value in lca.activity_dict.items() if key[0] == database_name } # Drop biosphere flows with zero references # TODO: This will ignore (-1 + 1 = 0) references lca.biosphere_dict = { key: value for key, value in lca.biosphere_dict.items() if lca.biosphere_matrix[lca.biosphere_dict[key], :].sum() != 0 } workbook = xlsxwriter.Workbook(filepath) bold = workbook.add_format({"bold": True}) print("Sorting objects") sorted_activity_keys = sorted([(Database.get(key).get("name") or u"Unknown", key) for key in lca.activity_dict]) sorted_product_keys = sorted([(Database.get(key).get("name") or u"Unknown", key) for key in lca.product_dict]) sorted_bio_keys = sorted([(Database.get(key).get("name") or u"Unknown", key) for key in lca.biosphere_dict]) tm_sheet = workbook.add_worksheet("technosphere") tm_sheet.set_column("A:A", 50) data = Database(database_name).load() # Labels for index, data in enumerate(sorted_activity_keys): tm_sheet.write_string(0, index + 1, data[0]) for index, data in enumerate(sorted_product_keys): tm_sheet.write_string(index + 1, 0, data[0]) print("Entering technosphere matrix data") coo = lca.technosphere_matrix.tocoo() # Translate row index to sorted product index act_dict = {obj[1]: idx for idx, obj in enumerate(sorted_activity_keys)} pro_dict = {obj[1]: idx for idx, obj in enumerate(sorted_product_keys)} bio_dict = {obj[1]: idx for idx, obj in enumerate(sorted_bio_keys)} pro_lookup = {v: pro_dict[k] for k, v in lca.product_dict.items()} bio_lookup = {v: bio_dict[k] for k, v in lca.biosphere_dict.items()} act_lookup = {v: act_dict[k] for k, v in lca.activity_dict.items()} # Matrix values for row, col, value in zip(coo.row, coo.col, coo.data): tm_sheet.write_number(pro_lookup[row] + 1, act_lookup[col] + 1, value) bm_sheet = workbook.add_worksheet("biosphere") bm_sheet.set_column("A:A", 50) data = Database(database_name).load() # Labels for index, data in enumerate(sorted_activity_keys): bm_sheet.write_string(0, index + 1, data[0]) for index, data in enumerate(sorted_bio_keys): bm_sheet.write_string(index + 1, 0, data[0]) print("Entering biosphere matrix data") coo = lca.biosphere_matrix.tocoo() # Matrix values for row, col, value in zip(coo.row, coo.col, coo.data): bm_sheet.write_number(bio_lookup[row] + 1, act_lookup[col] + 1, value) COLUMNS = ( u"Index", u"Name", u"Reference product", u"Unit", u"Categories", u"Location", ) tech_sheet = workbook.add_worksheet("technosphere-labels") tech_sheet.set_column("B:B", 60) tech_sheet.set_column("C:C", 30) tech_sheet.set_column("D:D", 15) tech_sheet.set_column("E:E", 30) print("Writing metadata") # Header for index, col in enumerate(COLUMNS): tech_sheet.write_string(0, index, col, bold) tech_sheet.write_comment( "C1", "Only for ecoinvent 3, where names =/= products.", ) for index, data in enumerate(sorted_activity_keys): obj = Database.get(data[1]) tech_sheet.write_number(index + 1, 0, index + 1) tech_sheet.write_string(index + 1, 1, obj.get(u"name") or u"Unknown") tech_sheet.write_string(index + 1, 2, obj.get(u"reference product") or u"") tech_sheet.write_string(index + 1, 3, obj.get(u"unit") or u"Unknown") tech_sheet.write_string(index + 1, 4, u" - ".join(obj.get(u"categories") or [])) tech_sheet.write_string(index + 1, 5, obj.get(u"location") or u"Unknown") COLUMNS = ( u"Index", u"Name", u"Unit", u"Categories", ) bio_sheet = workbook.add_worksheet("biosphere-labels") bio_sheet.set_column("B:B", 60) bio_sheet.set_column("C:C", 15) bio_sheet.set_column("D:D", 30) # Header for index, col in enumerate(COLUMNS): bio_sheet.write_string(0, index, col, bold) for index, data in enumerate(sorted_bio_keys): obj = Database.get(data[1]) bio_sheet.write_number(index + 1, 0, index + 1) bio_sheet.write_string(index + 1, 1, obj.get(u"name") or u"Unknown") bio_sheet.write_string(index + 1, 2, obj.get(u"unit") or u"Unknown") bio_sheet.write_string(index + 1, 3, u" - ".join(obj.get(u"categories") or [])) workbook.close() return filepath
def write_database( self, data=None, delete_existing=True, backend=None, activate_parameters=False, **kwargs ): """ Write data to a ``Database``. All arguments are optional, and are normally not specified. ``delete_existing`` effects both the existing database (it will be emptied prior to writing if True, which is the default), and, if ``activate_parameters`` is True, existing database and activity parameters. Database parameters will only be deleted if the import data specifies a new set of database parameters (i.e. ``database_parameters`` is not ``None``) - the same is true for activity parameters. If you need finer-grained control, please use the ``DatabaseParameter``, etc. objects directly. Args: * *data* (dict, optional): The data to write to the ``Database``. Default is ``self.data``. * *delete_existing* (bool, default ``True``): See above. * *activate_parameters* (bool, default ``False``). Instead of storing parameters in ``Activity`` and other proxy objects, create ``ActivityParameter`` and other parameter objects, and evaluate all variables and formulas. * *backend* (string, optional): Storage backend to use when creating ``Database``. Default is the default backend. Returns: ``Database`` instance. """ data = self.data if data is None else data self.metadata.update(kwargs) if activate_parameters: # Comes before .write_database because we # need to remove `parameters` key activity_parameters = self._prepare_activity_parameters( data, delete_existing ) if {o["database"] for o in data} != {self.db_name}: error = "Activity database must be {}, but {} was also found".format( self.db_name, {o["database"] for o in data}.difference({self.db_name}) ) raise WrongDatabase(error) if len({o["code"] for o in data}) < len(data): seen, duplicates = set(), [] for o in data: if o["code"] in seen: duplicates.append(o["name"]) else: seen.add(o["code"]) error = "The following activities have non-unique codes: {}" raise NonuniqueCode(error.format(duplicates)) data = {(ds["database"], ds["code"]): ds for ds in data} if self.db_name in databases: # TODO: Raise error if unlinked exchanges? db = Database(self.db_name) if delete_existing: existing = {} else: existing = db.load(as_dict=True) else: existing = {} if "format" not in self.metadata: self.metadata["format"] = self.format with warnings.catch_warnings(): warnings.simplefilter("ignore") db = Database(self.db_name, backend=backend) db.register(**self.metadata) self.write_database_parameters(activate_parameters, delete_existing) existing.update(data) db.write(existing) if activate_parameters: self._write_activity_parameters(activity_parameters) print(u"Created database: {}".format(self.db_name)) return db
def test_bw2_database(): d = Database("biosphere") d.write(biosphere) d = Database("food") d.write(food)
def get_database_filepath(functional_unit): """Get filepaths for all databases in supply chain of `functional_unit`""" dbs = set.union(*[ Database(key[0]).find_graph_dependents() for key in functional_unit ]) return [Database(obj).filepath_processed() for obj in dbs]
def test_traverse_tagged_databases_graph_nonunitary_production(): Database("biosphere").write( { ("biosphere", "bad"): {"name": "bad", "type": "emission"}, ("biosphere", "worse"): {"name": "worse", "type": "emission"}, } ) method = Method(("test method",)) method.register() method.write( [(("biosphere", "bad"), 2), (("biosphere", "worse"), 3),] ) Database("background").write( { ("background", "first"): { "exchanges": [ {"input": ("biosphere", "bad"), "amount": 1, "type": "biosphere"}, { "input": ("background", "first"), "amount": 5, "type": "production", }, ], }, ("background", "second"): { "exchanges": [ {"input": ("biosphere", "worse"), "amount": 1, "type": "biosphere"} ], }, } ) Database("foreground").write( { ("foreground", "fu"): { "name": "functional unit", "tag field": "functional unit", "exchanges": [ { "input": ("foreground", "i"), "amount": 1, "type": "technosphere", }, { "input": ("foreground", "iv"), "amount": 4, "type": "technosphere", }, {"input": ("foreground", "fu"), "amount": 2, "type": "production",}, ], }, ("foreground", "i"): { "tag field": "A", "exchanges": [ { "input": ("foreground", "ii"), "amount": 2, "type": "technosphere", }, { "input": ("foreground", "iii"), "amount": 3, "type": "technosphere", }, { "input": ("biosphere", "bad"), "amount": 5, "tag field": "C", "type": "biosphere", }, { "input": ("biosphere", "worse"), "amount": 6, "type": "biosphere", }, ], }, ("foreground", "ii"): { "tag field": "C", "exchanges": [ {"input": ("biosphere", "bad"), "amount": 8, "type": "biosphere",}, { "input": ("biosphere", "worse"), "amount": 7, "tag field": "D", "type": "biosphere", }, {"input": ("foreground", "ii"), "amount": 3, "type": "production",}, ], }, ("foreground", "iii"): { # Default tag: "B" "exchanges": [ { "input": ("background", "first"), "amount": 10, "type": "technosphere", }, { "input": ("biosphere", "bad"), "tag field": "A", "amount": 9, "type": "biosphere", }, ], }, ("foreground", "iv"): { "tag field": "C", "exchanges": [ { "input": ("background", "second"), "amount": 12, "type": "technosphere", }, { "input": ("biosphere", "worse"), "tag field": "B", "amount": 11, "type": "biosphere", }, { "input": ("foreground", "iv"), "amount": 10, "type": "production", }, ], }, } ) _, graph = traverse_tagged_databases( {("foreground", "fu"): 2}, ("test method",), label="tag field", default_tag="B" ) expected = [ { "amount": 2, "biosphere": [], "activity": get_activity(("foreground", "fu")), "technosphere": [ { "amount": 1, "biosphere": [ {"amount": 5, "impact": 10, "tag": "C", "secondary_tags": []}, {"amount": 6, "impact": 18, "tag": "A", "secondary_tags": []}, ], "activity": get_activity(("foreground", "i")), "technosphere": [ { "amount": 2, "biosphere": [ { "amount": 16 / 3, "impact": 32 / 3, "tag": "C", "secondary_tags": [], }, { "amount": 14 / 3, "impact": 42 / 3, "tag": "D", "secondary_tags": [], }, ], "activity": get_activity(("foreground", "ii")), "technosphere": [], "impact": 0, "tag": "C", "secondary_tags": [], }, { "amount": 3, "biosphere": [ { "amount": 27, "impact": 54, "tag": "A", "secondary_tags": [], } ], "activity": get_activity(("foreground", "iii")), "technosphere": [], "impact": 60 / 5, "tag": "B", "secondary_tags": [], }, ], "impact": 0, "tag": "A", "secondary_tags": [], }, { "amount": 4, "biosphere": [ { "amount": pytest.approx(44 / 10), "impact": pytest.approx(132 / 10), "tag": "B", "secondary_tags": [], } ], "activity": get_activity(("foreground", "iv")), "technosphere": [], "impact": pytest.approx(144 / 10), "tag": "C", "secondary_tags": [], }, ], "impact": 0, "tag": "functional unit", "secondary_tags": [], } ] assert graph == expected
def basic(): assert not len(Database('animals')) animal_data = { ('animals', 'food'): { 'name': 'food', 'exchanges': [{ 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'production' }], 'unit': 'kilogram', 'location': 'GLO', 'reference product': 'food', }, ('animals', 'german_shepherd'): { 'name': 'dogs', 'reference product': 'dog', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'german_shepherd'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'DE', }, ('animals', 'pug'): { 'name': 'dogs', 'reference product': 'dog', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'pug'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'CN', }, ('animals', 'mutt'): { 'name': 'dogs', 'reference product': 'dog', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'mutt'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'RoW', }, ('animals', 'german_shepherd pup'): { 'name': 'dogs', 'reference product': 'puppy', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'german_shepherd pup'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'DE', }, ('animals', 'pug pup'): { 'name': 'dogs', 'reference product': 'puppy', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'pug pup'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'CN', }, ('animals', 'mutt pup'): { 'name': 'dogs', 'reference product': 'puppy', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'mutt pup'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'RoW', }, ('animals', 'persian'): { 'name': 'cats', 'reference product': 'cat', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'persian'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'IR', }, ('animals', 'moggy'): { 'name': 'cats', 'reference product': 'cat', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'moggy'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'RoW', }, ('animals', 'hamster'): { 'name': 'hamster', 'reference product': 'hamster', 'exchanges': [ { 'amount': 1.0, 'input': ('animals', 'food'), 'type': 'technosphere' }, { 'amount': 1.0, 'input': ('animals', 'hamster'), 'type': 'production' }, ], 'unit': 'kilogram', 'location': 'GLO', }, } db = Database('animals') db.write(animal_data) return db
def load_and_clean_exiobase_3_ecoinvent_36_migration( ecoinvent_biosphere_name=None, explode=False): # load migration data migration = get_migration("exiobase-3-ecoinvent-3.6") # convert migration data into dataframe df = pd.DataFrame([{ "exiobase name": k[0], "exiobase compartment": k[1], "value": v } if isinstance(v, list) else { "exiobase name": k[0], "exiobase compartment": k[1], "value": [v] } for k, v in migration["data"]]) # convert lists into individual rows df = df.explode("value").reset_index(drop=True) # convert dicts into individual columns df = df.join(df["value"].apply(pd.Series)).drop(columns=["value"]) # rename columns df = df.rename( columns={ "unit": "ecoinvent unit", "name": "ecoinvent name", "categories": "ecoinvent categories", "__multiplier__": "multiplier", "__disaggregation__": "disaggregation", }) # fill in missing data df = df.fillna({ "exiobase compartment": "undef", "ecoinvent name": df["exiobase name"], "disaggregation": 1, "ecoinvent categories": df["exiobase compartment"], }) # convert ecoinvent categories into tuples df.loc[:, "ecoinvent categories"] = df["ecoinvent categories"].apply( lambda x: tuple(x) if isinstance(x, list) else (x, )) # combine multiplier and disaggregation into one 'factor' column df["factor"] = df["multiplier"] * df["disaggregation"] # merge with ecoinvent biosphere to extract global flow indices if ecoinvent_biosphere_name is not None: df["biosphere index"] = df.merge( pd.DataFrame(Database(ecoinvent_biosphere_name) ), # get ecoinvent biosphere as dataframe how="left", # keep left index left_on=[ "ecoinvent name", "ecoinvent categories", "ecoinvent unit", ], # columns to merge on right_on=["name", "categories", "unit"], # columns to merge on )["id"] # undo exploding for unique index if explode is False: df = df.groupby(["exiobase name", "exiobase compartment"], dropna=False).agg(list) return df
def test_database_write_adds_to_geomapping(add_biosphere): d = Database("food") d.write(food, process=False) assert "CA" in geomapping assert "CH" in geomapping
def import_data(self): biosphere_data = { ('biosphere', 'F'): { 'type': 'emission', 'exchanges': [], }, ('biosphere', 'G'): { 'type': 'emission', 'exchanges': [], } } biosphere = Database("biosphere") biosphere.register(depends=[], geocollections=[]) biosphere.write(biosphere_data) inventory_data = { ('inventory', 'U'): { 'type': 'process', 'location': "L", 'exchanges': [ { 'input': ('biosphere', 'F'), 'type': 'biosphere', 'amount': 1 }, { 'input': ('biosphere', 'G'), 'type': 'biosphere', 'amount': 1 }, ] }, ('inventory', 'V'): { 'type': 'process', 'location': "M", 'exchanges': [] }, ('inventory', 'X'): { 'type': 'process', 'location': "N", 'exchanges': [] }, ('inventory', 'Y'): { 'type': 'process', 'location': "O", 'exchanges': [] }, ('inventory', 'Z'): { 'type': 'process', 'location': "O", 'exchanges': [] } } inventory = Database("inventory") inventory.register(depends=["biosphere"], geocollections=["places"]) inventory.write(inventory_data) intersection_data = [ ["L", "A", 1], ["M", "A", 2], ["M", "B", 3], ["N", "B", 5], ["N", "C", 8], ["O", "C", 13], ] inter = Intersection(("places", "regions")) inter.register() inter.write(intersection_data) loading_data = [ [2, "A"], [4, "B"], [8, "C"], ] loading = Loading("loading") loading.register() loading.write(loading_data) method_data = [ [('biosphere', 'F'), 1, "A"], [('biosphere', 'G'), 2, "A"], [('biosphere', 'F'), 3, "B"], [('biosphere', 'G'), 4, "B"], [('biosphere', 'F'), 5, "C"], [('biosphere', 'G'), 6, "C"], ] method = Method(("a", "method")) method.register(geocollections=['regions']) method.write(method_data)
def __init__(self, data, ref_database_name, from_simapro=False): self.data = data self.assert_data_fully_linked() self.fields = ("name", "location", "unit") if from_simapro else None assert ref_database_name in databases, u"Invalid reference database name" self.ref_database = Database(ref_database_name)
def add_biosphere(): Database("biosphere").write(biosphere)
def write_database(): bio_data = { ("bio", "a"): { "exchange": [], "type": "biosphere" }, ("bio", "b"): { "exchange": [], "type": "biosphere" }, } Database("bio").write(bio_data) tech_data = { ("test", "1"): { "exchanges": [ { "amount": 1, "type": "production", "input": ("test", "1"), "uncertainty type": 0, }, { "amount": 0.1, "type": "technosphere", "input": ("test", "3"), "uncertainty type": 0, }, { "amount": 7, "type": "biosphere", "input": ("bio", "b"), "uncertainty type": 0, }, ], }, ("test", "2"): { "exchanges": [ { "amount": 0.5, "type": "production", "input": ("test", "2"), "uncertainty type": 0, }, { "amount": -2, "type": "technosphere", "input": ("test", "1"), "uncertainty type": 0, }, { "amount": 1, "type": "biosphere", "input": ("bio", "a"), "uncertainty type": 0, }, { "amount": 5, "type": "biosphere", "input": ("bio", "b"), "uncertainty type": 0, }, ], }, ("test", "3"): { "exchanges": [ { "amount": 1, "type": "production", "input": ("test", "3"), "uncertainty type": 0, }, { "amount": 3, "type": "technosphere", "input": ("test", "1"), "uncertainty type": 0, }, { "amount": 2, "type": "technosphere", "input": ("test", "2"), "uncertainty type": 0, }, { "amount": 2, "type": "biosphere", "input": ("bio", "a"), "uncertainty type": 0, }, ], }, } Database("test").write(tech_data) cfs = [ (("bio", "a"), 4), (("bio", "b"), -2), ] Method(("m", )).register() Method(("m", )).write(cfs)
def get_lca(self): db = Database("a") db.write(lci_fixture) lca = LCA({("a", "2"): 1}) lca.lci() return lca
def contribution_for_all_datasets_one_method(database, method, progress=True): """Calculate contribution analysis (for technosphere processes) for all inventory datasets in one database for one LCIA method. Args: *database* (str): Name of database *method* (tuple): Method tuple Returns: NumPy array of relative contributions. Each column sums to one. Lookup dictionary, dataset keys to row/column indices Total elapsed time in seconds """ def get_normalized_scores(lca, kind): if kind == "activities": data = lca.characterized_inventory.sum(axis=0) elif kind == "flows": data = lca.characterized_inventory.sum(axis=1) elif kind == "all": data = lca.characterized_inventory.data scores = np.abs(np.array(data).ravel()) summed = scores.sum() if summed == 0: return np.zeros(scores.shape) else: return scores / summed start = time() assert database in databases, "Can't find database %s" % database assert method in methods, "Can't find method %s" % method keys = Database(database).load().keys() assert keys, "Database %s appears to have no datasets" % database # Array to store results results = np.zeros((len(keys), len(keys)), dtype=np.float32) # Instantiate LCA object lca = bc.LCA({keys[0]: 1}, method=method) lca.lci() lca.decompose_technosphere() lca.lcia() rows = lca.characterized_inventory.shape[0] cols = lca.characterized_inventory.shape[1] all_cutoff = cols * 4 results = { "activities": np.zeros((cols, cols), dtype=np.float32), "flows": np.zeros((rows, cols), dtype=np.float32), "all": np.zeros((all_cutoff, cols), dtype=np.float32), } pbar = pyprind.ProgBar(len(keys), title="Activities:") # Actual calculations for key in keys: lca.redo_lcia({key: 1}) if lca.score == 0.0: continue col = lca.activity_dict[mapping[key]] results["activities"][:, col] = get_normalized_scores(lca, "activities") results["flows"][:, col] = get_normalized_scores(lca, "flows") results_all = get_normalized_scores(lca, "all") results_all.sort() results_all = results_all[::-1] fill_number = results_all.shape[0] assert fill_number < all_cutoff, "Too many values in 'all'" results["all"][:fill_number, col] = results_all pbar.update() print(pbar) return results, lca.activity_dict, time() - start
#~from ..dynamic_ia_methods import DynamicIAMethod, dynamic_methods #~from ..utils import get_function_name # from bw2data import Database, Method, databases, methods # from bw2calc import LCA from bw2data import Database, config #,projects from bw2data.tests import BW2DataTest as BaseTestCase from ..dyn_methods.timedependent_lca import time_dependent_LCA from ..dyn_methods.method_creation import create_climate_methods from bw2io import bw2setup import numpy as np #~import warnings db_bio = Database(config.biosphere) class ClimateMetricsTestCase(BaseTestCase): def create_db(self): bw2setup() create_climate_methods() data = { ("clima", "co2"): { 'name': "co2", 'exchanges': [ { 'amount': 1, 'input':
def initial_biosphere(): config.p["biosphere_database"] = "biosphere" Database("biosphere").write(biosphere_data)
def create_db(self): bw2setup() create_climate_methods() data = { ("clima", "co2"): { 'name': "co2", 'exchanges': [ { 'amount': 1, 'input': (db_bio.name, '349b29d1-3e58-4c66-98b9-9d1a076efd2e' ), #fossil fuel carbon dioxide thus normal CF 'type': 'biosphere' }, ], 'type': 'process', }, ('clima', 'ch4'): { 'name': "ch4", 'exchanges': [ { 'amount': 1, 'input': (db_bio.name, 'da1157e2-7593-4dfd-80dd-a3449b37a4d8' ), #Methane non fossil thus normal CF 'type': 'biosphere' }, ], 'type': 'process', }, ('clima', 'ch4_fossil'): { 'name': "ch4_fossil", 'exchanges': [ { 'amount': 1, 'input': (db_bio.name, '0795345f-c7ae-410c-ad25-1845784c75f5' ), #Methane fossil thus consider conversion to co2 'type': 'biosphere' }, ], 'type': 'process', }, ('clima', 'co2bio_test'): { 'name': "co2bio_test", 'exchanges': [ { 'amount': 1, 'input': (db_bio.name, 'cc6a1abb-b123-4ca6-8f16-38209df609be' ), #biogenic carbon dioxide 'type': 'biosphere' }, ], 'type': 'process', } } db = Database('clima') db.write(data)
def import_data(self): biosphere_data = { ('biosphere', 'F'): { 'type': 'emission', 'exchanges': [], }, ('biosphere', 'G'): { 'type': 'emission', 'exchanges': [], } } biosphere = Database("biosphere") biosphere.register(depends=[], geocollections=[]) biosphere.write(biosphere_data) inventory_data = { ('inventory', 'U'): { 'type': 'process', 'location': "L", 'exchanges': [ { 'input': ('biosphere', 'F'), 'type': 'biosphere', 'amount': 1 }, { 'input': ('biosphere', 'G'), 'type': 'biosphere', 'amount': 1 }, ] }, ('inventory', 'V'): { 'type': 'process', 'location': "M", 'exchanges': [] }, ('inventory', 'X'): { 'type': 'process', 'location': "N", 'exchanges': [] }, ('inventory', 'Y'): { 'type': 'process', 'location': "O", 'exchanges': [] }, ('inventory', 'Z'): { 'type': 'process', 'location': "O", 'exchanges': [] } } inventory = Database("inventory") inventory.register(depends=["biosphere"], geocollections=["places"]) inventory.write(inventory_data) method_data = [ [('biosphere', 'F'), 1, "L"], [('biosphere', 'G'), 2, "L"], ] method = Method(("a", "method")) method.register(geocollections=['places']) method.write(method_data)
def import_exiopol_IO_table(database_name, dir_path): assert os.path.exists(dir_path) and os.path.isdir( dir_path), "Problem with given directory path" assert database_name not in databases, "Database {} already exists".format( database_name) assert "mrIot_version2.2.2.txt" in os.listdir( dir_path), "Directory path must contain `mrIot_version2.2.2.txt` file." print("Loading and processing data") fp = os.path.join(dir_path, 'mrIot_version2.2.2.txt') data = [line for line in csv.reader(open(fp, "r"), delimiter="\t")] labels = [tuple(x[:3]) for x in data[2:]] labels_dict = {i: obj for i, obj in enumerate(labels)} data = np.array([[float(x) for x in row[3:]] for row in data[2:]]) codify = lambda x: ":".join(x[:2]) def get_column_tech_exchanges(index, obj): excs = [] for row_i, value in enumerate(data[:, index]): if not value: continue elif row_i == index: excs.append({ 'type': 'production', 'uncertainty_type': UndefinedUncertainty.id, 'amount': float(1 - value), 'loc': float(1 - value), 'input': (database_name, obj), 'output': (database_name, obj) }) else: excs.append({ 'type': 'technosphere', 'uncertainty_type': UndefinedUncertainty.id, 'amount': float(value), 'loc': float(value), 'input': (database_name, codify(labels_dict[row_i])), 'output': (database_name, obj) }) return excs print("Creating LCA datasets") db = [] pbar = pyprind.ProgBar(len(labels)) for index, ds in enumerate(labels): db.append({ 'location': ds[0], 'name': ds[1], 'unit': ds[2], 'exchanges': get_column_tech_exchanges(index, codify(ds)), 'type': 'process', 'database': database_name, 'code': codify(ds) }) pbar.update() print("Writing datasets") db_obj = Database(database_name) db_obj.register(directory=dir_path) # db_obj.write({(ds['database'], ds['code']): ds for ds in db}) return db_obj
def test_value_error_no_method(self): empty = Database("empty") empty.register(depends=[]) with self.assertRaises(ValueError): LCA({("empty", "nothing"): 1})
def test_match_subcategories(self): self.maxDiff = None background = [ { "categories": ("air", "non-urban air or from high stacks"), "code": "first", "database": "b", "exchanges": [], "name": "Boron trifluoride", "type": "emission", "unit": "kilogram", }, { "categories": ("air", "low population density, long-term"), "code": "second", "database": "b", "exchanges": [], "name": "Boron trifluoride", "type": "emission", "unit": "kilogram", }, { "categories": ("air", "lower stratosphere + upper troposphere"), "code": "third", "database": "b", "exchanges": [], "name": "Boron trifluoride", "type": "emission", "unit": "kilogram", }, { # Skip - root category "categories": ("air",), "code": "fourth", "database": "b", "exchanges": [], "name": "Boron trifluoride", "type": "emission", "unit": "kilogram", }, { # Should be skipped - wrong type "categories": ("air", "skip me"), "code": "Bill. My friends just call me Bill.", "database": "b", "exchanges": [], "name": "Boron trifluoride", "type": "something else", "unit": "kilogram", }, ] db = Database("b") db.register() db.write({(obj["database"], obj["code"]): obj for obj in background}) data = [ { "name": "Some LCIA method", "exchanges": [ { "name": "Boron trifluoride", "categories": ("air",), "unit": "kilogram", # Only for CFs - no need for biosphere filter # 'type': 'biosphere', "amount": 1, }, { "name": "Boron trifluoride", "categories": ("air", "lower stratosphere + upper troposphere"), "unit": "kilogram", "amount": 0, }, ], } ] expected = [ { "name": "Some LCIA method", "exchanges": [ { "name": "Boron trifluoride", "categories": ("air",), "unit": "kilogram", "amount": 1, }, { # Not linked - already has subcategories "categories": ("air", "lower stratosphere + upper troposphere"), "name": "Boron trifluoride", "unit": "kilogram", "amount": 0, }, { "categories": ("air", "low population density, long-term"), "database": "b", "name": "Boron trifluoride", "unit": "kilogram", "input": ("b", "second"), "amount": 1, }, { "amount": 1, "categories": ("air", "non-urban air or from high stacks"), "database": "b", "input": ("b", "first"), "name": "Boron trifluoride", "unit": "kilogram", }, ], } ] answer = match_subcategories(data, "b", remove=False) self.assertEqual(expected, answer)
def bw25_setup(): # Biosphere database - won't be extracted Database("b").write( { ("b", "1"): {"type": "emission", "exchanges": [],}, ("b", "2"): {"type": "emission", "exchanges": [],}, } ) # Background database - won't be extracted Database("a").write( { ("a", "1"): { "exchanges": [ {"input": ("a", "1"), "amount": 1, "type": "production"}, {"input": ("b", "1"), "amount": 1, "type": "biosphere"}, ], }, ("a", "2"): { "exchanges": [ {"input": ("a", "2"), "amount": 1, "type": "production"}, {"input": ("b", "2"), "amount": 2, "type": "biosphere"}, {"input": ("a", "1"), "amount": 1, "type": "technosphere"}, ], }, } ) # Foreground database - will be extracted Database("c").write( { ("c", "1"): { "name": "c1-1", "location": "c1-2", "unit": "c1-3", "exchanges": [ {"input": ("c", "1"), "amount": 1, "type": "production"}, {"input": ("a", "1"), "amount": 1, "type": "technosphere"}, {"input": ("a", "2"), "amount": 2, "type": "technosphere"}, {"input": ("b", "1"), "amount": 4, "type": "biosphere"}, ], }, ("c", "2"): { "name": "c2-1", "location": "c2-2", "unit": "c2-3", "exchanges": [ {"input": ("c", "2"), "amount": 1, "type": "production"}, {"input": ("a", "1"), "amount": 1, "type": "technosphere"}, {"input": ("a", "2"), "amount": 2, "type": "technosphere"}, {"input": ("c", "1"), "amount": 3, "type": "technosphere"}, {"input": ("b", "1"), "amount": 4, "type": "biosphere"}, ], }, } ) """ Base technosphere matrix: a1 a2 c1 c2 a1 [[ 1. -1. -1. -1.] a2 [ 0. 1. -2. -2.] c1 [ 0. 0. 1. -3.] c2 [ 0. 0. 0. 1.]] Base biosphere matrix: a1 a2 c1 c2 b1 [[1. 0. 4. 4.] b2 [0. 2. 0. 0.]] Total impact for c2 is 1*4 + (3*4) + (2 + 3*2) * 2 + (1 + 3*1 + 2*1 + 3*2*1) * 1 = 44 """ Method(("d",)).write([(("b", "1"), 1), (("b", "2"), 1)])
def tagged_fixture(): Database("biosphere").write( { ("biosphere", "bad"): {"name": "bad", "type": "emission"}, ("biosphere", "worse"): {"name": "worse", "type": "emission"}, } ) method = Method(("test method",)) method.register() method.write( [(("biosphere", "bad"), 2), (("biosphere", "worse"), 3),] ) Database("background").write( { ("background", "first"): { "exchanges": [ {"input": ("biosphere", "bad"), "amount": 1, "type": "biosphere",} ], }, ("background", "second"): { "exchanges": [ {"input": ("biosphere", "worse"), "amount": 1, "type": "biosphere",} ], }, } ) Database("foreground").write( { ("foreground", "fu"): { "name": "functional unit", "tag field": "functional unit", "secondary tag": "X", "exchanges": [ { "input": ("foreground", "i"), "amount": 1, "type": "technosphere", }, { "input": ("foreground", "iv"), "amount": 4, "type": "technosphere", }, ], }, ("foreground", "i"): { "tag field": "A", "secondary tag": "X", "exchanges": [ { "input": ("foreground", "ii"), "amount": 2, "type": "technosphere", }, { "input": ("foreground", "iii"), "amount": 3, "type": "technosphere", }, { "input": ("biosphere", "bad"), "amount": 5, "tag field": "C", "type": "biosphere", }, { "input": ("biosphere", "worse"), "amount": 6, "type": "biosphere", }, ], }, ("foreground", "ii"): { "tag field": "C", "secondary tag": "X", "exchanges": [ {"input": ("biosphere", "bad"), "amount": 8, "type": "biosphere",}, { "input": ("biosphere", "worse"), "amount": 7, "tag field": "D", "secondary tag": "Y", "type": "biosphere", }, ], }, ("foreground", "iii"): { # Default tag: "B" # Default secondary tag: "unknown" "exchanges": [ { "input": ("background", "first"), "amount": 10, "type": "technosphere", }, { "input": ("biosphere", "bad"), "tag field": "A", "secondary tag": "Y", "amount": 9, "type": "biosphere", }, ], }, ("foreground", "iv"): { "tag field": "C", "secondary tag": "Y", "exchanges": [ { "input": ("background", "second"), "amount": 12, "type": "technosphere", }, { "input": ("biosphere", "worse"), "tag field": "B", "secondary tag": "Y", "amount": 11, "type": "biosphere", }, ], }, } )
class DatabaseHealthCheck(object): def __init__(self, database): self.db = Database(database) self.db.filters = {"type": "process"} def check(self, graphs_dir=None): tg, tfn, bg, bfn = self.make_graphs(graphs_dir) aggregated = self.aggregated_processes() return { "tg": tg, "tfn": tfn, "bg": bg, "bfn": bfn, "pr": self.page_rank(), "ue": self.unique_exchanges(), "uncertainty": self.uncertainty_check(), "sp": aggregated["system_processes"], "me": aggregated["many_exchanges"], "nsp": self.no_self_production(), "mo": self.multioutput_processes(), "ob": self.ouroboros(), } def make_graphs(self, graphs_dir=None): lca = LCA({self.db.random(): 1}) lca.lci() tech_filename = safe_filename(self.db.name) + ".technosphere.png" tech_filepath = os.path.join(graphs_dir or projects.output_dir, tech_filename) SparseMatrixGrapher(lca.technosphere_matrix).graph(tech_filepath, dpi=600) bio_filename = safe_filename(self.db.name) + ".biosphere.png" bio_filepath = os.path.join(graphs_dir or projects.output_dir, bio_filename) SparseMatrixGrapher(lca.biosphere_matrix).graph(bio_filepath, dpi=600) return tech_filepath, tech_filename, bio_filepath, bio_filename def page_rank(self): return PageRank(self.db).calculate() def unique_exchanges(self): data = self.db.load() exchanges = [(exc["input"], exc["amount"], exc["type"]) for ds in data.values() for exc in ds.get("exchanges", []) if exc["type"] in {"biosphere", "technosphere"}] bio_exchanges = [obj for obj in exchanges if obj[2] == "biosphere"] tech_exchanges = [obj for obj in exchanges if obj[2] == "technosphere"] return ( len(tech_exchanges), len(set(tech_exchanges)), len(bio_exchanges), len(set(bio_exchanges)), ) def uncertainty_check(self): # TODO: Also report no (None) uncertainty data = self.db.load() results = { obj.id: { "total": 0, "bad": 0 } for obj in uncertainty_choices } for ds in data.values(): for exc in ds.get("exchanges", []): ut = exc.get("uncertainty type") if ut is None: continue results[ut]["total"] += 1 if ut == LognormalUncertainty.id: right_amount = np.allclose(np.log(np.abs(exc["amount"])), exc["loc"], rtol=1e-3) if not exc.get("scale") or not right_amount: results[ut]["bad"] += 1 elif ut == NormalUncertainty.id: if not exc.get("scale") or abs( exc["amount"]) != exc["loc"]: results[ut]["bad"] += 1 elif ut in {TriangularUncertainty.id, UniformUncertainty.id}: if exc["minimum"] >= exc["maximum"]: results[ut]["bad"] += 1 return results def multioutput_processes(self): num_production_exchanges = [( key, len([ exc for exc in ds.get("exchanges") if exc["type"] == "production" and exc["input"] != key ]), ) for key, ds in self.db.load().items()] return [obj for obj in num_production_exchanges if obj[1]] def aggregated_processes(self, cutoff=500): num_exchanges = { key: { "technosphere": len([ exc for exc in value.get("exchanges", []) if exc["type"] == "technosphere" ]), "biosphere": len([ exc for exc in value.get("exchanges", []) if exc["type"] == "biosphere" ]), } for key, value in self.db.load().items() if value.get("type", "process") == "process" } system_processes = [ (key, value["biosphere"]) for key, value in num_exchanges.items() if value["technosphere"] == 0 and value["biosphere"] > cutoff ] many_exchanges = [(key, value["technosphere"]) for key, value in num_exchanges.items() if value["technosphere"] > cutoff] return { "system_processes": system_processes, "many_exchanges": many_exchanges } def no_self_production(self): self_production = lambda a, b: not a or b in a return { key for key, value in self.db.load().items() if value.get("type", "process") == "process" and not self_production( { exc["input"] for exc in value.get("exchanges", []) if exc["type"] == "production" }, key, ) } def ouroboros(self): """Find processes that consume their own reference products as inputs. Not necessarily an error, but should be examined carefully (see `Two potential points of confusion in LCA math <http://chris.mutel.org/too-confusing.html>`__). Returns: A set of database keys. """ return { key for key, value in self.db.load().items() if any(exc for exc in value.get("exchanges", []) if exc["input"] == key and exc["type"] == "technosphere") }
def lci_matrices_to_matlab(database_name): from bw2calc import LCA lca = LCA({Database(database_name).random(): 1}) lca.lci() lca.fix_dictionaries() ra, rp, rb = lca.reverse_dict() safe_name = safe_filename(database_name, False) scipy.io.savemat( os.path.join(projects.output_dir, safe_name + ".mat"), { "technosphere": lca.technosphere_matrix, "biosphere": lca.biosphere_matrix }, ) workbook = xlsxwriter.Workbook(os.path.join(dirpath, safe_name + ".xlsx")) bold = workbook.add_format({"bold": True}) COLUMNS = ("Index", "Name", "Reference product", "Unit", "Categories", "Location") tech_sheet = workbook.add_worksheet("technosphere") tech_sheet.set_column("B:B", 60) tech_sheet.set_column("C:C", 30) tech_sheet.set_column("D:D", 15) tech_sheet.set_column("E:E", 30) # Header for index, col in enumerate(COLUMNS): tech_sheet.write_string(0, index, col, bold) tech_sheet.write_comment( "C1", "Only for ecoinvent 3, where names =/= products.", ) data = Database(database_name).load() for index, key in sorted(ra.items()): tech_sheet.write_number(index + 1, 0, index + 1) tech_sheet.write_string(index + 1, 1, data[key].get("name") or "Unknown") tech_sheet.write_string(index + 1, 2, data[key].get("reference product") or "") tech_sheet.write_string(index + 1, 3, data[key].get("unit") or "Unknown") tech_sheet.write_string(index + 1, 4, " - ".join(data[key].get("categories") or [])) tech_sheet.write_string(index + 1, 5, data[key].get("location") or "Unknown") COLUMNS = ( "Index", "Name", "Unit", "Categories", ) biosphere_dicts = {} bio_sheet = workbook.add_worksheet("biosphere") bio_sheet.set_column("B:B", 60) bio_sheet.set_column("C:C", 15) bio_sheet.set_column("D:D", 30) # Header for index, col in enumerate(COLUMNS): bio_sheet.write_string(0, index, col, bold) for index, key in sorted(rb.items()): if key[0] not in biosphere_dicts: biosphere_dicts[key[0]] = Database(key[0]).load() obj = biosphere_dicts[key[0]][key] bio_sheet.write_number(index + 1, 0, index + 1) bio_sheet.write_string(index + 1, 1, obj.get("name", "Unknown")) bio_sheet.write_string(index + 1, 2, obj.get("unit", "Unknown")) bio_sheet.write_string(index + 1, 3, " - ".join(obj.get("categories", []))) workbook.close() return dirpath
def __init__(self, database): self.db = Database(database) self.db.filters = {"type": "process"}
def test_unprocessed_database_error(self): empty = Database("empty") empty.register(depends=[]) with self.assertRaises(UnprocessedDatabase): rlca = RegionalizationBase({("empty", "nothing"): 1}) rlca.get_inventory_geocollections()
def write_database(): bio_data = { ("bio", "a"): { 'exchange': [], 'type': 'biosphere' }, ("bio", "b"): { 'exchange': [], 'type': 'biosphere' }, } Database("bio").write(bio_data) tech_data = { ("test", "1"): { 'exchanges': [{ 'amount': 1, 'type': 'production', 'input': ("test", "1"), 'uncertainty type': 0 }, { 'amount': 0.1, 'type': 'technosphere', 'input': ("test", "3"), 'uncertainty type': 0 }, { 'amount': 7, 'type': 'biosphere', 'input': ("bio", "b"), 'uncertainty type': 0 }], }, ("test", "2"): { 'exchanges': [{ 'amount': 0.5, 'type': 'production', 'input': ("test", "2"), 'uncertainty type': 0 }, { 'amount': -2, 'type': 'technosphere', 'input': ("test", "1"), 'uncertainty type': 0 }, { 'amount': 1, 'type': 'biosphere', 'input': ("bio", "a"), 'uncertainty type': 0 }, { 'amount': 5, 'type': 'biosphere', 'input': ("bio", "b"), 'uncertainty type': 0 }], }, ("test", "3"): { 'exchanges': [{ 'amount': 1, 'type': 'production', 'input': ("test", "3"), 'uncertainty type': 0 }, { 'amount': 3, 'type': 'technosphere', 'input': ("test", "1"), 'uncertainty type': 0 }, { 'amount': 2, 'type': 'technosphere', 'input': ("test", "2"), 'uncertainty type': 0 }, { 'amount': 2, 'type': 'biosphere', 'input': ("bio", "a"), 'uncertainty type': 0 }], } } Database("test").write(tech_data) cfs = [ (("bio", "a"), 4), (("bio", "b"), -2), ] Method(("m", )).register() Method(("m", )).write(cfs)
def __init__(self, database_name, objs=None): assert database_name in databases, "Database {} not found".format(database_name) self.db = Database(database_name) self.db.order_by = "name" self.objs = objs or iter(self.db)
class DatabaseToGEXF(object): """Export a Gephi graph for a database. Call ``.export()`` to export the file after class instantiation. Args: * *database* (str): Database name. * *include_descendants* (bool): Include databases which are linked from ``database``. .. warning:: ``include_descendants`` is not yet implemented. """ def __init__(self, database, include_descendants=False): self.database = database self.descendants = include_descendants if self.descendants: raise NotImplemented filename = database + ("_plus" if include_descendants else "") self.filepath = os.path.join(projects.output_dir, filename + ".gexf") self.data = Database(self.database).load() self.id_mapping = dict([(key, str(i)) for i, key in enumerate(self.data)]) def export(self): """Export the Gephi XML file. Returns the filepath of the created file.""" E = ElementMaker(namespace="http://www.gexf.net/1.2draft", nsmap={None: "http://www.gexf.net/1.2draft"}) meta = E.meta(E.creator("Brightway2"), E.description(self.database), lastmodified=datetime.date.today().strftime("%Y-%m-%d")) attributes = E.attributes( E.attribute(id="0", title="category", type="string"), **{"class": "node"}) nodes, edges = self.get_data(E) graph = E.graph(attributes, nodes, edges, mode="static", defaultedgetype="directed") with open(self.filepath, "w", encoding='utf-8') as f: # Need XML declaration, but then ``tostring`` returns bytes # so need to decode. # See https://bugs.python.org/issue10942 # and http://makble.com/python-why-lxml-etree-tostring-method-returns-bytes f.write( tostring(E.gexf(meta, graph, version="1.2"), xml_declaration=True, encoding="utf-8", pretty_print=True).decode("utf-8")) return self.filepath def get_data(self, E): """Get Gephi nodes and edges.""" count = itertools.count() nodes = [] edges = [] pbar = pyprind.ProgBar(len(self.data), title="Get nodes and edges:", monitor=True) for key, value in self.data.items(): nodes.append( E.node(E.attvalues( E.attvalue(value="-".join(value.get("categories", [])), **{"for": "0"})), id=self.id_mapping[key], label=value.get("name", "Unknown"))) for exc in value.get("exchanges", []): if exc["input"] not in self.id_mapping: continue elif exc["input"] == key: # Don't need production process in graph continue else: edges.append( E.edge( id=str(next(count)), source=self.id_mapping[exc["input"]], target=self.id_mapping[key], label="%.3g" % exc['amount'], )) pbar.update() print(pbar) return E.nodes(*nodes), E.edges(*edges)