diff --git a/soundcard_input.py b/soundcard_input.py index 81d3289..5e731d9 100644 --- a/soundcard_input.py +++ b/soundcard_input.py @@ -727,11 +727,6 @@ class LevelMonitorGUI: self.winisd_max_power_var = tk.StringVar(value=str(args.winisd_max_power or WINISD_MAX_POWER_FILE)) self.headroom_smoothing_var = tk.StringVar(value=f"{args.headroom_smoothing_alpha:g}") self.winisd_status_var = tk.StringVar(value="WinISD headroom uses per-bin P/Pmax for LF.") - self.show_waveform_plot_var = tk.BooleanVar(value=True) - self.show_psd_plot_var = tk.BooleanVar(value=True) - self.show_power_history_plot_var = tk.BooleanVar(value=True) - self.show_power_limit_plot_var = tk.BooleanVar(value=True) - self.show_headroom_plot_var = tk.BooleanVar(value=True) self.lf_enabled_var = tk.BooleanVar(value=True) self.lf_channel_var = tk.StringVar(value="1") self.lf_impedance_var = tk.StringVar(value="impedance.txt" if Path("impedance.txt").exists() else "") @@ -909,33 +904,13 @@ class LevelMonitorGUI: plots_frame = ttk.LabelFrame(outer, text="Plot viewer", padding=10) plots_frame.pack(fill="both", expand=True, pady=(12, 0)) plots_frame.columnconfigure(0, weight=1) - plots_frame.rowconfigure(1, weight=1) + plots_frame.rowconfigure(0, weight=1) - plot_selector = ttk.Frame(plots_frame) - plot_selector.grid(row=0, column=0, sticky="ew", pady=(0, 8)) - plot_options = ( - ("Waveform", self.show_waveform_plot_var), - ("Input PSD", self.show_psd_plot_var), - ("Power history", self.show_power_history_plot_var), - ("P vs WinISD", self.show_power_limit_plot_var), - ("Headroom", self.show_headroom_plot_var), - ) - for col, (label, variable) in enumerate(plot_options): - ttk.Checkbutton( - plot_selector, - text=label, - variable=variable, - command=self._layout_plot_tiles, - ).grid(row=0, column=col, sticky="w", padx=(0, 16)) + self.plot_tabs = ttk.Notebook(plots_frame) + self.plot_tabs.grid(row=0, column=0, sticky="nsew") + self.plot_tabs.bind("<>", lambda _event: self._redraw_active_plot()) - self.plot_area = ttk.Frame(plots_frame) - self.plot_area.grid(row=1, column=0, sticky="nsew") - self.plot_area.columnconfigure(0, weight=1) - self.plot_area.columnconfigure(1, weight=1) - for row in range(3): - self.plot_area.rowconfigure(row, weight=1) - - self.scope_frame = ttk.LabelFrame(self.plot_area, text="Input waveform, calibrated voltage", padding=10) + self.scope_frame = ttk.Frame(self.plot_tabs, padding=10) self.scope_frame.rowconfigure(0, weight=1) self.scope_frame.columnconfigure(0, weight=1) @@ -961,8 +936,9 @@ class LevelMonitorGUI: self.waveform_y_limit_var.trace_add("write", lambda *_args: self.draw_scope_grid()) self.scope_canvas.bind("", lambda _event: self.draw_scope_grid()) self.draw_scope_grid() + self.plot_tabs.add(self.scope_frame, text="Waveform") - self.spectrum_frame = ttk.LabelFrame(self.plot_area, text="Input PSD, Welch scaled", padding=10) + self.spectrum_frame = ttk.Frame(self.plot_tabs, padding=10) self.spectrum_frame.rowconfigure(0, weight=1) self.spectrum_frame.columnconfigure(0, weight=1) self.spectrum_canvas = self.tk.Canvas( @@ -978,8 +954,9 @@ class LevelMonitorGUI: ) self.spectrum_canvas.bind("", lambda _event: self.draw_spectrum_grid()) self.draw_spectrum_grid() + self.plot_tabs.add(self.spectrum_frame, text="Input PSD") - self.power_history_frame = ttk.LabelFrame(self.plot_area, text="Output power history", padding=10) + self.power_history_frame = ttk.Frame(self.plot_tabs, padding=10) self.power_history_frame.rowconfigure(0, weight=1) self.power_history_frame.columnconfigure(0, weight=1) self.power_history_canvas = self.tk.Canvas( @@ -1004,8 +981,9 @@ class LevelMonitorGUI: self.power_history_window_var.trace_add("write", lambda *_args: self.draw_power_history()) self.power_history_canvas.bind("", lambda _event: self.draw_power_history_grid()) self.draw_power_history_grid() + self.plot_tabs.add(self.power_history_frame, text="Power history") - self.power_limit_frame = ttk.LabelFrame(self.plot_area, text="Power Spectrum vs WinISD Limit", padding=10) + self.power_limit_frame = ttk.Frame(self.plot_tabs, padding=10) self.power_limit_frame.rowconfigure(0, weight=1) self.power_limit_frame.columnconfigure(0, weight=1) self.power_limit_canvas = self.tk.Canvas( @@ -1021,8 +999,9 @@ class LevelMonitorGUI: ) self.power_limit_canvas.bind("", lambda _event: self.draw_power_limit_grid()) self.draw_power_limit_grid() + self.plot_tabs.add(self.power_limit_frame, text="P vs WinISD") - self.headroom_frame = ttk.LabelFrame(self.plot_area, text="WinISD Headroom", padding=10) + self.headroom_frame = ttk.Frame(self.plot_tabs, padding=10) self.headroom_frame.rowconfigure(0, weight=1) self.headroom_frame.columnconfigure(0, weight=1) self.headroom_canvas = self.tk.Canvas( @@ -1038,7 +1017,7 @@ class LevelMonitorGUI: ) self.headroom_canvas.bind("", lambda _event: self.draw_headroom_grid()) self.draw_headroom_grid() - self._layout_plot_tiles() + self.plot_tabs.add(self.headroom_frame, text="Headroom") def _build_power_config_row( self, @@ -1091,37 +1070,21 @@ class LevelMonitorGUI: vars_by_metric["light_id"] = light_id self.power_rows[name] = vars_by_metric - def _layout_plot_tiles(self) -> None: - plot_specs = ( - (self.scope_frame, self.show_waveform_plot_var, self.draw_scope_grid), - (self.spectrum_frame, self.show_psd_plot_var, self.draw_spectrum_grid), - (self.power_history_frame, self.show_power_history_plot_var, self.draw_power_history_grid), - (self.power_limit_frame, self.show_power_limit_plot_var, self.draw_power_limit_grid), - (self.headroom_frame, self.show_headroom_plot_var, self.draw_headroom_grid), - ) - active = [(frame, redraw) for frame, variable, redraw in plot_specs if variable.get()] - for frame, _variable, _redraw in plot_specs: - frame.grid_forget() - - for idx, (frame, redraw) in enumerate(active): - row = idx // 2 - col = idx % 2 - frame.grid( - row=row, - column=col, - sticky="nsew", - padx=(0, 6) if col == 0 else (6, 0), - pady=(0, 12), - ) - redraw() - - if self.show_psd_plot_var.get(): + def _redraw_active_plot(self) -> None: + selected = self.plot_tabs.select() + if selected == str(self.scope_frame): + self.draw_scope_grid() + elif selected == str(self.spectrum_frame): + self.draw_spectrum_grid() self.draw_spectrum() - if self.show_power_history_plot_var.get(): + elif selected == str(self.power_history_frame): + self.draw_power_history_grid() self.draw_power_history() - if self.show_power_limit_plot_var.get(): + elif selected == str(self.power_limit_frame): + self.draw_power_limit_grid() self.draw_power_limit() - if self.show_headroom_plot_var.get(): + elif selected == str(self.headroom_frame): + self.draw_headroom_grid() self.draw_headroom() def _select_initial_device(self, requested_index: int | None) -> None: