def test_delete_parameterized_exchange():
    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()
    exc = a.new_exchange(amount=0, input=b, type="technosphere", formula="foo * bar + 4")
    exc.save()

    activity_data = [{
        'name': 'reference_me',
        'formula': 'sqrt(25)',
        '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

    exc.delete()
    assert ActivityParameter.select().count() == 2
    assert not ParameterizedExchange.select().count()
Esempio n. 2
0
def resetParams(db_name):
    """Reset project and activity parameters"""
    _param_registry().clear()
    ProjectParameter.delete().execute()
    ActivityParameter.delete().execute()
    DatabaseParameter.delete().execute()
    Group.delete().execute()
Esempio n. 3
0
def test_delete_activity_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()

    activity_data = [
        {
            "name": "reference_me",
            "formula": "sqrt(25)",
            "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

    a.delete()
    assert ActivityParameter.select().count() == 1
    assert not ParameterizedExchange.select().count()
Esempio n. 4
0
    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)
Esempio n. 5
0
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
Esempio n. 6
0
    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()
Esempio n. 7
0
    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()
Esempio n. 8
0
 def recalculate_exchanges():
     """ Will iterate through all activity parameters and rerun the
     formula interpretation for all exchanges.
     """
     for param in ActivityParameter.select().iterator():
         act = bw.get_activity((param.database, param.code))
         bw.parameters.add_exchanges_to_group(param.group, act)
         ActivityParameter.recalculate_exchanges(param.group)
     signals.parameters_changed.emit()
Esempio n. 9
0
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
Esempio n. 10
0
 def get_activity_parameters(self, act):
     data = [
         o.dict
         for o in ActivityParameter.select().where(
             ActivityParameter.database == act[0], ActivityParameter.code == act[1],
         )
     ]
     if not data:
         return {}
     dct = self.order_dicts(data, "parameter")
     dct["group"] = ActivityParameter.get(database=act[0], code=act[1],).group
     return dct
Esempio n. 11
0
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)
Esempio n. 12
0
    def parameterize_exchanges(self, key: tuple) -> None:
        """ Used whenever a formula is set on an exchange in an activity.

        If no `ActivityParameter` exists for the key, generate one immediately
        """
        if ActivityParameter.get_or_none(database=key[0], code=key[1]) is None:
            signals.add_activity_parameter.emit(key)

        param = ActivityParameter.get(database=key[0], code=key[1])
        act = bw.get_activity(key)
        bw.parameters.remove_exchanges_from_group(param.group, act)
        bw.parameters.add_exchanges_to_group(param.group, act)
        ActivityParameter.recalculate_exchanges(param.group)
        signals.parameters_changed.emit()
Esempio n. 13
0
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()
Esempio n. 14
0
def test_create_activity_param(qtbot):
    """ Create several activity parameters.

    TODO: Figure out some way of performing a drag action between tables.
     Use method calls for now.
     Until the above is implemented, take shortcuts and don't check db validity
    """
    project_db_tab = ParameterDefinitionTab()
    qtbot.addWidget(project_db_tab)
    project_db_tab.build_tables()
    table = project_db_tab.activity_table

    # Open the order column just because we can
    col = table.COLUMNS.index("order")
    assert table.isColumnHidden(col)
    with qtbot.waitSignal(project_db_tab.show_order.stateChanged, timeout=1000):
        qtbot.mouseClick(project_db_tab.show_order, QtCore.Qt.LeftButton)
    assert not table.isColumnHidden(col)

    # Create multiple parameters for a single activity
    act_key = ("testdb", "act1")
    for _ in range(3):
        table.add_parameter(act_key)

    # Test created parameters
    assert ActivityParameter.select().count() == 3
    # First of the multiple parameters
    assert table.proxy_model.index(0, 0).data() == "act_1"
    # Second of the multiple parameters
    assert table.proxy_model.index(1, 0).data() == "act_2"
    # The group name for the `testdb` parameters is the same.
    loc = table.visualRect(table.proxy_model.index(0, 0))
    qtbot.mouseClick(table.viewport(), QtCore.Qt.LeftButton, pos=loc.center())
    group = table.get_current_group()
    assert table.proxy_model.index(2, table.COLUMNS.index("group")).data() == group
Esempio n. 15
0
 def get_interpreter(self) -> Interpreter:
     """ Use the activity key to determine which symbols are added
     to the formula interpreter.
     """
     interpreter = Interpreter()
     act = ActivityParameter.get_or_none(database=self.key[0],
                                         code=self.key[1])
     if act:
         interpreter.symtable.update(
             ActivityParameter.static(act.group, full=True))
     else:
         print("No parameter found for {}, creating one on formula save".
               format(self.key))
         interpreter.symtable.update(ProjectParameter.static())
         interpreter.symtable.update(DatabaseParameter.static(self.key[0]))
     return interpreter
Esempio n. 16
0
    def parameterize_exchanges(self, key: tuple) -> None:
        """ Used whenever a formula is set on an exchange in an activity.

        If no `ActivityParameter` exists for the key, generate one immediately
        """
        group = bc.build_activity_group_name(key)
        if not (ActivityParameter.select()
                .where(ActivityParameter.group == group).count()):
            ActivityParameterTable.add_parameter(key)

        act = bw.get_activity(key)
        with bw.parameters.db.atomic():
            bw.parameters.remove_exchanges_from_group(group, act)
            bw.parameters.add_exchanges_to_group(group, act)
            ActivityParameter.recalculate_exchanges(group)
        signals.parameters_changed.emit()
Esempio n. 17
0
 def delete_activity(self, key):
     act = bw.get_activity(key)
     nu = len(act.upstream())
     if nu:
         text = "activities consume" if nu > 1 else "activity consumes"
         QtWidgets.QMessageBox.information(
             None,
             "Not possible.",
             """Can't delete {}. {} upstream {} its reference product.
             Upstream exchanges must be modified or deleted.""".format(act, nu, text)
         )
     else:
         # Check if the activity is parameterized:
         query = ActivityParameter.select().where(
             ActivityParameter.database == act[0],
             ActivityParameter.code == act[1]
         )
         if query.exists():
             # Remove all activity parameters
             Controller.delete_activity_parameter(act.key)
         act.delete()
         bw.databases.set_modified(act["database"])
         signals.metadata_changed.emit(act.key)
         signals.database_changed.emit(act["database"])
         signals.databases_changed.emit()
         signals.calculation_setup_changed.emit()
Esempio n. 18
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()]
Esempio n. 19
0
    def recalculate_activity_parameters(self,
                                        group: str,
                                        global_params: dict = None
                                        ) -> Optional[dict]:
        new_values = self.get_altered_values(group)
        if global_params is None:
            global_params = {}

        data = ActivityParameter.load(group)
        if not data:
            return

        for name, amount in new_values.items():
            data[name]["amount"] = amount

        new_symbols = get_new_symbols(data.values(), set(data))
        missing = new_symbols.difference(global_params)
        if missing:
            raise MissingName(
                "The following variables aren't defined:\n{}".format(
                    "|".join(missing)))

        glo = self._static(global_params,
                           needed=new_symbols) if new_symbols else None

        ParameterSet(data, glo).evaluate_and_set_amount_field()
        return self._prune_result_data(data)
Esempio n. 20
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()))
Esempio n. 21
0
def test_edit_activity_param(qtbot):
    """ Alter names, amounts and formulas.

    Introduce dependencies through formulas
    """
    table = ActivityParameterTable()
    qtbot.addWidget(table)
    table.sync(table.build_df())

    # Fill rows with new variables
    table.rename_parameter(table.proxy_model.index(0, 0), "edit_act_1", True)
    table.model.setData(table.model.index(0, 2), "test_db3 * 3")
    table.rename_parameter(table.proxy_model.index(1, 0), "edit_act_2", True)
    table.model.setData(table.model.index(1, 2), "edit_act_1 - 3")

    # Test updated values
    assert ActivityParameter.get(name="edit_act_1").amount == 25.5
    assert ActivityParameter.get(name="edit_act_2").amount == 22.5
Esempio n. 22
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)
Esempio n. 23
0
 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()
Esempio n. 24
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
Esempio n. 25
0
 def get_activity_groups(self, proxy, ignore_groups: list = None):
     """ Helper method to look into the Group and determine which if any
     other groups the current activity can depend on
     """
     db = self.get_key(proxy)[0]
     ignore_groups = [] if ignore_groups is None else ignore_groups
     return (param.group for param in (
         ActivityParameter.select(ActivityParameter.group).where(
             ActivityParameter.database == db).distinct())
             if param.group not in ignore_groups)
Esempio n. 26
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()),
     ))
Esempio n. 27
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()
Esempio n. 28
0
    def get_usable_parameters():
        """ Include all types of parameters.

        NOTE: This method does not take into account which formula is being
        edited, and therefore does not restrict which database or activity
        parameters are returned.
        """
        database = DataBaseParameterTable.get_usable_parameters()
        activity = ([p.name, p.amount, "activity ({})".format(p.group)]
                    for p in ActivityParameter.select())
        return itertools.chain(database, activity)
Esempio n. 29
0
 def delete_activity_parameter(key: tuple) -> None:
     """Remove all activity parameters and underlying exchange parameters
     for the given key.
     """
     query = ActivityParameter.select(ActivityParameter.group).where(
         ActivityParameter.database == key[0],
         ActivityParameter.code == key[1],
     )
     for p in query.iterator():
         bw.parameters.remove_from_group(p.group, key)
     bw.parameters.recalculate()
     signals.parameters_changed.emit()
Esempio n. 30
0
 def parse_parameter(cls, parameter) -> dict:
     """ Override the base method to add more steps.
     """
     row = super().parse_parameter(parameter)
     # Combine the 'database' and 'code' fields of the parameter into a 'key'
     row["key"] = (parameter.database, parameter.code)
     act = bw.get_activity(row["key"])
     row["product"] = act.get("reference product") or act.get("name")
     row["activity"] = act.get("name")
     row["location"] = act.get("location", "unknown")
     # Replace the namedtuple with the actual ActivityParameter
     row["parameter"] = ActivityParameter.get_by_id(parameter.id)
     return row