def delete_parameter(self, parameter: ParameterBase) -> None: """ Remove the given parameter from the project. If there are multiple `ActivityParameters` for a single activity, only delete the selected instance, otherwise use `bw.parameters.remove_from_group` to clear out the `ParameterizedExchanges` as well. """ if isinstance(parameter, ActivityParameter): db = parameter.database code = parameter.code amount = (ActivityParameter.select() .where((ActivityParameter.database == db) & (ActivityParameter.code == code)) .count()) if amount > 1: with bw.parameters.db.atomic(): parameter.delete_instance() else: group = parameter.group act = bw.get_activity((db, code)) bw.parameters.remove_from_group(group, act) # Also clear the group if there are no more parameters in it exists = (ActivityParameter.select() .where(ActivityParameter.group == group).exists()) if not exists: with bw.parameters.db.atomic(): Group.delete().where(Group.name == group).execute() else: with bw.parameters.db.atomic(): parameter.delete_instance() # After deleting things, recalculate and signal changes bw.parameters.recalculate() signals.parameters_changed.emit()
def test_delete_activity_param(qtbot): """ Remove activity parameters. """ project_db_tab = ParameterDefinitionTab() qtbot.addWidget(project_db_tab) project_db_tab.build_tables() table = project_db_tab.activity_table rect = table.visualRect(table.proxy_model.index(0, 0)) qtbot.mouseClick(table.viewport(), QtCore.Qt.LeftButton, pos=rect.center()) group = table.get_current_group() # Now delete the parameter for the selected row. table.delete_parameter(table.currentIndex()) assert table.rowCount() == 2 assert ActivityParameter.select().count() == 2 assert Group.get_or_none(name=group) # And delete the other two parameters one by one. table.delete_parameter(table.proxy_model.index(0, 0)) table.delete_parameter(table.proxy_model.index(0, 0)) assert table.rowCount() == 0 assert ActivityParameter.select().count() == 0 # Group is automatically removed with the last parameter gone assert Group.get_or_none(name=group) is None
def resetParams(db_name): """Reset project and activity parameters""" _param_registry().clear() ProjectParameter.delete().execute() ActivityParameter.delete().execute() DatabaseParameter.delete().execute() Group.delete().execute()
def delete_parameter(self, proxy) -> None: """ Override the base method to include additional logic. If there are multiple `ActivityParameters` for a single activity, only delete the selected instance, otherwise use `bw.parameters.remove_from_group` to clear out the `ParameterizedExchanges` as well. """ key = self.get_key(proxy) query = (ActivityParameter.select().where( ActivityParameter.database == key[0], ActivityParameter.code == key[1])) if query.count() > 1: super().delete_parameter(proxy) else: act = bw.get_activity(key) group = self.get_current_group(proxy) bw.parameters.remove_from_group(group, act) # Also clear the group if there are no more parameters in it if ActivityParameter.get_or_none(group=group) is None: with bw.parameters.db.atomic(): Group.get(name=group).delete_instance() bw.parameters.recalculate() signals.parameters_changed.emit()
def add_example_database(overwrite=True): from ..importers.excel import ( assign_only_product_as_production, convert_activity_parameters_to_list, convert_uncertainty_types_to_integers, csv_add_missing_exchanges_section, csv_drop_unknown, csv_numerize, csv_restore_booleans, csv_restore_tuples, drop_falsey_uncertainty_fields_but_keep_zeros, ExcelImporter, set_code_by_activity_hash, strip_biosphere_exc_locations, ) if "Mobility example" in databases: if not overwrite: print("Example already imported, use `overwrite=True` to delete") return else: del databases["Mobility example"] if ("IPCC", "simple") in methods: del methods[("IPCC", "simple")] importer = ExcelImporter( os.path.join(dirpath, "examples", "sample_parameterized_database.xlsx")) importer.strategies = [ csv_restore_tuples, csv_restore_booleans, csv_numerize, csv_drop_unknown, csv_add_missing_exchanges_section, strip_biosphere_exc_locations, set_code_by_activity_hash, assign_only_product_as_production, drop_falsey_uncertainty_fields_but_keep_zeros, convert_uncertainty_types_to_integers, convert_activity_parameters_to_list, ] importer.apply_strategies() importer.match_database(fields=['name']) importer.write_database(activate_parameters=True) group = "Mobility exchanges" Group.delete().where(Group.name == group).execute() group = Group.create(name=group) for ds in Database("Mobility example"): parameters.add_exchanges_to_group(group, ds) parameters.recalculate() ipcc = Method(("IPCC", "simple")) ipcc.register() ipcc.write([(("Mobility example", "CO2"), 1)])
def delete_database(self, name: str) -> None: ok = QtWidgets.QMessageBox.question(self.window, "Delete database?", ( "Are you sure you want to delete database '{}'? It has {} activity datasets" ).format(name, bc.count_database_records(name))) if ok == QtWidgets.QMessageBox.Yes: project_settings.remove_db(name) del bw.databases[name] Group.delete().where(Group.name == name).execute() ProjectController.change_project(bw.projects.current, reload=True)
def test_append_package(): ProjectParameter.create( name="p1", amount=1, ) ProjectParameter.create( name="p2", amount=1, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("project") pbm.load_parameter_data() pbm.calculate_static() for obj in pbm.data.values(): obj['amount'] = 10 _, dirpath = pbm.save_presample('project-test') pp = PresamplesPackage(dirpath) assert len(pp) == 1 assert pp.parameters['project__p1'] == 10 Database("db").register() Group.create(name="D", order=[]) DatabaseParameter.create( database="db", name="db1", formula="2 * p1", amount=2, ) DatabaseParameter.create( database="db", name="db2", amount=2, ) ActivityParameter.create( group="D", database="db", code="D1", name="d1", formula="p1 + db1", amount=3, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("D") pbm.load_existing(dirpath) expected = {'project__p1': 10, 'project__p2': 10} assert pbm.global_params == expected pbm.load_parameter_data() pbm.data = {'D__d1': pbm.data['D__d1']} pbm.data['D__d1']['amount'] = 12 _, dp = pbm.append_presample(dirpath, 'D-test') assert dp == dirpath pp = PresamplesPackage(dirpath) assert len(pp) == 2 assert pp.parameters['D__d1'] == 12 assert pp.parameters['project__p1'] == 10
def test_calculate_stochastic(): Database("db").register() ProjectParameter.create( name="p1", amount=1, ) ProjectParameter.create( name="p2", amount=1, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("project") pbm.load_parameter_data() pbm.data['project__p1']['amount'] = np.ones(10) + 100 pbm.data['project__p2']['amount'] = np.ones(10) + 10 _, dirpath_project = pbm.save_presample('project-test') pp = PresamplesPackage(dirpath_project) assert len(pp) == 1 assert np.allclose(pp.parameters['project__p1'], np.ones(10) + 100) # Create rest of parameters Group.create(name="E", order=[]) ActivityParameter.create( group="E", database="db", code="E1", name="e1", formula="p1 + p2 + e2", amount=4, ) ActivityParameter.create(group="E", database="db", code="E2", name="e2", amount=1, data={ 'uncertainty type': 4, 'minimum': 1000, 'maximum': 1100 }) parameters.recalculate() pbm = ParameterizedBrightwayModel("E") pbm.load_existing(dirpath_project) pbm.load_parameter_data() result = pbm.calculate_stochastic(10) assert np.allclose(result['project__p1'], [101] * 10) assert np.allclose(result['project__p2'], [11] * 10) assert all(result['E__e2'] >= 1000) assert all(result['E__e2'] <= 1100) assert np.allclose(result['E__e1'], result['E__e2'] + 101 + 11)
def resetParams(db_name=None): """Clear parameters in live memory (registry) and on disk. Clear either all params (project and all db params) or db params from a single database (if db_name provided)""" _param_registry().clear(db_name) if db_name is None: ProjectParameter.delete().execute() ActivityParameter.delete().execute() DatabaseParameter.delete().execute() else: ActivityParameter.delete().where( ActivityParameter.database == db_name).execute() DatabaseParameter.delete().where( DatabaseParameter.database == db_name).execute() Group.delete().execute()
def modify_parameter(self, param: ParameterBase, field: str, value: Union[str, float, list]) -> None: with bw.parameters.db.atomic() as transaction: try: if hasattr(param, field): setattr(param, field, value) elif field == "order": # Store the given order in the Group used by the parameter if param.group in value: value.remove(param.group) group = Group.get(name=param.group) group.order = value group.expire() else: param.data[field] = value param.save() bw.parameters.recalculate() except Exception as e: # Anything wrong? Roll the transaction back and throw up a # warning message. transaction.rollback() QMessageBox.warning( self.window, "Could not save changes", str(e), QMessageBox.Ok, QMessageBox.Ok ) signals.parameters_changed.emit()
def get_usable_parameters(self): """ Use the `key` set for the table to determine the database and group of the activity, using that information to constrain the usable parameters. """ project = ([k, v, "project"] for k, v in ProjectParameter.static().items()) if self.key is None: return project database = ([k, v, "database"] for k, v in DatabaseParameter.static(self.key[0]).items()) # Determine if the activity is already part of a parameter group. query = (Group.select().join( ActivityParameter, on=(Group.name == ActivityParameter.group)).where( ActivityParameter.database == self.key[0], ActivityParameter.code == self.key[1]).distinct()) if query.exists(): group = query.get() # First, build a list for parameters in the same group activity = ([p.name, p.amount, "activity"] for p in ActivityParameter.select().where( ActivityParameter.group == group.name)) # Then extend the list with parameters from groups in the `order` # field additions = ([p.name, p.amount, "activity"] for p in ActivityParameter.select().where( ActivityParameter.group << group.order)) activity = itertools.chain(activity, additions) else: activity = [] return itertools.chain(project, database, activity)
def clear_broken_activity_parameter(database: str, code: str, group: str) -> None: """Take the given information and attempt to remove all of the downstream parameter information. """ with bw.parameters.db.atomic() as txn: bw.parameters.remove_exchanges_from_group(group, None, False) ActivityParameter.delete().where( ActivityParameter.database == database, ActivityParameter.code == code ).execute() # Do commit to ensure .exists() call does not include deleted params txn.commit() exists = (ActivityParameter.select() .where(ActivityParameter.group == group) .exists()) if not exists: # Also clear Group if it is not in use anymore Group.delete().where(Group.name == group).execute()
def store_group_order(self, proxy) -> None: """ Store the given order in the Group used by the parameter linked in the proxy. """ param = self.get_parameter(proxy) order = proxy.data() if param.group in order: order.remove(param.group) group = Group.get(name=param.group) group.order = order group.expire()
def delete_activity_parameter(key: tuple) -> None: """Remove all activity parameters and underlying exchange parameters for the given activity key. """ query = (ActivityParameter .select(ActivityParameter.group) .where((ActivityParameter.database == key[0]) & (ActivityParameter.code == key[1])) .tuples()) if not query.exists(): return groups = set(p[0] for p in query) for group in groups: bw.parameters.remove_from_group(group, key) exists = (ActivityParameter.select() .where(ActivityParameter.group == group) .exists()) if not exists: Group.delete().where(Group.name == group).execute() bw.parameters.recalculate() signals.parameters_changed.emit()
def test_chain_loading_complicated(): Database("db").register() Group.create(name="D", order=[]) Group.create(name="E", order=[]) Group.create(name="B", order=["E"]) Group.create(name="C", order=["D", "E"]) Group.create(name="A", order=["C", "B"]) ProjectParameter.create( name="p1", amount=1, ) ProjectParameter.create( name="p2", amount=1, ) DatabaseParameter.create( database="db", name="db1", formula="2 * p1", amount=2, ) DatabaseParameter.create( database="db", name="db2", amount=2, ) ActivityParameter.create( group="D", database="db", code="D1", name="d1", formula="p1 + db1", amount=3, ) ActivityParameter.create( group="E", database="db", code="E1", name="e1", formula="p1 + p2 + db2", amount=4, ) ActivityParameter.create( group="C", database="db", code="C1", name="c1", formula="(e1 - d1) * 5", amount=5, ) ActivityParameter.create( group="B", database="db", code="B1", name="b1", formula="e1 * 2 - 2", amount=6, ) ActivityParameter.create( group="A", database="db", code="A1", name="a1", formula="b1 + c1 - db1 - 2", amount=7, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("A") pbm.load_parameter_data() expected = { 'A__a1': { 'amount': 7.0, 'code': 'A1', 'database': 'db', 'formula': '(((B__b1 + C__c1) - db__db1) - 2)', 'original': 'a1' }, 'B__b1': { 'amount': 6.0, 'code': 'B1', 'database': 'db', 'formula': '((E__e1 * 2) - 2)', 'original': 'b1' }, 'C__c1': { 'amount': 5.0, 'code': 'C1', 'database': 'db', 'formula': '((E__e1 - D__d1) * 5)', 'original': 'c1' }, 'D__d1': { 'amount': 3.0, 'code': 'D1', 'database': 'db', 'formula': '(project__p1 + db__db1)', 'original': 'd1' }, 'E__e1': { 'amount': 4.0, 'code': 'E1', 'database': 'db', 'formula': '((project__p1 + project__p2) + db__db2)', 'original': 'e1' }, 'db__db1': { 'amount': 2.0, 'database': 'db', 'formula': '(2 * project__p1)', 'original': 'db1' }, 'db__db2': { 'amount': 2.0, 'database': 'db', 'original': 'db2' }, 'project__p1': { 'amount': 1.0, 'original': 'p1' }, 'project__p2': { 'amount': 1.0, 'original': 'p2' } } assert pbm.data == expected
def test_calculate_matrix_presamples(): data = { ("test-db", 'b'): { 'exchanges': [], 'type': 'emission', }, ("test-db", 't1'): { 'exchanges': [{ 'amount': 1, 'input': ('test-db', 't2'), 'type': 'technosphere', 'formula': 'foo + bar' }, { 'amount': 1, 'input': ('test-db', 'b'), 'type': 'biosphere', 'formula': 'foo - bar + pppp' }], 'type': 'process', }, ("test-db", 't2'): { 'exchanges': [], 'type': 'process', }, } Database("test-db").write(data) Group.create(name="E", order=[]) data = [{ 'name': 'foo', 'database': 'test-db', 'code': 't1', 'amount': 7, 'uncertainty_type': 4, 'minimum': 0, 'maximum': 14, }, { 'name': 'bar', 'database': 'test-db', 'code': 't1', 'amount': 11, }] parameters.new_project_parameters([{'name': 'pppp', 'amount': 12}]) parameters.new_activity_parameters(data, 'A') parameters.add_exchanges_to_group('A', get_activity(("test-db", 't1'))) parameters.recalculate() pbm = ParameterizedBrightwayModel("A") pbm.load_parameter_data() pbm.calculate_static() pbm.calculate_matrix_presamples() id_, dirpath = pbm.save_presample('test-everything') # Check for file contents pp = PresamplesPackage(dirpath) resources = pp.resources assert len(resources) == 3 assert resources[0]['type'] == 'biosphere' assert resources[0]['samples']['shape'] == [1, 1] assert resources[1]['type'] == 'technosphere' assert resources[1]['samples']['shape'] == [1, 1] assert resources[2]['label'] == 'test-everything' assert resources[2]['samples']['shape'] == [3, 1]
def test_load_existing_with_prefix(): # Same as test_load_existing_complete but parameter presamples don't know what groups they are in. # Start with `project` project_parameters = [{ 'name': 'p1', 'amount': 1 }, { 'name': 'p2', 'amount': 1 }] parameters.new_project_parameters(project_parameters) parameters.recalculate() _, dirpath_project = create_presamples_package( parameter_data=[(np.stack([[42], [42]]), ['p1', 'p2'], 'label')]) pbm = ParameterizedBrightwayModel("project") loaded = pbm.load_parameter_data() assert len(loaded) == 2 result = pbm.calculate_static() expected = {'project__p1': 1, 'project__p2': 1} assert result == expected pbm = ParameterizedBrightwayModel("project") pbm.load_existing(dirpath_project, prefix="project") loaded = pbm.load_parameter_data() assert len(loaded) == 0 result = pbm.calculate_static() expected = {'project__p1': 42, 'project__p2': 42} assert result == expected result = pbm.global_params expected = {'project__p1': 42, 'project__p2': 42} assert result == expected pbm = ParameterizedBrightwayModel("project") pbm.load_existing(dirpath_project, only='p1', prefix="project") loaded = pbm.load_parameter_data() assert len(loaded) == 1 result = pbm.calculate_static() expected = {'project__p1': 42, 'project__p2': 1} assert result == expected # With database parameters now Database("db").register() Group.create(name="D", order=[]) database_parameters = [{ 'name': "db1", 'formula': "2 * p1", 'amount': 2, }, { 'name': "db2", 'amount': 2, }, { 'name': "db3", 'formula': "10 * db2", 'amount': 0, }] parameters.new_database_parameters(database_parameters, 'db') _, dirpath_db = create_presamples_package( parameter_data=[(np.array([100]), ['db2'], 'yet another label')]) parameters.recalculate() pbm = ParameterizedBrightwayModel("db") pbm.load_parameter_data() result = pbm.calculate_static() expected = { 'db__db1': 2, 'db__db2': 2, 'db__db3': 20, 'project__p1': 1, 'project__p2': 1, } assert expected == result # Load existing pbm = ParameterizedBrightwayModel("db") pbm.load_existing(dirpath_db, prefix='db') pbm.load_parameter_data() result = pbm.global_params expected = {'db__db2': 100} assert result == expected result = pbm.calculate_static() expected = { 'db__db1': 2, 'db__db2': 100, 'db__db3': 1000, 'project__p1': 1, 'project__p2': 1, } assert expected == result
def test_load_existing_complete(): # Use same structure as in complicated example, but pre-create some presamples packages # Start with `project` ProjectParameter.create( name="p1", amount=1, ) ProjectParameter.create( name="p2", amount=1, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("project") pbm.load_parameter_data() result = pbm.calculate_static() expected = {'project__p1': 1, 'project__p2': 1} assert result == expected for obj in pbm.data.values(): obj['amount'] = 10 _, dirpath_project = pbm.save_presample('project-test') pp = PresamplesPackage(dirpath_project) assert len(pp) == 1 assert pp.parameters['project__p1'] == 10 # We will also do group 'D'; this will include database parameters, which will we purge ourselves Database("db").register() Group.create(name="D", order=[]) DatabaseParameter.create( database="db", name="db1", formula="2 * p1", amount=2, ) DatabaseParameter.create( database="db", name="db2", amount=2, ) ActivityParameter.create( group="D", database="db", code="D1", name="d1", formula="p1 + db1", amount=3, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("D") pbm.load_existing(dirpath_project) expected = {'project__p1': 10, 'project__p2': 10} assert pbm.global_params == expected pbm.load_parameter_data() expected = { 'D__d1': { 'database': 'db', 'code': 'D1', 'formula': '(project__p1 + db__db1)', 'amount': 3.0, 'original': 'd1' }, 'db__db1': { 'database': 'db', 'formula': '(2 * project__p1)', 'amount': 2.0, 'original': 'db1' }, 'db__db2': { 'database': 'db', 'amount': 2.0, 'original': 'db2' }, } assert pbm.data == expected # Want to calculate database parameters dynamically pbm.data = {'D__d1': pbm.data['D__d1']} pbm.data['D__d1']['amount'] = 12 _, dirpath_d = pbm.save_presample('D-test') pp = PresamplesPackage(dirpath_d) assert len(pp) == 1 assert pp.parameters['D__d1'] == 12 # Create rest of parameters Group.create(name="E", order=[]) Group.create(name="B", order=["E"]) Group.create(name="C", order=["D", "E"]) Group.create(name="A", order=["C", "B"]) ActivityParameter.create( group="E", database="db", code="E1", name="e1", formula="p1 + p2 + db2", amount=4, ) ActivityParameter.create( group="C", database="db", code="C1", name="c1", formula="(e1 - d1) * 5", amount=5, ) ActivityParameter.create( group="B", database="db", code="B1", name="b1", formula="e1 * 2 - 2", amount=6, ) ActivityParameter.create( group="A", database="db", code="A1", name="a1", formula="b1 + c1 - db1 - 2", amount=7, ) parameters.recalculate() pbm = ParameterizedBrightwayModel("A") pbm.load_existing(dirpath_project) pbm.load_existing(dirpath_d) pbm.load_parameter_data() expected = { 'A__a1': { 'amount': 7.0, 'code': 'A1', 'database': 'db', 'formula': '(((B__b1 + C__c1) - db__db1) - 2)', 'original': 'a1' }, 'B__b1': { 'amount': 6.0, 'code': 'B1', 'database': 'db', 'formula': '((E__e1 * 2) - 2)', 'original': 'b1' }, 'C__c1': { 'amount': 5.0, 'code': 'C1', 'database': 'db', 'formula': '((E__e1 - D__d1) * 5)', 'original': 'c1' }, 'E__e1': { 'amount': 4.0, 'code': 'E1', 'database': 'db', 'formula': '((project__p1 + project__p2) + db__db2)', 'original': 'e1' }, 'db__db1': { 'amount': 2.0, 'database': 'db', 'formula': '(2 * project__p1)', 'original': 'db1' }, 'db__db2': { 'amount': 2.0, 'database': 'db', 'original': 'db2' }, } assert pbm.data == expected result = pbm.calculate_static() expected = { 'A__a1': 70.0, 'B__b1': 42.0, 'C__c1': 50.0, 'D__d1': 12.0, 'E__e1': 22.0, 'db__db1': 20.0, 'db__db2': 2.0, 'project__p1': 10, 'project__p2': 10, } assert result == expected pbm = ParameterizedBrightwayModel("A") pbm.load_existing(dirpath_project, only=['project__p1']) pbm.load_existing(dirpath_d) pbm.load_parameter_data() assert 'project__p2' in pbm.data assert 'project__p1' not in pbm.data
def test_chain_loading(): Database("B").register() Database("K").register() Group.create(name="G", order=["A"]) ActivityParameter.create( group="A", database="B", code="C", name="D", formula="2 ** 3", amount=1, ) ActivityParameter.create( group="A", database="B", code="E", name="F", formula="foo + bar + D", amount=2, ) ActivityParameter.create( group="G", database="K", code="H", name="J", formula="F + D * 2", amount=3, ) DatabaseParameter.create( database="B", name="foo", formula="2 ** 2", amount=5, ) ProjectParameter.create( name="bar", formula="2 * 2 * 2", amount=6, ) parameters.recalculate() m = ParameterizedBrightwayModel("A") m.load_parameter_data() expected = { 'A__D': { 'database': 'B', 'code': 'C', 'formula': '(2 ** 3)', 'amount': 8.0, 'original': 'D' }, 'A__F': { 'database': 'B', 'code': 'E', 'formula': '((B__foo + project__bar) + A__D)', 'amount': 20.0, 'original': 'F' }, 'B__foo': { 'database': 'B', 'formula': '(2 ** 2)', 'amount': 4.0, 'original': 'foo' }, 'project__bar': { 'formula': '((2 * 2) * 2)', 'amount': 8.0, 'original': 'bar' } } assert m.data == expected