def test_create_database_params(qtbot): """ Create three database parameters Does not user the overarching application due to mouseClick failing """ assert DatabaseParameter.select().count() == 0 project_db_tab = ParameterDefinitionTab() qtbot.addWidget(project_db_tab) project_db_tab.build_tables() table = project_db_tab.database_table # Open the database foldout assert table.isHidden() with qtbot.waitSignal(project_db_tab.show_database_params.stateChanged, timeout=1000): qtbot.mouseClick(project_db_tab.show_database_params, QtCore.Qt.LeftButton) assert not table.isHidden() signal_list = [ signals.parameters_changed, signals.parameters_changed, signals.parameters_changed ] # Generate a few database parameters with qtbot.waitSignals(signal_list, timeout=1000): qtbot.mouseClick(project_db_tab.new_database_param, QtCore.Qt.LeftButton) qtbot.mouseClick(project_db_tab.new_database_param, QtCore.Qt.LeftButton) qtbot.mouseClick(project_db_tab.new_database_param, QtCore.Qt.LeftButton) # First created parameter is named 'param_2' assert table.model.index(0, 0).data() == "param_2" assert table.rowCount() == 3 assert DatabaseParameter.select().count() == 3
def test_edit_database_params(qtbot, monkeypatch): table = DataBaseParameterTable() qtbot.addWidget(table) table.model.sync() # Fill rows with new variables monkeypatch.setattr( QtWidgets.QInputDialog, "getText", staticmethod(lambda *args, **kwargs: ("test_db1", True))) table.model.handle_parameter_rename(table.proxy_model.index(0, 0)) table.model.setData(table.model.index(0, 2), "test_project + 3.5") monkeypatch.setattr( QtWidgets.QInputDialog, "getText", staticmethod(lambda *args, **kwargs: ("test_db2", True))) table.model.handle_parameter_rename(table.proxy_model.index(1, 0)) table.model.setData(table.model.index(1, 2), "test_db1 ** 2") monkeypatch.setattr( QtWidgets.QInputDialog, "getText", staticmethod(lambda *args, **kwargs: ("test_db3", True))) table.model.handle_parameter_rename(table.proxy_model.index(2, 0)) table.model.setData(table.model.index(2, 1), "8.5") table.model.setData(table.model.index(2, 3), "testdb") # 5 + 3.5 = 8.5 -> 8.5 ** 2 = 72.25 assert DatabaseParameter.get(name="test_db2").amount == 72.25 # There are two parameters for `biosphere3` and one for `testdb` assert (DatabaseParameter.select().where( DatabaseParameter.database == "biosphere3").count()) == 2 assert (DatabaseParameter.select().where( DatabaseParameter.database == "testdb").count()) == 1
def get_usable_parameters(): """ Include the project parameters, and generate database parameters. """ project = ProjectParameterTable.get_usable_parameters() database = ([p.name, p.amount, "database ({})".format(p.database)] for p in DatabaseParameter.select()) return itertools.chain(project, database)
def get_database_parameters(self): data = [ o.dict for o in DatabaseParameter.select().where( DatabaseParameter.database == self.db.name ) ] return self.order_dicts(data, "parameter")
def process_brightway_parameters() -> Iterable[tuple]: """ Converts brightway parameters of all types into a simple structure in order of possible dependency. """ return itertools.chain( ((p.name, "project", p.amount) for p in ProjectParameter.select()), ((p.name, p.database, p.amount) for p in DatabaseParameter.select()), ((p.name, p.group, p.amount) for p in ActivityParameter.select()))
def build_df(cls) -> pd.DataFrame: """ Build a dataframe using the DatabaseParameters set in brightway """ data = [ cls.parse_parameter(p) for p in DatabaseParameter.select() ] df = pd.DataFrame(data, columns=cls.combine_columns()) return df
def __init__(self, seed: Optional[int] = None): super().__init__() parameters = itertools.chain(ProjectParameter.select(), DatabaseParameter.select(), ActivityParameter.select()) self.uncertainties = UncertaintyBase.from_dicts( *[getattr(p, "data", {}) for p in parameters]) self.mc_generator = MCRandomNumberGenerator(self.uncertainties, seed=seed)
def recalculate_scenario( self, scenario_values: Iterable[float]) -> (np.ndarray, np.ndarray): """ Convenience function that takes new parameter values and returns a fully-formed set of exchange amounts and indices. All parameter types are recalculated in turn before interpreting the ParameterizedExchange formulas into amounts. """ self.param_values = replace_amounts(self.param_values, scenario_values) global_project = self.recalculate_project_parameters() all_db = {} for p in DatabaseParameter.select( DatabaseParameter.database).distinct(): db = self.recalculate_database_parameters(p.database, global_project) all_db[p.database] = {x: y for x, y in db.items()} if db else {} complete_data = [] complete_indices = [] for p in ActivityParameter.select( ActivityParameter.group, ActivityParameter.database).distinct(): combination = {x: y for x, y in global_project.items() } if global_project else {} combination.update(all_db.get(p.database, {})) act = self.recalculate_activity_parameters(p.group, combination) combination.update(act) recalculated = self.recalculate_exchanges( p.group, global_params=combination) # If the parameter group contains no ParameterizedExchanges, skip. if not recalculated: continue # `data` contains the recalculated amounts for the exchanges. ids, data = zip(*recalculated) indices = [] for pk in ids: exc = ExchangeDataset.get_by_id(pk) input_key = (exc.input_database, exc.input_code) output_key = (exc.output_database, exc.output_code) if exc.input_database == bw.config.biosphere: indices.append((input_key, output_key, "biosphere")) else: indices.append((input_key, output_key, "technosphere")) complete_data.extend(data) complete_indices.extend(indices) # After recalculating all the exchanges and adding all samples and indices # to lists, format them according to presamples requirements: # eg: samples as a column of floats and indices as a row of tuples. samples = np.array(complete_data) samples = samples.reshape(1, -1).T indices = np.array(complete_indices) return samples, indices
def test_create_database_params(qtbot): """ Create three database parameters Does not user the overarching application due to mouseClick failing """ assert DatabaseParameter.select().count() == 0 project_db_tab = ParameterDefinitionTab() qtbot.addWidget(project_db_tab) project_db_tab.build_tables() table = project_db_tab.database_table # Open the database foldout assert not table.isHidden() with qtbot.waitSignal(project_db_tab.show_database_params.stateChanged, timeout=1000): qtbot.mouseClick(project_db_tab.show_database_params, QtCore.Qt.LeftButton) assert table.isHidden() project_db_tab.show_database_params.toggle() # Generate a few database parameters bw.parameters.new_database_parameters([ { "name": "param_2", "amount": 1.0 }, { "name": "param_3", "amount": 1.0 }, { "name": "param_4", "amount": 1.0 }, ], database="biosphere3") table.model.sync() # First created parameter is named 'param_2' assert table.model.index(0, 0).data() == "param_2" assert table.rowCount() == 3 assert DatabaseParameter.select().count() == 3
def from_bw_parameters(cls) -> 'Parameters': """Construct a Parameters list from brightway2 parameters.""" return cls(chain( (Parameter(p.name, "project", p.amount, "project") for p in ProjectParameter.select()), (Parameter(p.name, p.database, p.amount, "database") for p in DatabaseParameter.select()), (Parameter(p.name, p.group, p.amount, "activity") for p in ActivityParameter.select()), ))
def sync(self, *args, **kwargs) -> None: self.beginResetModel() self.root.clear() self.endResetModel() self._data.update({ "project": ProjectParameter.select().iterator(), "database": DatabaseParameter.select().iterator(), "activity": ActivityParameter.select().iterator(), }) self.setup_model_data() self.updated.emit()
def add_parameter(self) -> None: """ Build a new parameter and immediately store it. """ counter = (ProjectParameter.select().count() + DatabaseParameter.select().count()) try: bw.parameters.new_project_parameters([ {"name": "param_{}".format(counter + 1), "amount": 1.0} ], False) signals.parameters_changed.emit() except ValueError as e: simple_warning_box(self, "Name already in use!", str(e))
def test_edit_database_params(qtbot): table = DataBaseParameterTable() qtbot.addWidget(table) table.sync(table.build_df()) # Fill rows with new variables table.rename_parameter(table.proxy_model.index(0, 0), "test_db1") table.model.setData(table.model.index(0, 2), "test_project + 3.5") table.rename_parameter(table.proxy_model.index(1, 0), "test_db2") table.model.setData(table.model.index(1, 2), "test_db1 ** 2") table.rename_parameter(table.proxy_model.index(2, 0), "test_db3") table.model.setData(table.model.index(2, 1), "8.5") table.model.setData(table.model.index(2, 3), "testdb") # 5 + 3.5 = 8.5 -> 8.5 ** 2 = 72.25 assert DatabaseParameter.get(name="test_db2").amount == 72.25 # There are two parameters for `biosphere3` and one for `testdb` assert (DatabaseParameter.select() .where(DatabaseParameter.database == "biosphere3").count()) == 2 assert (DatabaseParameter.select() .where(DatabaseParameter.database == "testdb").count()) == 1
def add_parameter(self) -> None: """ Add a new database parameter to the dataframe NOTE: The new parameter uses the first database it can find. """ counter = (ProjectParameter.select().count() + DatabaseParameter.select().count()) database = next(iter(bw.databases)) try: bw.parameters.new_database_parameters([ {"name": "param_{}".format(counter + 1), "amount": 1.0} ], database, False) signals.parameters_changed.emit() except ValueError as e: simple_warning_box(self, "Name already in use!", str(e))
def test_delete_database_params(qtbot): """ Attempt to delete a parameter. """ project_db_tab = ParameterDefinitionTab() qtbot.addWidget(project_db_tab) project_db_tab.build_tables() table = project_db_tab.database_table # Check that we can delete the parameter and remove it. proxy = table.proxy_model.index(1, 0) assert table.get_parameter(proxy).is_deletable() table.delete_parameter(proxy) # Now we have two rows left assert table.rowCount() == 2 assert DatabaseParameter.select().count() == 2
def __init__(self): self._project_params = ProjectParameter.load() self._db_params = { p.database: DatabaseParameter.load(p.database) for p in DatabaseParameter.select(DatabaseParameter.database).distinct() } self._act_params = { p.group: ActivityParameter.load(p.group) for p in ActivityParameter.select(ActivityParameter.group).distinct() } self._distinct_act_params = [ p for p in (ActivityParameter .select(ActivityParameter.group, ActivityParameter.database) .distinct()) ] self._exc_params = [p for p in ParameterizedExchange.select()]
def export_db(db_name, filename) : """Export Db and linked parameters""" db = bw.Database(db_name) db_params = DatabaseParameter.select().where(DatabaseParameter.database == db_name) # Export Db params db.metadata["database_parameters"] = [param_data(param) for param in db_params] # List of all project params used in this dataset used_project_params = list(param.name for param in _listParams(db_name) if param.dbname is None) if len(used_project_params) > 0 : error('Warning : this DB uses project parameters that are exported as well and might override project params at import time : ', used_project_params) proj_params = list(ProjectParameter.get(ProjectParameter.name==name) for name in used_project_params) db.metadata["project_parameters"] = [param_data(param) for param in proj_params] BW2Package._write_file(filename, [BW2Package._prepare_obj(db, False)])
def test_database_delete_parameters(): db = DatabaseChooser("example") db.register() a = db.new_activity(code="A", name="An activity") a.save() b = db.new_activity(code="B", name="Another activity") b.save() a.new_exchange( amount=0, input=b, type="technosphere", formula="foo * bar + 4" ).save() database_data = [ {"name": "red", "formula": "(blue ** 2) / 5",}, {"name": "blue", "amount": 12}, ] parameters.new_database_parameters(database_data, "example") activity_data = [ { "name": "reference_me", "formula": "sqrt(red - 20)", "database": "example", "code": "B", }, { "name": "bar", "formula": "reference_me + 2", "database": "example", "code": "A", }, ] parameters.new_activity_parameters(activity_data, "my group") parameters.add_exchanges_to_group("my group", a) assert ActivityParameter.select().count() == 2 assert ParameterizedExchange.select().count() == 1 assert DatabaseParameter.select().count() == 2 assert len(parameters) == 4 del databases["example"] assert not len(parameters) assert not ParameterizedExchange.select().count()
def test_database_delete_parameters(): db = DatabaseChooser("example") db.register() a = db.new_activity(code="A", name="An activity") a.save() b = db.new_activity(code="B", name="Another activity") b.save() a.new_exchange(amount=0, input=b, type="technosphere", formula="foo * bar + 4").save() database_data = [{ 'name': 'red', 'formula': '(blue ** 2) / 5', }, { 'name': 'blue', 'amount': 12 }] parameters.new_database_parameters(database_data, "example") activity_data = [{ 'name': 'reference_me', 'formula': 'sqrt(red - 20)', 'database': 'example', 'code': "B", }, { 'name': 'bar', 'formula': 'reference_me + 2', 'database': 'example', 'code': "A", }] parameters.new_activity_parameters(activity_data, "my group") parameters.add_exchanges_to_group("my group", a) assert ActivityParameter.select().count() == 2 assert ParameterizedExchange.select().count() == 1 assert DatabaseParameter.select().count() == 2 assert len(parameters) == 4 del databases['example'] assert not len(parameters) assert not ParameterizedExchange.select().count()
def sync(self) -> None: self.data.update({ "project": ProjectParameter.select().iterator(), "database": DatabaseParameter.select().iterator(), "activity": ActivityParameter.select().iterator(), })
def loadParams(global_variable=True, dbname=None): """ Load parameters from Brightway database, as per : https://stats-arrays.readthedocs.io/en/latest/ Parameters ---------- global_variable If true, loaded parameters are made available as global variable. dbname : None. By default load all project and database parameters. If provided, only load DB params """ enumParams = defaultdict(lambda: dict()) def register(param): _param_registry()[param.name] = param # Make it available as global var if global_variable: if param.name in builtins.__dict__: error( "Variable '%s' was already defined : overidding it with param." % param.name) builtins.__dict__[param.name] = param select = DatabaseParameter.select() if dbname: select = select.where(DatabaseParameter.database == dbname) params = list(select) if not dbname: params += list(ProjectParameter.select()) for bwParam in params: data = bwParam.data data["amount"] = bwParam.amount name = bwParam.name type = data.get(UNCERTAINTY_TYPE, None) # print("Data for ", name, data) # Common extra args args = _loadArgs(data) if type == _UncertaintyType.DISCRETE: # Boolean or enum if data.get('scale') is not None: # Enum param : group them by common prefix splits = name.split("_") enum_value = splits.pop() enum_name = "_".join(splits) enumParams[enum_name][enum_value] = data continue elif data["maximum"] == 2: del args["max"], args["min"] param = newBoolParam(name, save=False, **args) else: error( "Non boolean discrete values (max != 2) are not supported for param :", name) continue else: # Float parameter if type is None: error( "'Uncertainty type' of param %s not provided. Assuming UNIFORM" ) type = _UncertaintyType.UNIFORM # Uncertainty type to distribution type args["distrib"] = _DistributionTypeMapReverse[type] if type == _UncertaintyType.TRIANGLE: args["default"] = data["loc"] elif type in [_UncertaintyType.NORMAL, _UncertaintyType.LOGNORMAL]: args["default"] = data["loc"] args["std"] = data["scale"] elif type == _UncertaintyType.BETA: args["default"] = data["loc"] args["std"] = data["scale"] args["a"] = data["loc"] args["b"] = data["shape"] param = newFloatParam(name, save=False, **args) # Save it in shared dictionnary register(param) # Loop on EnumParams for param_name, param_values in enumParams.items(): first_enum_param = list(param_values.values())[0] args = _loadArgs(first_enum_param) del args["default"] # Dictionary of enum values with scale as weight args["values"] = { key: data["scale"] for key, data in param_values.items() } # Default enum value is the one with amount=1 defaults = list(key for key, data in param_values.items() if data.get("amount") == 1) if len(defaults) == 1: default = defaults[0] else: default = None error("No default enum value found for ", param_name, defaults) param = newEnumParam(param_name, default, save=False, **args) # Save it in shared dict register(param)
def sync(self) -> None: data = [self.parse_parameter(p) for p in DatabaseParameter.select()] self._dataframe = pd.DataFrame(data, columns=self.columns()) self.db_col = self._dataframe.columns.get_loc("database") self.param_col = self._dataframe.columns.get_loc("parameter") self.updated.emit()