diff --git a/src/petab_gui/controllers/mother_controller.py b/src/petab_gui/controllers/mother_controller.py index 19d82eb..e118eb0 100644 --- a/src/petab_gui/controllers/mother_controller.py +++ b/src/petab_gui/controllers/mother_controller.py @@ -877,6 +877,7 @@ def init_plotter(self): self.measurement_controller.proxy_model, self.simulation_controller.proxy_model, self.condition_controller.proxy_model, + self.visualization_controller.proxy_model ) self.plotter = self.view.plot_dock self.plotter.highlighter.click_callback = self._on_plot_point_clicked diff --git a/src/petab_gui/views/simple_plot_view.py b/src/petab_gui/views/simple_plot_view.py index 61fa0f7..7bdd4b3 100644 --- a/src/petab_gui/views/simple_plot_view.py +++ b/src/petab_gui/views/simple_plot_view.py @@ -43,9 +43,11 @@ def run(self): sim_df = self.sim_df.copy() if sim_df.empty: sim_df = None - - try: - if self.vis_df is not None: + if self.group_by == "vis_df" and self.vis_df.empty: + print("Empty Vis DF. Falling back to grouping by observable.") + self.group_by = "observable" + if self.group_by == "vis_df": + try: petab_vis.plot_with_vis_spec( self.vis_df, self.cond_df, @@ -55,8 +57,11 @@ def run(self): fig = plt.gcf() self.signals.finished.emit(fig) return - except Exception as e: - print(f"Invalid Visualisation DF: {e}") + except Exception as e: + print(f"Invalid Visualisation DF: {e}") + plt.gcf() + self.signals.finished.emit(fig) + return # Fallback plt.close("all") @@ -100,11 +105,11 @@ def __init__(self, parent=None): self.update_timer.timeout.connect(self.plot_it) self.observable_to_subplot = {} - def initialize(self, meas_proxy, sim_proxy, cond_proxy): + def initialize(self, meas_proxy, sim_proxy, cond_proxy, vis_proxy): self.meas_proxy = meas_proxy self.cond_proxy = cond_proxy self.sim_proxy = sim_proxy - self.vis_df = None + self.vis_proxy = vis_proxy # Connect data changes self.options_manager.option_changed.connect(self._debounced_plot) @@ -117,6 +122,9 @@ def initialize(self, meas_proxy, sim_proxy, cond_proxy): self.sim_proxy.dataChanged.connect(self._debounced_plot) self.sim_proxy.rowsInserted.connect(self._debounced_plot) self.sim_proxy.rowsRemoved.connect(self._debounced_plot) + self.vis_proxy.dataChanged.connect(self._debounced_plot) + self.vis_proxy.rowsInserted.connect(self._debounced_plot) + self.vis_proxy.rowsRemoved.connect(self._debounced_plot) self.plot_it() @@ -127,13 +135,14 @@ def plot_it(self): measurements_df = proxy_to_dataframe(self.meas_proxy) simulations_df = proxy_to_dataframe(self.sim_proxy) conditions_df = proxy_to_dataframe(self.cond_proxy) + visualisation_df = proxy_to_dataframe(self.vis_proxy) group_by = self.options_manager.get_option() # group_by different value in petab.visualize if group_by == "condition": group_by = "simulation" worker = PlotWorker( - self.vis_df, + visualisation_df, conditions_df, measurements_df, simulations_df, @@ -375,6 +384,9 @@ def __init__(self, canvas, parent): grp: QAction(f"Groupy by {grp}", self) for grp in ["observable", "dataset", "condition"] } + self.groupy_by_options["vis_df"] = QAction( + "Use Visualization DF", self + ) for grp, action in self.groupy_by_options.items(): action.setCheckable(True) action.triggered.connect(lambda _, grp=grp: self.manager.set_option(grp)) diff --git a/src/petab_gui/views/utils.py b/src/petab_gui/views/utils.py index 66a4549..bd4a99e 100644 --- a/src/petab_gui/views/utils.py +++ b/src/petab_gui/views/utils.py @@ -36,5 +36,11 @@ def proxy_to_dataframe(proxy_model): data = pd.DataFrame(data) data["simulation"] = data["simulation"].astype(float) data["time"] = data["time"].astype(float) + elif proxy_model.source_model.table_type == "visualization": + data = pd.DataFrame(data) + data["xOffset"] = data["xOffset"].astype(float) + data["yOffset"] = data["yOffset"].astype(float) + else: + data = pd.DataFrame(data) return data