def link_local_electricity_supply(self): """Create LDV activities for REMIND regions and relink existing electricity exchanges for BEVs and PHEVs to REMIND-compatible (regional) market groups. """ print( "Re-linking local electricity supply for all EV and FCEV activities" ) for region in self.iam_data.regions: try: supply = ws.get_one( self.db, ws.equals( "name", "electricity market for fuel preparation, {}".format( self.year)), ws.equals("location", region)) # replace electricity input supply["exchanges"] = [ e for e in supply["exchanges"] if e["type"] == "production" ] supply["exchanges"].append({ "amount": 1.0, "location": region, "name": "market group for electricity, low voltage", "product": "electricity, low voltage", "tag": "energy chain", "type": "technosphere", "uncertainty type": 0, "unit": "kilowatt hour", }) except ws.NoResults: pass
def get_suppliers_of_a_region( self, remind_region, ecoinvent_technologies, reference_product ): """ Return a list of datasets which location and name correspond to the region, name and reference product given, respectively. :param remind_region: a REMIND region :type remind_region: str :param ecoinvent_technologies: list of names of ecoinvent dataset :type ecoinvent_technologies: list :param reference_product: reference product :type reference_product: str :return: list of wurst datasets :rtype: list """ return ws.get_many( self.db, *[ ws.either( *[ ws.equals("name", supplier) for supplier in ecoinvent_technologies ] ), ws.either( *[ ws.equals("location", loc) for loc in self.geo.remind_to_ecoinvent_location(remind_region) ] ), ws.equals("unit", "kilogram"), ws.equals("reference product", reference_product), ] )
def adjust_recycled_steel_share(self, dict_act): """ Adjust the supply shares of primary and secondary steel, based on REMIND data. :param dict_act: dictionary with REMIND region as keys and datasets as values. :type dict_act: dict :return: same dictionary, with modified exchanges :rtype: dict """ dict_act = self.remove_exchanges(dict_act, ['steel production']) for d, act in dict_act.items(): remind_region = d total_production_volume = self.steel_data.sel(region=remind_region, variables='Production|Industry|Steel') primary_share = (self.steel_data.sel(region=remind_region, variables='Production|Industry|Steel|Primary') / total_production_volume).values secondary_share = 1 - primary_share ds = ws.get_one(self.db, ws.equals('reference product', act['reference product']), ws.contains('name', 'steel production'), ws.contains('name', 'converter'), ws.contains('location', 'RoW')) act['exchanges'].append( { "uncertainty type": 0, "loc": 1, "amount": primary_share, "type": "technosphere", "production volume": 1, "product": ds['reference product'], "name": ds['name'], "unit": ds['unit'], "location": remind_region, } ) ds = ws.get_one(self.db, ws.equals('reference product', act['reference product']), ws.contains('name', 'steel production'), ws.contains('name', 'electric'), ws.contains('location', 'RoW')) act['exchanges'].append( { "uncertainty type": 0, "loc": 1, "amount": secondary_share, "type": "technosphere", "production volume": 1, "product": ds['reference product'], "name": ds['name'], "unit": ds['unit'], "location": remind_region, } ) return dict_act
def producer_in_locations(locs): possible_producers = list( ws.get_many( self.db, ws.equals("name", name), ws.either(*[ws.equals("location", loc) for loc in locs]))) if len(possible_producers) == 1: selected_producer = possible_producers[0] elif len(possible_producers) > 1: possible_locations = tuple( [p["location"] for p in possible_producers]) print( ("Multiple potential producers for {} found in {}, " "using activity from {}").format(name, region, possible_locations)) mapping = { ("RAS", "RER"): "RER", } selected_producer = [ p for p in possible_producers if p["location"] == mapping.get(possible_locations, "RER") ][0] print("We will use the following location: {}".format( selected_producer["location"])) else: selected_producer = None return selected_producer
def producer_in_locations(locs): prod = None producers = list(ws.get_many( self.db, ws.equals("name", name), ws.either(*[ ws.equals("location", loc) for loc in locs ]))) if len(producers) >= 1: prod = producers[0] if len(producers) > 1: print(("Multiple producers for {} found in {}, " "using activity from {}").format( name, region, prod["location"])) return prod
def add_negative_CO2_flows_for_biomass_CCS(self): """ Rescale the amount of all exchanges of carbon dioxide, non-fossil by a factor -9 (.9/-.1), to account for sequestered CO2. All CO2 capture and storage in the Carma datasets is assumed to be 90% efficient. Thus, we can simply find out what the new CO2 emission is and then we know how much gets stored in the ground. It's very important that we ONLY do this for biomass CCS plants, as only they will have negative emissions! Modifies in place (does not return anything). """ for ds in ws.get_many(self.db, ws.contains('name', 'storage'), ws.equals('database', 'Carma CCS')): for exc in ws.biosphere(ds, ws.equals('name', 'Carbon dioxide, non-fossil')): wurst.rescale_exchange(exc, (0.9 / -0.1), remove_uncertainty=True)
def default_global_location(database): """Set missing locations to ```GLO``` for datasets in ``database``. Changes location if ``location`` is missing or ``None``. Will add key ``location`` if missing.""" for ds in get_many(database, *[equals('location', None)]): ds['location'] = 'GLO' return database
def _find_local_supplier(self, region, name): """ Use geomatcher to find a supplier with `name` first strictly within the region, then in an intersecting region and eventually *any* activity with this name. """ def producer_in_locations(locs): possible_producers = list( ws.get_many( self.db, ws.equals("name", name), ws.either(*[ws.equals("location", loc) for loc in locs]))) if len(possible_producers) == 1: selected_producer = possible_producers[0] elif len(possible_producers) > 1: possible_locations = tuple( [p["location"] for p in possible_producers]) print( ("Multiple potential producers for {} found in {}, " "using activity from {}").format(name, region, possible_locations)) mapping = { ("RAS", "RER"): "RER", } selected_producer = [ p for p in possible_producers if p["location"] == mapping.get(possible_locations, "RER") ][0] print("We will use the following location: {}".format( selected_producer["location"])) else: selected_producer = None return selected_producer ei_locs = self.geo.iam_to_ecoinvent_location(region, contained=True) prod = producer_in_locations(ei_locs) if prod is None: ei_locs = self.geo.iam_to_ecoinvent_location(region) prod = producer_in_locations(ei_locs) if prod is None: # let's use "any" dataset producers = list(ws.get_many(self.db, ws.equals("name", name))) if len(producers) == 0: raise ValueError("No producers found for {}.".format(name)) prod = producers[0] # we can leave things as they are since the existing # supply is the default supply print( ("No producers for {} found in {}\n" "Using activity from {}").format(name, region, prod["location"])) return prod
def _get_local_act_or_copy(self, db, act, region): """ Find and return a local activity. If it is not found, create a local copy, append it to the database and return it. If multiple results are found, throw a ValueError. """ local_acts = list(ws.get_many( db, ws.equals("name", act["name"]), ws.equals("location", region))) if len(local_acts) == 1: return local_acts[0] elif len(local_acts) == 0: new_act = self._create_local_copy(act, region) self.db.append(new_act) return new_act else: raise ValueError("Multiple activities found for {} in {}" .format(act["name"], region))
def create_local_evs(self): """Create LDV activities for REMIND regions and relink existing electricity exchanges for BEVs and PHEVs to REMIND-compatible (regional) market groups. """ print("Creating local BEV and PHEV activities") bevs = list(ws.get_many( self.db, ws.either( ws.contains("name", "BEV,"), ws.contains("name", "PHEV")))) self._delete_non_global(bevs) old_supply = ws.get_one( self.db, ws.startswith( "name", "electricity supply for electric vehicles")) for region in self.remind_regions: # create local electricity supply supply = self._create_local_copy(old_supply, region) # replace electricity input for sup in ws.technosphere( supply, ws.equals("product", "electricity, low voltage")): sup.update({ "name": "market group for electricity, low voltage", "location": region }) print("Relinking electricity markets for BEVs in {}".format(region)) for bev in bevs: new_bev = self._create_local_copy(bev, region) # update fuel market oldex = list(ws.technosphere( new_bev, ws.startswith( "name", "electricity supply for electric vehicles"))) # should only be one if len(oldex) != 1: raise ValueError( "Zero or more than one electricity " "markets for fuel production found for {} in {}" .format(new_bev["name"], new_bev["location"])) elif len(oldex) == 1: # reference the new supply oldex[0].update({ "location": region }) self.db.append(new_bev) self.db.append(supply)
def change_biogenic_co2_name(self): """ CO2 capture through biomass growth is represented with `Carbon dioxide, in air`. However, such flow does not have a CF in the IPCC method. This becomes an issue when biommas is used together with CCS. Hence, we change th flow name to `Carbon dioxide, to soil or biomass stock`, for which the IPPCC has a CF of -1. :return: """ for ds in self.db: for exc in ws.biosphere( ds, ws.equals("name", "Carbon dioxide, in air")): exc["name"] = "Carbon dioxide, to soil or biomass stock" exc["categories"] = ("soil", ) for exc in ws.biosphere( ds, ws.equals("name", "Carbon dioxide, non-fossil")): exc["name"] = "Carbon dioxide, from soil or biomass stock" exc["categories"] = ("air", )
def update_efficiency_of_solar_PV(self): """ Update the efficiency of solar PV modules. We look at how many square meters are needed per kilowatt of installed capacity to obtain the current efficiency. Then we update the surface needed according to the projected efficiency. :return: """ ds = ws.get_many( self.db, *[ ws.contains("name", "photovoltaic"), ws.either( ws.contains("name", "installation"), ws.contains("name", "construction"), ), ws.doesnt_contain_any("name", ["market", "factory"]), ws.equals("unit", "unit"), ]) for d in ds: power = float(re.findall("\d+", d["name"])[0]) for exc in ws.technosphere( d, *[ ws.contains("name", "photovoltaic"), ws.equals("unit", "square meter"), ]): surface = float(exc["amount"]) max_power = surface # in kW, since we assume a constant 1,000W/m^2 current_eff = power / max_power new_eff = get_efficiency_ratio_solar_PV(self.year, power).values # We only update the efficiency if it is higher than the current one. if new_eff > current_eff: exc["amount"] *= float(current_eff / new_eff) d["parameters"] = {"efficiency": new_eff} return self.db
def update_cars(self): try: next( ws.get_many( self.db, ws.equals("name", "market group for electricity, low voltage"))) crs = Cars(self.db, self.rdc, self.scenario, self.year) crs.update_cars() except StopIteration as e: print(("No updated electricity markets found. Please update " "electricity markets before updating upstream fuel " "inventories for electricity powered vehicles"))
def find_location_given_lookup_dict(self, lookup_dict): """ Return a list of location names, given the filtering conditions given in `lookup_dict`. It is, for example, used to return a list of location names based on the name and the unit of a dataset. :param lookup_dict: a dictionary with filtering conditions :return: a list of location names :rtype: list """ return [ x["location"] for x in wurst.searching.get_many( self.db, *[ws.equals(k, v) for k, v in lookup_dict.items()]) ]
def add_non_fossil_co2_flows_to_ipcc_method(): """Add non-fossil CO2 flows to the IPCC 2013 GWP 100a method.""" ipcc = bw.Method(('IPCC 2013', 'climate change', 'GWP 100a')) gwp_data = ipcc.load() non_fossil = [ x for x in ws.get_many(bw.Database("biosphere3"), ws.equals("name", "Carbon dioxide, non-fossil")) ] print("Adding the following flows:") pprint(non_fossil) gwp_data.extend([(x.key, 1.) for x in non_fossil]) co2_in_air = ws.get_one(bw.Database("biosphere3"), ws.equals("name", 'Carbon dioxide, in air')) print("Adding {}.".format(co2_in_air)) gwp_data.append((co2_in_air.key, -1.)) method = bw.Method(('IPCC 2013', 'climate change', 'GWP 100a', 'Complete')) method.register() method.write(gwp_data) method.process()
def _create_local_copy(old_act, region): """ Create a local copy of an activity. Update also the production exchange. """ act = copy.deepcopy(old_act) act.update({"location": region, "code": str(uuid.uuid4().hex)}) # update production exchange prods = list(ws.production(act, ws.equals("name", act["name"]))) if len(prods) == 1: prods[0]["location"] = region else: raise ValueError( "Multiple or no Production Exchanges found for {}.".format( old_act["name"])) return act
def _find_local_supplier(self, region, name): """ Use geomatcher to find a supplier with `name` first strictly within the region, then in an intersecting region and eventually *any* activity with this name. """ def producer_in_locations(locs): prod = None producers = list(ws.get_many( self.db, ws.equals("name", name), ws.either(*[ ws.equals("location", loc) for loc in locs ]))) if len(producers) >= 1: prod = producers[0] if len(producers) > 1: print(("Multiple producers for {} found in {}, " "using activity from {}").format( name, region, prod["location"])) return prod ei_locs = self.geo.remind_to_ecoinvent_location(region, contained=True) prod = producer_in_locations(ei_locs) if prod is None: ei_locs = self.geo.remind_to_ecoinvent_location(region) prod = producer_in_locations(ei_locs) if prod is None: # let's use "any" dataset producers = list(ws.get_many( self.db, ws.equals("name", name))) if len(producers) == 0: raise ValueError("No producers found for {}.") prod = producers[0] # we can leave things as they are since the existing # supply is the default supply print(("No producers for {} found in {}\n" "Using activity from {}") .format(name, region, prod["location"])) return prod
def get_suppliers_of_a_region(self, iam_region, ecoinvent_technologies, reference_product, unit="kilogram", look_for_locations_in="ecoinvent"): """ Return a list of datasets which location and name correspond to the region, name and reference product given, respectively. :param unit: unit of the dataset. If not specified, "kilogram" is used. :param look_for_locations_in: whether it should look for a supplier in ecoinvent locations or IAM locations. :param iam_region: an IAM region :type iam_region: str :param ecoinvent_technologies: list of names of ecoinvent dataset :type ecoinvent_technologies: list :param reference_product: reference product :type reference_product: str :return: list of wurst datasets :rtype: list """ if look_for_locations_in == "ecoinvent": return ws.get_many( self.db, *[ ws.either(*[ ws.contains("name", supplier) for supplier in ecoinvent_technologies ]), ws.either(*[ ws.equals("location", loc) for loc in self.geo.iam_to_ecoinvent_location(iam_region) ]), ws.equals("unit", unit), ws.equals("reference product", reference_product), ]) else: return ws.get_many( self.db, *[ ws.either(*[ ws.contains("name", supplier) for supplier in ecoinvent_technologies ]), ws.equals("location", look_for_locations_in), ws.equals("unit", unit), ws.equals("reference product", reference_product), ])
def create_local_icevs(self): """ Use REMIND fuel markets to update the mix of bio-, syn- and fossil liquids in gasoline and diesel. """ print("Creating local ICEV activities") icevs = list(ws.get_many( self.db, ws.either( ws.contains("name", "ICEV-"), ws.contains("name", "HEV-")) )) old_suppliers = { fuel: ws.get_one( self.db, ws.startswith( "name", "fuel supply for {} vehicles".format(fuel))) for fuel in ["diesel", "gasoline"]} new_producers = { "diesel": { # biodiesel is only from cooking oil from RER, # as this is not the focus for now # to be improved! "Biomass": ws.get_one( self.db, ws.equals("name", "Biodiesel from cooking oil")) }, "gasoline": { # only ethanol from European wheat straw as biofuel "Biomass": ws.get_one( self.db, ws.equals("name", "Ethanol from wheat straw pellets"), ws.equals("location", "RER")) } } data = self.rmd.get_remind_fuel_mix_for_ldvs() for region in self.remind_regions: # two regions for gasoline and diesel production if region == "EUR": new_producers["gasoline"]["Fossil"] = ws.get_one( self.db, ws.equals("name", "market for petrol, low-sulfur"), ws.equals("location", "Europe without Switzerland")) new_producers["diesel"]["Fossil"] = ws.get_one( self.db, ws.equals("name", "market group for diesel"), ws.equals("location", "RER")) else: new_producers["gasoline"]["Fossil"] = ws.get_one( self.db, ws.equals("name", "market for petrol, low-sulfur"), ws.equals("location", "RoW")) new_producers["diesel"]["Fossil"] = ws.get_one( self.db, ws.equals("name", "market group for diesel"), ws.equals("location", "GLO")) # local syndiesel new_producers["diesel"]["Hydrogen"] = self._find_local_supplier( region, "Diesel production, synthetic, Fischer Tropsch process") new_producers["gasoline"]["Hydrogen"] = self._find_local_supplier( region, "Gasoline production, synthetic, from methanol") print("Relinking fuel markets for ICEVs in {}".format(region)) for ftype in new_producers: new_supp = self._create_local_copy( old_suppliers[ftype], region) new_supp["exchanges"] = [{ "amount": data.loc[region, suptype].values.item(), "name": new_producers[ftype][suptype]["name"], "location": new_producers[ftype][suptype]["location"], "unit": "kilogram", "type": "technosphere", "reference product": new_producers[ftype][suptype]["reference product"], "product": new_producers[ftype][suptype]["reference product"] } for suptype in new_producers[ftype]] new_supp["exchanges"].append({ "amount": 1, "name": new_supp["name"], "location": region, "unit": "kilogram", "type": "production", "reference product": "fuel", "product": "fuel" }) self.db.append(new_supp) shortcuts = { "diesel": "EV-d", "gasoline": "EV-p" } for ftype in shortcuts: # diesel cars cars = list(ws.get_many( icevs, ws.contains("name", shortcuts[ftype]))) for car in cars: # some local activities might already exist local_dcar = self._get_local_act_or_copy( cars, car, region) # replace diesel supplier fuel_ex = next(ws.technosphere( local_dcar, ws.startswith( "name", "fuel supply for {} vehicles".format(ftype)))) fuel_ex["location"] = region
def add_modified_tags(original_db, scenarios): """ Add a `modified` label to any activity that is new Also add a `modified` label to any exchange that has been added or that has a different value than the source database. :return: """ # Class `Export` to which the original database is passed exp = Export(original_db) # Collect a dictionary of activities {row/col index in A matrix: code} rev_ind_A = rev_index(create_codes_index_of_A_matrix(original_db)) # Retrieve list of coordinates [activity, activity, value] coords_A = exp.create_A_matrix_coordinates() # Turn it into a dictionary {(code of receiving activity, code of supplying activity): value} original = {(rev_ind_A[x[0]], rev_ind_A[x[1]]): x[2] for x in coords_A} # Collect a dictionary with activities' names and correponding codes codes_names = create_codes_and_names_of_A_matrix(original_db) # Collect list of substances rev_ind_B = rev_index(create_codes_index_of_B_matrix()) # Retrieve list of coordinates of the B matrix [activity index, substance index, value] coords_B = exp.create_B_matrix_coordinates() # Turn it into a dictionary {(activity code, substance code): value} original.update({(rev_ind_A[x[0]], rev_ind_B[x[1]]): x[2] for x in coords_B}) for s, scenario in enumerate(scenarios): print(f"Looking for differences in database {s + 1} ...") rev_ind_A = rev_index(create_codes_index_of_A_matrix(scenario["database"])) exp = Export(scenario["database"], scenario["model"], scenario["pathway"], scenario["year"], "") coords_A = exp.create_A_matrix_coordinates() new = {(rev_ind_A[x[0]], rev_ind_A[x[1]]): x[2] for x in coords_A} rev_ind_B = rev_index(create_codes_index_of_B_matrix()) coords_B = exp.create_B_matrix_coordinates() new.update({(rev_ind_A[x[0]], rev_ind_B[x[1]]): x[2] for x in coords_B}) list_new = set(i[0] for i in original.keys()) ^ set(i[0] for i in new.keys()) ds = (d for d in scenario["database"] if d["code"] in list_new) # Tag new activities for d in ds: d["modified"] = True # List codes that belong to activities that contain modified exchanges list_modified = (i[0] for i in new if i in original and new[i] != original[i]) # # Filter for activities that have modified exchanges for ds in ws.get_many( scenario["database"], ws.either(*[ws.equals("code", c) for c in set(list_modified)]) ): # Loop through biosphere exchanges and check if # the exchange also exists in the original database # and if it has the same value # if any of these two conditions is False, we tag the exchange excs = (exc for exc in ds["exchanges"] if exc["type"] == "biosphere") for exc in excs: if (ds["code"], exc["input"][0]) not in original or new[(ds["code"], exc["input"][0])] != original[(ds["code"], exc["input"][0])]: exc["modified"] = True # Same thing for technosphere exchanges, # except that we first need to look up the provider's code first excs = (exc for exc in ds["exchanges"] if exc["type"] == "technosphere") for exc in excs: if (exc["name"], exc["product"], exc["unit"], exc["location"]) in codes_names: exc_code = codes_names[(exc["name"], exc["product"], exc["unit"], exc["location"])] if new[(ds["code"], exc_code)] != original[(ds["code"], exc_code)]: exc["modified"] = True else: exc["modified"] = True return scenarios
def link_local_liquid_fuel_markets(self): """ Use IAM fuel markets to update the mix of bio-, syn- and fossil liquids in gasoline and diesel. """ new_producers = { "diesel": { # biodiesel is only from cooking oil from RER, # as this is not the focus for now # to be improved! "Biomass": ws.get_one( self.db, ws.equals( "name", "Biodiesel, from used cooking oil, at fuelling station" ), ) }, "gasoline": { # only ethanol from European wheat straw as biofuel "Biomass": ws.get_one( self.db, ws.equals( "name", "Ethanol, from wheat straw pellets, at fuelling station" ), ws.equals("location", "RER"), ) }, } for region in self.iam_data.regions: try: supply = { ftype: ws.get_one( self.db, ws.equals("location", region), ws.equals( "name", "fuel supply for {} vehicles, {}".format(ftype, self.year), ), ) for ftype in ["gasoline", "diesel"] } # two regions for gasoline and diesel production if region in ("EUR", "NEU", "WEU", "CEU"): new_producers["gasoline"]["Fossil"] = ws.get_one( self.db, ws.equals("name", "market for petrol, low-sulfur"), ws.equals("location", "Europe without Switzerland"), ) new_producers["diesel"]["Fossil"] = ws.get_one( self.db, ws.equals("name", "market group for diesel"), ws.equals("location", "RER"), ) else: new_producers["gasoline"]["Fossil"] = ws.get_one( self.db, ws.equals("name", "market for petrol, low-sulfur"), ws.equals("location", "RoW"), ) new_producers["diesel"]["Fossil"] = ws.get_one( self.db, ws.equals("name", "market group for diesel"), ws.equals("location", "GLO"), ) # local syndiesel new_producers["diesel"]["Hydrogen"] = self._find_local_supplier( region, "Diesel, synthetic, from electrolysis-based hydrogen, energy allocation, at fuelling station", ) new_producers["gasoline"]["Hydrogen"] = self._find_local_supplier( region, "Gasoline, synthetic, from MTG, hydrogen from electrolysis, energy allocation, at fuelling station", ) supply_search = { "gasoline": { "Hydrogen": "gasoline, synthetic, vehicle grade", "Fossil": "petrol, low-sulfur", }, "diesel": { "Hydrogen": "diesel, synthetic, vehicle grade", "Fossil": "diesel", }, } print("Relinking fuel markets for ICEVs in {}".format(region)) for ftype in supply_search: for subtype in supply_search[ftype]: ex = list( ws.technosphere( supply[ftype], ws.equals("product", supply_search[ftype][subtype]), ) ) if len(ex) > 0: ex[0].update( { "location": new_producers[ftype][subtype][ "location" ], "name": new_producers[ftype][subtype]["name"], } ) except ws.NoResults: pass
def fetch_proxies(self, name, ref_prod): """ Fetch dataset proxies, given a dataset `name` and `reference product`. Store a copy for each REMIND region. If a REMIND region does not find a fitting ecoinvent location, fetch a dataset with a "RoW" location. Delete original datasets from the database. :return: """ d_map = { self.geo.ecoinvent_to_remind_location(d['location']): d['location'] for d in ws.get_many( self.db, ws.equals("name", name), ws.equals("reference product", ref_prod) ) } list_remind_regions = [ c[1] for c in self.geo.geo.keys() if type(c) == tuple and c[0] == "REMIND" ] d_remind_to_eco = {r: d_map.get(r, "RoW") for r in list_remind_regions} d_act = {} for d in d_remind_to_eco: try: ds = ws.get_one( self.db, ws.equals("name", name), ws.equals("reference product", ref_prod), ws.equals("location", d_remind_to_eco[d]), ) d_act[d] = copy.deepcopy(ds) d_act[d]["location"] = d d_act[d]["code"] = str(uuid.uuid4().hex) except ws.NoResults: print('No dataset {} found for the REMIND region {}'.format(name, d)) continue for prod in ws.production(d_act[d]): prod['location'] = d deleted_markets = [ (act['name'], act['reference product'], act['location']) for act in self.db if (act["name"], act['reference product']) == (name, ref_prod) ] with open(DATA_DIR / "logs/log deleted cement datasets.csv", "a") as csv_file: writer = csv.writer(csv_file, delimiter=';', lineterminator='\n') for line in deleted_markets: writer.writerow(line) # Remove old datasets self.db = [act for act in self.db if (act["name"], act['reference product']) != (name, ref_prod)] return d_act