Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spikeinterface_gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@

from .version import version as __version__

from .main import run_mainwindow, run_launcher
from .main import run_mainwindow, run_launcher, run_compare_analyzer

90 changes: 90 additions & 0 deletions spikeinterface_gui/backend_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,93 @@ def refresh(self):
'horizontal' : QT.Qt.Horizontal,
'vertical' : QT.Qt.Vertical,
}


class ControllerSynchronizer(QT.QWidget):
def __init__(self, sorting_comparison, controllers, windows, parent=None):
QT.QWidget.__init__(self, parent=parent)

self.comp = sorting_comparison
self.controllers = controllers
self.windows = windows

self.layout = QT.QVBoxLayout()
self.setLayout(self.layout)

self.label = QT.QLabel('')
self.layout.addWidget(self.label)


for i, window in enumerate(windows):

# this is not working ???!!!!!
# callback = lambda: self.on_unit_visibility_changed(win_ind=i)

# so uggly solution
callback = [self.on_unit_visibility_changed_0, self.on_unit_visibility_changed_1][i]

for view in window.views.values():
view.notifier.unit_visibility_changed.connect(callback)

settings = [
{'name': 'mode', 'type': 'list', 'limits' : ['all', 'best', ] },
{'name': 'thresh', 'type': 'float', 'value' : 0.05, 'step': 0.01, 'limits': (0, 1.)},
]
self.settings = pg.parametertree.Parameter.create(name="settings", type='group', children=settings)

# not that the parent is not the view (not Qt anymore) itself but the widget
self.tree_settings = pg.parametertree.ParameterTree(parent=self)
self.tree_settings.header().hide()
self.tree_settings.setParameters(self.settings, showTop=True)
self.tree_settings.setWindowTitle('Settings')
self.layout.addWidget(self.tree_settings)


def on_unit_visibility_changed_0(self):
self.on_unit_visibility_changed(0)

def on_unit_visibility_changed_1(self):
self.on_unit_visibility_changed(1)


def on_unit_visibility_changed(self, win_ind):
changed_controller = self.controllers[win_ind]
visible_unit_inds = changed_controller.get_visible_unit_indices()
visible_unit_ids = changed_controller.get_visible_unit_ids()
if len(visible_unit_inds) != 1:
# TODO handle several units at once
return

unit_ind = visible_unit_inds[0]

agreement = self.comp.agreement_scores.values
if win_ind == 1:
agreement = agreement.T

thresh = self.settings['thresh']
mode = self.settings['mode']

other_ind = (win_ind + 1) % 2
other_controller = self.controllers[other_ind]
other_window = self.windows[other_ind]

if mode == 'all':
other_visible_inds = agreement[unit_ind, :] > thresh
elif mode == 'best':
best_ind = np.argmax(agreement[unit_ind, :])
if agreement[unit_ind, best_ind] > thresh:
other_visible_inds = [best_ind]
else:
other_visible_inds = []

other_visible_ids = other_controller.unit_ids[other_visible_inds]
other_controller.set_visible_unit_ids(other_visible_ids)

for view in other_window.views.values():
view.refresh()

self.label.setText(
f'Analyzer {win_ind} : {visible_unit_ids}\n'
f'Analyzer {other_ind} : {other_visible_ids}\n'

)
73 changes: 72 additions & 1 deletion spikeinterface_gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,75 @@ def find_skippable_extensions(layout_dict):

skippable_extensions = list(all_extensions.difference(set(needed_extensions)))

return skippable_extensions
return skippable_extensions


def run_compare_analyzer(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def run_compare_analyzer(
def run_compare_analyzers(

analyzers,
mode="desktop",
with_traces=False,
# displayed_unit_properties=None,
skip_extensions=None,
layout_preset=None,
layout=None,
verbose=False,
# user_settings=None,
# disable_save_settings_button=False,
):

assert isinstance(analyzers, list)
assert len(analyzers) == 2
assert mode == "desktop"

from spikeinterface_gui.myqt import QT, mkQApp
from spikeinterface_gui.backend_qt import QtMainWindow, ControllerSynchronizer
from spikeinterface.comparison import compare_two_sorters

layout_dict = get_layout_description(layout_preset, layout)



controllers = []
windows = []
for i, analyzer in enumerate(analyzers):
if verbose:
import time
t0 = time.perf_counter()

controller = Controller(
analyzer, backend="qt",
# verbose=verbose,
verbose=False,

curation=False,
with_traces=with_traces,
skip_extensions=skip_extensions,
)
if verbose:
t1 = time.perf_counter()
print('controller init time', t1 - t0)


# Suppress a known pyqtgraph warning
warnings.filterwarnings("ignore", category=RuntimeWarning, module="pyqtgraph")
warnings.filterwarnings('ignore', category=UserWarning, message=".*QObject::connect.*")


app = mkQApp()

win = QtMainWindow(controller, layout_dict=layout_dict) #, user_settings=user_settings)
win.setWindowTitle(f'Analyzer {i}')
# Set window icon
icon_file = Path(__file__).absolute().parent / 'img' / 'si.png'
if icon_file.exists():
app.setWindowIcon(QT.QIcon(str(icon_file)))
win.show()
windows.append(win)
controllers.append(controller)

comp = compare_two_sorters(analyzers[0].sorting, analyzers[1].sorting)

synchronizer = ControllerSynchronizer(comp, controllers, windows)
synchronizer.show()

app.exec()