From 5dd5dd87b199910f4cfa949ef3afb00aad23c118 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 8 Sep 2026 15:04:37 +0200 Subject: [PATCH 1/4] feat: extend scatter range behavior --- spikeinterface_gui/amplitudescalingsview.py | 9 +++++++++ spikeinterface_gui/basescatterview.py | 10 +++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/spikeinterface_gui/amplitudescalingsview.py b/spikeinterface_gui/amplitudescalingsview.py index 2c71633d..275200f4 100644 --- a/spikeinterface_gui/amplitudescalingsview.py +++ b/spikeinterface_gui/amplitudescalingsview.py @@ -9,6 +9,15 @@ def __init__(self, controller=None, parent=None, backend="qt"): y_label = "Amplitude scaling" spike_data = controller.amplitude_scalings + # Overwrite "range_type", "range_min", and "range_max"so that default range is 0 - 2 + for setting in AmplitudeScalingsView._settings: + if setting['name'] == 'range_type': + setting['value'] = 'absolute' + elif setting['name'] == 'range_min': + setting['value'] = 0.0 + elif setting['name'] == 'range_max': + setting['value'] = 2.0 + BaseScatterView.__init__( self, controller=controller, diff --git a/spikeinterface_gui/basescatterview.py b/spikeinterface_gui/basescatterview.py index 5ba831b8..f5fff0ef 100644 --- a/spikeinterface_gui/basescatterview.py +++ b/spikeinterface_gui/basescatterview.py @@ -14,8 +14,9 @@ class BaseScatterView(ViewBase): {'name': 'alpha', 'type': 'float', 'value' : 0.7, 'limits':(0, 1.), 'step':0.05}, {'name': 'scatter_size', 'type': 'float', 'value' : 2., 'step':0.5}, {'name': 'num_bins', 'type': 'int', 'value' : 30, 'step': 1}, - {'name': 'display_low_percentiles', 'type': 'float', 'value' : 2.0, 'limits':(0, 50), 'step':0.5}, - {'name': 'display_high_percentiles', 'type': 'float', 'value' : 98.0, 'limits':(50, 100), 'step':0.5}, + {'name': 'range_type', 'type': 'list', 'limits': ['percentiles', 'absolute']}, + {'name': 'range_min', 'type': 'float', 'value' : 1.0}, + {'name': 'range_max', 'type': 'float', 'value' : 99.0}, ] _need_compute = False @@ -56,7 +57,10 @@ def get_unit_data(self, unit_id, segment_index=0): return spike_times, spike_data, np.array([1]), np.array([ymin, ymax]), ymin, ymax, inds # avoid clear outliers in the plot and histogram by using percentiles - ymin, ymax = np.percentile(spike_data, [self.settings['display_low_percentiles'], self.settings['display_high_percentiles']]) + if self.settings['range_type'] == 'percentiles': + ymin, ymax = np.percentile(spike_data, [self.settings['range_min'], self.settings['range_max']]) + else: + ymin, ymax = self.settings['range_min'], self.settings['range_max'] min_bin_size = np.min(np.diff(np.unique(spike_data))) bins = np.linspace(ymin, ymax, self.settings['num_bins']) # if bins are too small, adjust the number of bins to ensure a minimum bin size and avoid jumps in the histogram From 996a8ebecaf32a7bfe1494c2c0798fd6e41adcf4 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 8 Sep 2026 15:08:18 +0200 Subject: [PATCH 2/4] feat: add checks on limits --- spikeinterface_gui/basescatterview.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spikeinterface_gui/basescatterview.py b/spikeinterface_gui/basescatterview.py index f5fff0ef..303d7c4a 100644 --- a/spikeinterface_gui/basescatterview.py +++ b/spikeinterface_gui/basescatterview.py @@ -1,3 +1,4 @@ +import warnings import numpy as np from matplotlib.path import Path as mpl_path @@ -58,6 +59,15 @@ def get_unit_data(self, unit_id, segment_index=0): # avoid clear outliers in the plot and histogram by using percentiles if self.settings['range_type'] == 'percentiles': + if self.settings["range_min"] < 0: + warnings.warn("range_min cannot be less than 0. Setting it to 0.") + self.settings["range_min"] = 0.0 + if self.settings["range_max"] > 100: + warnings.warn("range_max cannot be greater than 100. Setting it to 100.") + self.settings["range_max"] = 100.0 + if self.settings["range_min"] > self.settings["range_max"]: + warnings.warn("range_min cannot be greater than range_max. Setting range_min to range_max.") + self.settings["range_min"] = self.settings["range_max"] - 1 ymin, ymax = np.percentile(spike_data, [self.settings['range_min'], self.settings['range_max']]) else: ymin, ymax = self.settings['range_min'], self.settings['range_max'] From f069d7f4b6bdbb482c5b1f8c1c343692083b7515 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 8 Sep 2026 15:09:05 +0200 Subject: [PATCH 3/4] feat: add checks on limits 2 --- spikeinterface_gui/basescatterview.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spikeinterface_gui/basescatterview.py b/spikeinterface_gui/basescatterview.py index 303d7c4a..4733ce98 100644 --- a/spikeinterface_gui/basescatterview.py +++ b/spikeinterface_gui/basescatterview.py @@ -66,10 +66,13 @@ def get_unit_data(self, unit_id, segment_index=0): warnings.warn("range_max cannot be greater than 100. Setting it to 100.") self.settings["range_max"] = 100.0 if self.settings["range_min"] > self.settings["range_max"]: - warnings.warn("range_min cannot be greater than range_max. Setting range_min to range_max.") + warnings.warn("range_min cannot be greater than range_max. Setting range_min to range_max - 1.") self.settings["range_min"] = self.settings["range_max"] - 1 ymin, ymax = np.percentile(spike_data, [self.settings['range_min'], self.settings['range_max']]) else: + if self.settings["range_min"] > self.settings["range_max"]: + warnings.warn("range_min cannot be greater than range_max. Setting range_min to range_max - 1.") + self.settings["range_min"] = self.settings["range_max"] - 1 ymin, ymax = self.settings['range_min'], self.settings['range_max'] min_bin_size = np.min(np.diff(np.unique(spike_data))) bins = np.linspace(ymin, ymax, self.settings['num_bins']) From a59b6ebd6f30948ee024d77f2e4dbe4f11c5937b Mon Sep 17 00:00:00 2001 From: chrishalcrow Date: Tue, 8 Sep 2026 14:30:04 +0100 Subject: [PATCH 4/4] Turn missing settings into warnings instead of errors --- spikeinterface_gui/backend_panel.py | 9 ++++++--- spikeinterface_gui/backend_qt.py | 11 +++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/spikeinterface_gui/backend_panel.py b/spikeinterface_gui/backend_panel.py index 9abeaa61..63cd6520 100644 --- a/spikeinterface_gui/backend_panel.py +++ b/spikeinterface_gui/backend_panel.py @@ -1,3 +1,5 @@ +import warnings + import param import panel as pn import numpy as np @@ -248,9 +250,10 @@ def make_views(self, user_settings): for setting_name, user_setting in user_settings.get(view_name).items(): available_settings = [s["name"] for s in view_class._settings] if setting_name not in available_settings: - raise KeyError(f"Setting {setting_name} is not a valid setting for View {view_name}. Check your settings file.") - settings_index = available_settings.index(setting_name) - view_class._settings[settings_index]["value"] = user_setting + warnings.warn(f"Setting {setting_name} is not a valid setting for View {view_name}. Ignoring setting. Check your settings file.") + else: + settings_index = available_settings.index(setting_name) + view_class._settings[settings_index]["value"] = user_setting view = view_class(controller=self.controller, parent=None, backend='panel') self.views[view_name] = view diff --git a/spikeinterface_gui/backend_qt.py b/spikeinterface_gui/backend_qt.py index 6e6a7d7c..074b0543 100644 --- a/spikeinterface_gui/backend_qt.py +++ b/spikeinterface_gui/backend_qt.py @@ -1,3 +1,5 @@ +import warnings + from .myqt import QT import pyqtgraph as pg import markdown @@ -203,10 +205,11 @@ def make_views(self, user_settings): if user_settings is not None and view_name != 'mainsettings' and user_settings.get(view_name) is not None: for setting_name, user_setting in user_settings.get(view_name).items(): if setting_name not in view.settings.keys().keys(): - raise KeyError(f"Setting {setting_name} is not a valid setting for View {view_name}. Check your settings file.") - stop_listen_setting_changes(view) - view.settings[setting_name] = user_setting - listen_setting_changes(view) + warnings.warn(f"Setting {setting_name} is not a valid setting for View {view_name}. Ignoring setting. Check your settings file.") + else: + stop_listen_setting_changes(view) + view.settings[setting_name] = user_setting + listen_setting_changes(view) widget.set_view(view)