Source code for tridesclous.gui.pairlist

from .myqt import QT
import pyqtgraph as pg

import numpy as np
import  itertools

from .base import WidgetBase
from .tools import ParamDialog



[docs]class PairList(WidgetBase): """ **Pair list** is an intuituitive list of pair of cluster : when you click on a pair this make visible only this 2 cluster on all others views. This help to validate in a fast way clusters. For convinience this paris can be filtered: * **all pairs** : all combinaison * **high similarity**: select only pairs that have similarity over a threshold (in settings) * **similarity amplitude ratio**! select only pairs that have "similarity ratio" over a threshold (in settings) And they can be sorted by: * label * similarity * ratio_similarity WIth a right click you can: * **merge** a pair * **tag same cell**, this keep 2 cluster but there tag as same cell. """ _params = [{'name': 'threshold_similarity', 'type': 'float', 'value' :.9, 'step' : 0.01}, {'name': 'threshold_ratio_similarity', 'type': 'float', 'value' :.8, 'step' : 0.01}, ] def __init__(self, controller=None, parent=None): WidgetBase.__init__(self, parent=parent, controller=controller) self.layout = QT.QVBoxLayout() self.setLayout(self.layout) #~ h = QT.QHBoxLayout() #~ self.layout.addLayout(h) self.combo_select = QT.QComboBox() #~ h.addWidget(QT.QLabel('Select')) #~ h.addWidget(self.combo_select) self.combo_select.addItems(['all pairs', 'similar amplitude ratio', 'high similarity']) # #~ self.combo_select.currentTextChanged.connect(self.refresh) #~ h.addStretch() h = QT.QHBoxLayout() self.layout.addLayout(h) h.addWidget(QT.QLabel('Sort by')) self.combo_sort = QT.QComboBox() self.combo_sort.addItems(['label', 'similarity', 'ratio_similarity']) self.combo_sort.currentIndexChanged.connect(self.refresh) h.addWidget(self.combo_sort) h.addStretch() #~ but = QT.QPushButton('settings') #~ self.layout.addWidget(but) #~ but.clicked.connect(self.open_settings) self.table = QT.QTableWidget(selectionMode=QT.QAbstractItemView.SingleSelection, selectionBehavior=QT.QAbstractItemView.SelectRows) self.table.setContextMenuPolicy(QT.Qt.CustomContextMenu) self.layout.addWidget(self.table) self.table.itemSelectionChanged.connect(self.on_item_selection_changed) self.table.customContextMenuRequested.connect(self.open_context_menu) self.menu = QT.QMenu() act = self.menu.addAction('Merge') act.triggered.connect(self.do_merge) act = self.menu.addAction('Tag same cell') act.triggered.connect(self.do_tag_same_cell) self.refresh() def on_item_selection_changed(self): inds = self.table.selectedIndexes() if len(inds)!=self.table.columnCount(): return k1, k2 = self.pairs[inds[0].row()] for k in self.controller.cluster_visible: self.controller.cluster_visible[k] = k in (k1, k2) self.cluster_visibility_changed.emit() def open_context_menu(self): self.menu.popup(self.cursor().pos()) def do_merge(self): if len(self.table.selectedIndexes())==0: return ind = self.table.selectedIndexes()[0].row() label_to_merge = list(self.pairs[ind]) self.controller.merge_cluster(label_to_merge) self.refresh() self.spike_label_changed.emit() def do_tag_same_cell(self): if len(self.table.selectedIndexes())==0: return ind = self.table.selectedIndexes()[0].row() label_to_merge = list(self.pairs[ind]) self.controller.tag_same_cell(label_to_merge) self.refresh() self.cluster_tag_changed.emit() def refresh(self): self.table.clear() labels = ['cluster_label_1', 'cluster_label_2', 'cell_label_1', 'cell_label_2' , 'similarity', 'ratio_similarity'] self.table.setColumnCount(len(labels)) self.table.setHorizontalHeaderLabels(labels) self.table.setColumnWidth(0, 100) self.table.setColumnWidth(1, 100) #select mode = self.combo_select.currentText() if mode == 'all pairs': labels = self.controller.positive_cluster_labels #~ labels = labels[labels>=0] self.pairs = list(itertools.combinations(labels, 2)) elif mode == 'similar amplitude ratio': self.pairs = self.controller.detect_similar_waveform_ratio(threshold=self.params['threshold_ratio_similarity']) elif mode == 'high similarity': self.pairs = self.controller.detect_high_similarity(threshold=self.params['threshold_similarity']) #sort mode = self.combo_sort.currentText() order = np.arange(len(self.pairs)) if mode == 'label': pass elif mode == 'similarity': if self.controller.cluster_similarity is not None: order = [] for r in range(len(self.pairs)): k1, k2 = self.pairs[r] ind1 = self.controller.positive_cluster_labels.tolist().index(k1) ind2 = self.controller.positive_cluster_labels.tolist().index(k2) order.append(self.controller.cluster_similarity[ind1, ind2]) order = np.argsort(order)[::-1] elif mode == 'ratio_similarity': if self.controller.cluster_ratio_similarity is not None: order = [] for r in range(len(self.pairs)): k1, k2 = self.pairs[r] ind1 = self.controller.positive_cluster_labels.tolist().index(k1) ind2 = self.controller.positive_cluster_labels.tolist().index(k2) order.append(self.controller.cluster_ratio_similarity[ind1, ind2]) order = np.argsort(order)[::-1] self.pairs = [self.pairs[i] for i in order ] self.table.setRowCount(len(self.pairs)) for r in range(len(self.pairs)): k1, k2 = self.pairs[r] ind1 = self.controller.positive_cluster_labels.tolist().index(k1) ind2 = self.controller.positive_cluster_labels.tolist().index(k2) for c, k in enumerate((k1, k2)): color = self.controller.qcolors.get(k, QT.QColor( 'white')) pix = QT.QPixmap(16,16) pix.fill(color) icon = QT.QIcon(pix) name = '{} (nb={})'.format(k, self.controller.cluster_count[k]) item = QT.QTableWidgetItem(name) item.setFlags(QT.Qt.ItemIsEnabled|QT.Qt.ItemIsSelectable) self.table.setItem(r,c, item) item.setIcon(icon) cell_label = self.controller.cell_labels[self.controller.cluster_labels==k][0] name = '{}'.format(cell_label) item = QT.QTableWidgetItem(name) item.setFlags(QT.Qt.ItemIsEnabled|QT.Qt.ItemIsSelectable) self.table.setItem(r,c+2, item) if self.controller.cluster_similarity is not None: if self.controller.cluster_similarity.shape[0] == self.controller.positive_cluster_labels.size: name = '{}'.format(self.controller.cluster_similarity[ind1, ind2]) item = QT.QTableWidgetItem(name) item.setFlags(QT.Qt.ItemIsEnabled|QT.Qt.ItemIsSelectable) self.table.setItem(r,4, item) if self.controller.cluster_ratio_similarity is not None: if self.controller.cluster_ratio_similarity.shape[0] == self.controller.positive_cluster_labels.size: name = '{}'.format(self.controller.cluster_ratio_similarity[ind1, ind2]) item = QT.QTableWidgetItem(name) item.setFlags(QT.Qt.ItemIsEnabled|QT.Qt.ItemIsSelectable) self.table.setItem(r,5, item) def on_spike_selection_changed(self): pass def on_spike_label_changed(self): self.refresh() def on_colors_changed(self): self.refresh() def on_cluster_visibility_changed(self): pass