예제 #1
0
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
예제 #2
0
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
예제 #3
0
 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)
예제 #4
0
 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")
예제 #5
0
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()))
예제 #6
0
 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
예제 #7
0
 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)
예제 #8
0
    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
예제 #9
0
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
예제 #10
0
 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()),
     ))
예제 #11
0
 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()
예제 #12
0
 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))
예제 #13
0
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
예제 #14
0
    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))
예제 #15
0
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
예제 #16
0
 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()]
예제 #17
0
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)])
예제 #18
0
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()
예제 #19
0
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()
예제 #20
0
 def sync(self) -> None:
     self.data.update({
         "project": ProjectParameter.select().iterator(),
         "database": DatabaseParameter.select().iterator(),
         "activity": ActivityParameter.select().iterator(),
     })
예제 #21
0
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)
예제 #22
0
 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()