From 075f34ee9b59ebdecf04d57fabd2f1415ae72cfc Mon Sep 17 00:00:00 2001 From: Marin Visscher <103424764+mrvisscher@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:11:24 +0100 Subject: [PATCH] Parameter Scenario fixes (#1420) * Fix deprecation warning * Fix unordered parameter scenario parsing * Parameter scenarios now sample on both parameter group and parameter name --- activity_browser/bwutils/manager.py | 6 +++--- .../bwutils/superstructure/dataframe.py | 4 ++-- activity_browser/bwutils/utils.py | 16 +++++++++++----- activity_browser/ui/tables/models/scenarios.py | 8 ++++++-- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/activity_browser/bwutils/manager.py b/activity_browser/bwutils/manager.py index d7b87a70c..98294b7a8 100644 --- a/activity_browser/bwutils/manager.py +++ b/activity_browser/bwutils/manager.py @@ -164,7 +164,7 @@ def calculate(self) -> np.ndarray: return data @abstractmethod - def recalculate(self, values: List[float]) -> np.ndarray: + def recalculate(self, values: dict[str, float]) -> np.ndarray: """Convenience function that takes the given new values and recalculates. Returning a fully-formed set of exchange amounts and indices. @@ -174,7 +174,7 @@ def recalculate(self, values: List[float]) -> np.ndarray: self.parameters.update(values) return self.calculate() - def ps_recalculate(self, values: List[float]) -> np.ndarray: + def ps_recalculate(self, values: dict[str, float]) -> np.ndarray: """Used to recalculate brightway parameters without editing the database. Leftover from Presamples. @@ -206,7 +206,7 @@ def arrays_from_scenarios(self, scenarios) -> (np.ndarray, np.ndarray): Side-note on presamples: Presamples was used in AB for calculating scenarios, presamples was superseded by this implementation. For more reading: https://presamples.readthedocs.io/en/latest/index.html""" - sample_data = [self.ps_recalculate(list(values)) for _, values in scenarios] + sample_data = [self.ps_recalculate(values.to_dict()) for _, values in scenarios] samples = np.concatenate(sample_data, axis=1) indices = self.reformat_indices() return samples, indices diff --git a/activity_browser/bwutils/superstructure/dataframe.py b/activity_browser/bwutils/superstructure/dataframe.py index 044c8b305..e165f1208 100644 --- a/activity_browser/bwutils/superstructure/dataframe.py +++ b/activity_browser/bwutils/superstructure/dataframe.py @@ -154,9 +154,9 @@ def exchange_replace_database( [["from key", "from database"], ["to key", "to database"]][i] ): ds_.loc[col] = ( - (key["database"][0], key["code"][0]) + (key["database"].iloc[0], key["code"].iloc[0]) if j == 0 - else key["database"][0] + else key["database"].iloc[0] ) except Exception as e: # if the record cannot be found add an exception (to a maximum of five) diff --git a/activity_browser/bwutils/utils.py b/activity_browser/bwutils/utils.py index 765315e61..d96169fee 100644 --- a/activity_browser/bwutils/utils.py +++ b/activity_browser/bwutils/utils.py @@ -159,14 +159,20 @@ def static(data: dict, needed: set) -> dict: """ return {k: data[k] for k in data.keys() & needed} - def update(self, values: Iterable[float]) -> None: + def update(self, new_values: dict[str, float]) -> None: """Replace parameters in the list if their linked value is not NaN. """ - assert len(values) == len(self.data) - for i, (p, v) in enumerate(zip(self.data, values)): - if not np.isnan(v): - self.data[i] = p._replace(amount=v) + param_by_name = {(p.group, p.name): p for p in self.data} + index_by_name = {(p.group, p.name): i for i, p in enumerate(self.data)} + + for name, value in new_values.items(): + if not np.isnan(value): + self.data[index_by_name[name]] = param_by_name[name]._replace(amount=value) + return + # for i, (p, v) in enumerate(zip(self.data, values)): + # if not np.isnan(v): + # self.data[i] = p._replace(amount=v) def to_gsa(self) -> List[tuple]: """Formats all of the parameters in the list for handling in a GSA.""" diff --git a/activity_browser/ui/tables/models/scenarios.py b/activity_browser/ui/tables/models/scenarios.py index b68bac909..ff733d747 100644 --- a/activity_browser/ui/tables/models/scenarios.py +++ b/activity_browser/ui/tables/models/scenarios.py @@ -124,7 +124,11 @@ def iterate_scenarios(self) -> Iterable[Tuple[str, Iterable]]: TODO: Fix this so it returns the least amount of required information. """ + df = self._dataframe.reset_index() + df = df.set_index(["Group", "Name"]) + + return ( - (scenario, self._dataframe[scenario]) - for scenario in self._dataframe.columns[1:] + (scenario, df[scenario]) + for scenario in df.columns )