def __init__(self, parent=None, width=5, height=4, dpi=100): self._fig = Figure(figsize=(width, height), dpi=dpi, facecolor='none') FigureCanvas.__init__(self, self._fig) # super(MPLCanvas, self).__init__(self._fig) self._axes = self._fig.add_subplot(111) self.compute_initial_figure() self.setParent(parent) FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.updateGeometry(self)
class CalibrationViewer(QtGui.QMainWindow): trialsChanged = QtCore.pyqtSignal() def __init__(self): self.filters = list() super(CalibrationViewer, self).__init__() self.setWindowTitle('Olfa Calibration') self.statusBar() self.trial_selected_list = [] self.trialsChanged.connect(self._trial_selection_changed) mainwidget = QtGui.QWidget(self) self.setCentralWidget(mainwidget) layout = QtGui.QGridLayout(mainwidget) mainwidget.setLayout(layout) menu = self.menuBar() filemenu = menu.addMenu("&File") toolsmenu = menu.addMenu("&Tools") openAction = QtGui.QAction("&Open recording...", self) openAction.triggered.connect(self._openAction_triggered) openAction.setStatusTip("Open a HDF5 data file with calibration recording.") openAction.setShortcut("Ctrl+O") filemenu.addAction(openAction) saveFigsAction = QtGui.QAction('&Save figures...', self) saveFigsAction.triggered.connect(self._saveFiguresAction_triggered) saveFigsAction.setShortcut('Ctrl+S') openAction.setStatusTip("Saves current figures.") filemenu.addAction(saveFigsAction) exitAction = QtGui.QAction("&Quit", self) exitAction.setShortcut("Ctrl+Q") exitAction.setStatusTip("Quit program.") exitAction.triggered.connect(QtGui.qApp.quit) filemenu.addAction(exitAction) removeTrialAction = QtGui.QAction("&Remove trials", self) removeTrialAction.setStatusTip('Permanently removes selected trials (bad trials) from trial list.') removeTrialAction.triggered.connect(self._remove_trials) removeTrialAction.setShortcut('Ctrl+R') toolsmenu.addAction(removeTrialAction) trial_group_list_box = QtGui.QGroupBox() trial_group_list_box.setTitle('Trial Groups') self.trial_group_list = TrialGroupListWidget() trial_group_layout = QtGui.QVBoxLayout() trial_group_list_box.setLayout(trial_group_layout) trial_group_layout.addWidget(self.trial_group_list) layout.addWidget(trial_group_list_box, 0, 0) self.trial_group_list.itemSelectionChanged.connect(self._trial_group_selection_changed) trial_select_list_box = QtGui.QGroupBox() trial_select_list_box.setMouseTracking(True) trial_select_list_layout = QtGui.QVBoxLayout() trial_select_list_box.setLayout(trial_select_list_layout) trial_select_list_box.setTitle('Trials') self.trial_select_list = TrialListWidget() self.trial_select_list.setMouseTracking(True) trial_select_list_layout.addWidget(self.trial_select_list) self.trial_select_list.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) self.trial_select_list.itemSelectionChanged.connect(self._trial_selection_changed) layout.addWidget(trial_select_list_box, 0, 1) self.trial_select_list.createGroupSig.connect(self.trial_group_list.create_group) filters_box = QtGui.QGroupBox("Trial filters.") filters_box_layout = QtGui.QVBoxLayout(filters_box) filters_scroll_area = QtGui.QScrollArea() filters_buttons = QtGui.QHBoxLayout() filters_all = QtGui.QPushButton('Select all', self) filters_all.clicked.connect(self._select_all_filters) filters_none = QtGui.QPushButton('Select none', self) filters_none.clicked.connect(self._select_none_filters) filters_buttons.addWidget(filters_all) filters_buttons.addWidget(filters_none) filters_box_layout.addLayout(filters_buttons) filters_box_layout.addWidget(filters_scroll_area) filters_wid = QtGui.QWidget() filters_scroll_area.setWidget(filters_wid) filters_scroll_area.setWidgetResizable(True) filters_scroll_area.setFixedWidth(300) self.filters_layout = QtGui.QVBoxLayout() filters_wid.setLayout(self.filters_layout) layout.addWidget(filters_box, 0, 2) plots_box = QtGui.QGroupBox() plots_box.setTitle('Plots') plots_layout = QtGui.QHBoxLayout() self.figure = Figure((9, 5)) self.figure.patch.set_facecolor('None') self.canvas = FigureCanvas(self.figure) self.canvas.setParent(plots_box) self.canvas.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) plots_layout.addWidget(self.canvas) plots_box.setLayout(plots_layout) layout.addWidget(plots_box, 0, 3) self.ax_pid = self.figure.add_subplot(2, 1, 1) self.ax_pid.set_title('PID traces') self.ax_pid.set_ylabel('') self.ax_pid.set_xlabel('t (ms)') # self.ax_pid.set_yscale('log') self.ax_mean_plots = self.figure.add_subplot(2, 1, 2) self.ax_mean_plots.set_title('Mean value') self.ax_mean_plots.set_ylabel('value') self.ax_mean_plots.set_xlabel('Concentration') self.ax_mean_plots.autoscale(enable=True, axis=u'both', tight=False) self.figure.tight_layout() @QtCore.pyqtSlot() def _list_context_menu_trig(self): pass @QtCore.pyqtSlot() def _filters_changed(self): mask = np.ones_like(self.trial_mask) for v in self.filters: mask *= v.trial_mask self.trial_mask = mask self.trial_select_list.itemSelectionChanged.disconnect(self._trial_selection_changed) for i in xrange(len(self.trial_mask)): hide = not self.trial_mask[i] it = self.trial_select_list.item(i) it.setHidden(hide) select = it.isSelected() * self.trial_mask[i] it.setSelected(select) self.trial_select_list.itemSelectionChanged.connect(self._trial_selection_changed) self.trial_select_list.itemSelectionChanged.emit() # emit that something changed so that we redraw. @QtCore.pyqtSlot() def _openAction_triggered(self): filedialog = QtGui.QFileDialog(self) if os.path.exists('D:\\experiment\\raw_data'): startpath = 'D:\\experiment\\raw_data\\mouse_o_cal_cw\\sess_001' else: startpath = '' fn = filedialog.getOpenFileName(self, "Select a data file.", startpath, "HDF5 (*.h5)") if fn: data = CalibrationFile(str(fn)) self.data = data self.trial_actions = [] trial_num_list = [] self.trial_select_list.clear() trials = self.data.trials for i, t in enumerate(trials): tstr = "Trial {0}".format(i) it = QtGui.QListWidgetItem(tstr, self.trial_select_list) # trial = trials[i] # odor = trial['odor'] # vialconc = trial['vialconc'] # odorconc = trial['odorconc'] # dilution = 1000 - trial['dilution'][0] # trst = 'Odor: {0}, vialconc: {1}, odorconc: {2}, dilution: {3}'.format(odor, vialconc, odorconc, # dilution) # it.setStatusTip(trst) trial_num_list.append(i) self.trial_select_list.trial_num_list = np.array(trial_num_list) self.trial_mask = np.ones(len(self.trial_select_list.trial_num_list), dtype=bool) self.build_filters(trials) else: print('No file selected.') return def build_filters(self, trials): while self.filters_layout.itemAt(0): self.filters_layout.takeAt(0) if self.filters: for f in self.filters: f.deleteLater() self.filters = list() colnames = trials.dtype.names if 'odorconc' not in colnames: self.error = QtGui.QErrorMessage() self.error.showMessage('Data file must have "odorconc" field to allow plotting.') start_strings = ('odorconc', 'olfas', 'dilutors') filter_fields = [] for ss in start_strings: for fieldname in colnames: if fieldname.startswith(ss): filter_fields.append(fieldname) for field in filter_fields: filter = FiltersListWidget(field) filter.populate_list(self.data.trials) filter.setVisible(False) self.filters.append(filter) box = QtGui.QWidget() box.setSizePolicy(0, 0) # box.setTitle(filter.fieldname) show_button = QtGui.QPushButton(filter.fieldname) show_button.setStyleSheet('text-align:left; border:0px') show_button.clicked.connect(filter.toggle_visible) _filt_layout = QtGui.QVBoxLayout(box) _filt_layout.addWidget(show_button) _filt_layout.addWidget(filter) _filt_layout.setSpacing(0) self.filters_layout.addWidget(box) filter.filterChanged.connect(self._filters_changed) for v in self.filters: assert isinstance(v, FiltersListWidget) # self.filters_layout.addWidget(QtGui.QSpacerItem()) self.filters_layout.addStretch() self.filters_layout.setSpacing(0) return @QtCore.pyqtSlot() def _saveFiguresAction_triggered(self): # TODO: add figure saving functionality with filedialog.getSaveFileName. self.saveDialog = QtGui.QFileDialog() saveloc = self.saveDialog.getSaveFileName(self, 'Save figure', '', 'PDF (*.pdf);;JPEG (*.jpg);;TIFF (*.tif)') saveloc = str(saveloc) self.figure.savefig(saveloc) @QtCore.pyqtSlot() def _remove_trials(self): selected_idxes = self.trial_select_list.selectedIndexes() remove_idxes = [] for id in selected_idxes: idx = id.row() remove_idxes.append(idx) while self.trial_select_list.selectedIndexes(): selected_idxes = self.trial_select_list.selectedIndexes() idx = selected_idxes[0].row() self.trial_select_list.takeItem(idx) new_trials_array = np.zeros(len(self.trial_select_list.trial_num_list)-len(remove_idxes), dtype=np.int) ii = 0 remove_trialnums = [] new_trials_mask = np.zeros_like(new_trials_array, dtype=bool) for i in xrange(len(self.trial_select_list.trial_num_list)): if i not in remove_idxes: new_trials_mask[ii] = self.trial_mask[i] new_trials_array[ii] = self.trial_select_list.trial_num_list[i] ii += 1 else: remove_trialnums.append(self.trial_select_list.trial_num_list[i]) self.trial_mask = new_trials_mask self.trial_select_list.trial_num_list = new_trials_array for f in self.filters: f.remove_trials(remove_idxes) self.trial_group_list._remove_trials(remove_trialnums) @QtCore.pyqtSlot() def _trial_selection_changed(self): selected_idxes = self.trial_select_list.selectedIndexes() selected_trial_nums = [] for id in selected_idxes: idx = id.row() trialnum = self.trial_select_list.trial_num_list[idx] selected_trial_nums.append(trialnum) self.update_plots(selected_trial_nums) self.trial_group_list.blockSignals(True) for i, g in zip(xrange(self.trial_group_list.count()), self.trial_group_list.trial_groups): it = self.trial_group_list.item(i) all_in = True group_trials = g['trial_nums'] for t in group_trials: if t not in selected_trial_nums: all_in = False if not all_in: it.setSelected(False) elif all_in: it.setSelected(True) self.trial_group_list.blockSignals(False) return @QtCore.pyqtSlot() def _trial_group_selection_changed(self): selected_idxes = self.trial_group_list.selectedIndexes() self._select_all_filters() selected_trial_nums = [] for id in selected_idxes: idx = id.row() trialnums = self.trial_group_list.trial_groups[idx]['trial_nums'] selected_trial_nums.extend(trialnums) self.trial_select_list.blockSignals(True) for i in range(self.trial_select_list.count()): item = self.trial_select_list.item(i) self.trial_select_list.setItemSelected(item, False) for i in selected_trial_nums: idx = np.where(self.trial_select_list.trial_num_list == i)[0][0] it = self.trial_select_list.item(idx) if not it.isSelected(): it.setSelected(True) self.trial_select_list.blockSignals(False) self._trial_selection_changed() def update_plots(self, trials): padding = (2000, 2000) #TODO: make this changable - this is the number of ms before/afterr trial to extract for stream. trial_streams = [] trial_colors = [] while self.ax_pid.lines: self.ax_pid.lines.pop(0) while self.ax_mean_plots.lines: self.ax_mean_plots.lines.pop(0) groups_by_trial = [] all_groups = set() ntrials = len(trials) vals = np.empty(ntrials) concs = np.empty_like(vals) if trials: a = max([1./len(trials), .25]) for i, tn in enumerate(trials): color = self.trial_group_list.get_trial_color(tn) groups = self.trial_group_list.get_trial_groups(tn) trial_colors.append(color) groups_by_trial.append(groups) all_groups.update(groups) trial = self.data.return_trial(tn, padding=padding) stream = remove_stream_trend(trial.streams['sniff'], (0, padding[0])) stream -= stream[0:padding[0]].min() # TODO: remove baseline (N2) trial average from this. trial_streams.append(stream) self.ax_pid.plot(stream, color=color, alpha=a) conc = trial.trials['odorconc'] baseline = np.mean(stream[:2000]) val = np.mean(stream[3000:4000]) - baseline vals[i] = val concs[i] = conc self.ax_mean_plots.plot(conc, val, '.', color=color) minlen = 500000000 for i in trial_streams: minlen = min(len(i), minlen) streams_array = np.empty((ntrials, minlen)) for i in xrange(ntrials): streams_array[i, :] = trial_streams[i][:minlen] for g in all_groups: mask = np.empty(ntrials, dtype=bool) for i in xrange(ntrials): groups = groups_by_trial[i] mask[i] = g in groups c = concs[mask] groupstreams = streams_array[mask] if len(np.unique(c)) < 2: self.ax_pid.plot(groupstreams.mean(axis=0), color='k', linewidth=2) else: v = vals[mask] a, b, _, _, _ = stats.linregress(c, v) color = self.trial_group_list.get_group_color(g) minn, maxx = self.ax_mean_plots.get_xlim() x = np.array([minn, maxx]) self.ax_mean_plots.plot(x, a*x + b, color=color) self.ax_pid.relim() self.ax_mean_plots.set_yscale('log') self.ax_mean_plots.set_xscale('log') self.ax_mean_plots.relim() self.canvas.draw() @QtCore.pyqtSlot() def _select_none_filters(self): for filter in self.filters: filter.filterChanged.disconnect(self._filters_changed) filter.clearSelection() filter.filterChanged.connect(self._filters_changed) self._filters_changed() @QtCore.pyqtSlot() def _select_all_filters(self): for filter in self.filters: filter.filterChanged.disconnect(self._filters_changed) filter.selectAll() filter.filterChanged.connect(self._filters_changed) self._filters_changed()
class CalibrationViewer(QtGui.QMainWindow): trialsChanged = QtCore.pyqtSignal() def __init__(self): self.filters = list() super(CalibrationViewer, self).__init__() self.setWindowTitle('Olfa Calibration') self.statusBar() self.trial_selected_list = [] self.trialsChanged.connect(self._trial_selection_changed) mainwidget = QtGui.QWidget(self) self.setCentralWidget(mainwidget) layout = QtGui.QGridLayout(mainwidget) mainwidget.setLayout(layout) menu = self.menuBar() filemenu = menu.addMenu("&File") toolsmenu = menu.addMenu("&Tools") openAction = QtGui.QAction("&Open recording...", self) openAction.triggered.connect(self._openAction_triggered) openAction.setStatusTip( "Open a HDF5 data file with calibration recording.") openAction.setShortcut("Ctrl+O") filemenu.addAction(openAction) saveFigsAction = QtGui.QAction('&Save figures...', self) saveFigsAction.triggered.connect(self._saveFiguresAction_triggered) saveFigsAction.setShortcut('Ctrl+S') openAction.setStatusTip("Saves current figures.") filemenu.addAction(saveFigsAction) exitAction = QtGui.QAction("&Quit", self) exitAction.setShortcut("Ctrl+Q") exitAction.setStatusTip("Quit program.") exitAction.triggered.connect(QtGui.qApp.quit) filemenu.addAction(exitAction) removeTrialAction = QtGui.QAction("&Remove trials", self) removeTrialAction.setStatusTip( 'Permanently removes selected trials (bad trials) from trial list.' ) removeTrialAction.triggered.connect(self._remove_trials) removeTrialAction.setShortcut('Ctrl+R') toolsmenu.addAction(removeTrialAction) trial_group_list_box = QtGui.QGroupBox() trial_group_list_box.setTitle('Trial Groups') self.trial_group_list = TrialGroupListWidget() trial_group_layout = QtGui.QVBoxLayout() trial_group_list_box.setLayout(trial_group_layout) trial_group_layout.addWidget(self.trial_group_list) layout.addWidget(trial_group_list_box, 0, 0) self.trial_group_list.itemSelectionChanged.connect( self._trial_group_selection_changed) trial_select_list_box = QtGui.QGroupBox() trial_select_list_box.setMouseTracking(True) trial_select_list_layout = QtGui.QVBoxLayout() trial_select_list_box.setLayout(trial_select_list_layout) trial_select_list_box.setTitle('Trials') self.trial_select_list = TrialListWidget() self.trial_select_list.setMouseTracking(True) trial_select_list_layout.addWidget(self.trial_select_list) self.trial_select_list.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection) self.trial_select_list.itemSelectionChanged.connect( self._trial_selection_changed) layout.addWidget(trial_select_list_box, 0, 1) self.trial_select_list.createGroupSig.connect( self.trial_group_list.create_group) filters_box = QtGui.QGroupBox("Trial filters.") filters_box_layout = QtGui.QVBoxLayout(filters_box) filters_scroll_area = QtGui.QScrollArea() filters_buttons = QtGui.QHBoxLayout() filters_all = QtGui.QPushButton('Select all', self) filters_all.clicked.connect(self._select_all_filters) filters_none = QtGui.QPushButton('Select none', self) filters_none.clicked.connect(self._select_none_filters) filters_buttons.addWidget(filters_all) filters_buttons.addWidget(filters_none) filters_box_layout.addLayout(filters_buttons) filters_box_layout.addWidget(filters_scroll_area) filters_wid = QtGui.QWidget() filters_scroll_area.setWidget(filters_wid) filters_scroll_area.setWidgetResizable(True) filters_scroll_area.setFixedWidth(300) self.filters_layout = QtGui.QVBoxLayout() filters_wid.setLayout(self.filters_layout) layout.addWidget(filters_box, 0, 2) plots_box = QtGui.QGroupBox() plots_box.setTitle('Plots') plots_layout = QtGui.QHBoxLayout() self.figure = Figure((9, 5)) self.figure.patch.set_facecolor('None') self.canvas = FigureCanvas(self.figure) self.canvas.setParent(plots_box) self.canvas.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) plots_layout.addWidget(self.canvas) plots_box.setLayout(plots_layout) layout.addWidget(plots_box, 0, 3) self.ax_pid = self.figure.add_subplot(2, 1, 1) self.ax_pid.set_title('PID traces') self.ax_pid.set_ylabel('') self.ax_pid.set_xlabel('t (ms)') # self.ax_pid.set_yscale('log') self.ax_mean_plots = self.figure.add_subplot(2, 1, 2) self.ax_mean_plots.set_title('Mean value') self.ax_mean_plots.set_ylabel('value') self.ax_mean_plots.set_xlabel('Concentration') self.ax_mean_plots.autoscale(enable=True, axis=u'both', tight=False) self.figure.tight_layout() @QtCore.pyqtSlot() def _list_context_menu_trig(self): pass @QtCore.pyqtSlot() def _filters_changed(self): mask = np.ones_like(self.trial_mask) for v in self.filters: mask *= v.trial_mask self.trial_mask = mask self.trial_select_list.itemSelectionChanged.disconnect( self._trial_selection_changed) for i in xrange(len(self.trial_mask)): hide = not self.trial_mask[i] it = self.trial_select_list.item(i) it.setHidden(hide) select = it.isSelected() * self.trial_mask[i] it.setSelected(select) self.trial_select_list.itemSelectionChanged.connect( self._trial_selection_changed) self.trial_select_list.itemSelectionChanged.emit( ) # emit that something changed so that we redraw. @QtCore.pyqtSlot() def _openAction_triggered(self): filedialog = QtGui.QFileDialog(self) if os.path.exists('D:\\experiment\\raw_data'): startpath = 'D:\\experiment\\raw_data\\mouse_o_cal_cw\\sess_001' else: startpath = '' fn = filedialog.getOpenFileName(self, "Select a data file.", startpath, "HDF5 (*.h5)") if fn: data = CalibrationFile(str(fn)) self.data = data self.trial_actions = [] trial_num_list = [] self.trial_select_list.clear() trials = self.data.trials for i, t in enumerate(trials): tstr = "Trial {0}".format(i) it = QtGui.QListWidgetItem(tstr, self.trial_select_list) # trial = trials[i] # odor = trial['odor'] # vialconc = trial['vialconc'] # odorconc = trial['odorconc'] # dilution = 1000 - trial['dilution'][0] # trst = 'Odor: {0}, vialconc: {1}, odorconc: {2}, dilution: {3}'.format(odor, vialconc, odorconc, # dilution) # it.setStatusTip(trst) trial_num_list.append(i) self.trial_select_list.trial_num_list = np.array(trial_num_list) self.trial_mask = np.ones(len( self.trial_select_list.trial_num_list), dtype=bool) self.build_filters(trials) else: print('No file selected.') return def build_filters(self, trials): while self.filters_layout.itemAt(0): self.filters_layout.takeAt(0) if self.filters: for f in self.filters: f.deleteLater() self.filters = list() colnames = trials.dtype.names if 'odorconc' not in colnames: self.error = QtGui.QErrorMessage() self.error.showMessage( 'Data file must have "odorconc" field to allow plotting.') start_strings = ('odorconc', 'olfas', 'dilutors') filter_fields = [] for ss in start_strings: for fieldname in colnames: if fieldname.startswith(ss): filter_fields.append(fieldname) for field in filter_fields: filter = FiltersListWidget(field) filter.populate_list(self.data.trials) filter.setVisible(False) self.filters.append(filter) box = QtGui.QWidget() box.setSizePolicy(0, 0) # box.setTitle(filter.fieldname) show_button = QtGui.QPushButton(filter.fieldname) show_button.setStyleSheet('text-align:left; border:0px') show_button.clicked.connect(filter.toggle_visible) _filt_layout = QtGui.QVBoxLayout(box) _filt_layout.addWidget(show_button) _filt_layout.addWidget(filter) _filt_layout.setSpacing(0) self.filters_layout.addWidget(box) filter.filterChanged.connect(self._filters_changed) for v in self.filters: assert isinstance(v, FiltersListWidget) # self.filters_layout.addWidget(QtGui.QSpacerItem()) self.filters_layout.addStretch() self.filters_layout.setSpacing(0) return @QtCore.pyqtSlot() def _saveFiguresAction_triggered(self): # TODO: add figure saving functionality with filedialog.getSaveFileName. self.saveDialog = QtGui.QFileDialog() saveloc = self.saveDialog.getSaveFileName( self, 'Save figure', '', 'PDF (*.pdf);;JPEG (*.jpg);;TIFF (*.tif)') saveloc = str(saveloc) self.figure.savefig(saveloc) @QtCore.pyqtSlot() def _remove_trials(self): selected_idxes = self.trial_select_list.selectedIndexes() remove_idxes = [] for id in selected_idxes: idx = id.row() remove_idxes.append(idx) while self.trial_select_list.selectedIndexes(): selected_idxes = self.trial_select_list.selectedIndexes() idx = selected_idxes[0].row() self.trial_select_list.takeItem(idx) new_trials_array = np.zeros( len(self.trial_select_list.trial_num_list) - len(remove_idxes), dtype=np.int) ii = 0 remove_trialnums = [] new_trials_mask = np.zeros_like(new_trials_array, dtype=bool) for i in xrange(len(self.trial_select_list.trial_num_list)): if i not in remove_idxes: new_trials_mask[ii] = self.trial_mask[i] new_trials_array[ii] = self.trial_select_list.trial_num_list[i] ii += 1 else: remove_trialnums.append( self.trial_select_list.trial_num_list[i]) self.trial_mask = new_trials_mask self.trial_select_list.trial_num_list = new_trials_array for f in self.filters: f.remove_trials(remove_idxes) self.trial_group_list._remove_trials(remove_trialnums) @QtCore.pyqtSlot() def _trial_selection_changed(self): selected_idxes = self.trial_select_list.selectedIndexes() selected_trial_nums = [] for id in selected_idxes: idx = id.row() trialnum = self.trial_select_list.trial_num_list[idx] selected_trial_nums.append(trialnum) self.update_plots(selected_trial_nums) self.trial_group_list.blockSignals(True) for i, g in zip(xrange(self.trial_group_list.count()), self.trial_group_list.trial_groups): it = self.trial_group_list.item(i) all_in = True group_trials = g['trial_nums'] for t in group_trials: if t not in selected_trial_nums: all_in = False if not all_in: it.setSelected(False) elif all_in: it.setSelected(True) self.trial_group_list.blockSignals(False) return @QtCore.pyqtSlot() def _trial_group_selection_changed(self): selected_idxes = self.trial_group_list.selectedIndexes() self._select_all_filters() selected_trial_nums = [] for id in selected_idxes: idx = id.row() trialnums = self.trial_group_list.trial_groups[idx]['trial_nums'] selected_trial_nums.extend(trialnums) self.trial_select_list.blockSignals(True) for i in range(self.trial_select_list.count()): item = self.trial_select_list.item(i) self.trial_select_list.setItemSelected(item, False) for i in selected_trial_nums: idx = np.where(self.trial_select_list.trial_num_list == i)[0][0] it = self.trial_select_list.item(idx) if not it.isSelected(): it.setSelected(True) self.trial_select_list.blockSignals(False) self._trial_selection_changed() def update_plots(self, trials): padding = ( 2000, 2000 ) #TODO: make this changable - this is the number of ms before/afterr trial to extract for stream. trial_streams = [] trial_colors = [] while self.ax_pid.lines: self.ax_pid.lines.pop(0) while self.ax_mean_plots.lines: self.ax_mean_plots.lines.pop(0) groups_by_trial = [] all_groups = set() ntrials = len(trials) vals = np.empty(ntrials) concs = np.empty_like(vals) if trials: a = max([1. / len(trials), .25]) for i, tn in enumerate(trials): color = self.trial_group_list.get_trial_color(tn) groups = self.trial_group_list.get_trial_groups(tn) trial_colors.append(color) groups_by_trial.append(groups) all_groups.update(groups) trial = self.data.return_trial(tn, padding=padding) stream = remove_stream_trend(trial.streams['sniff'], (0, padding[0])) stream -= stream[0:padding[0]].min() # TODO: remove baseline (N2) trial average from this. trial_streams.append(stream) self.ax_pid.plot(stream, color=color, alpha=a) conc = trial.trials['odorconc'] baseline = np.mean(stream[:2000]) val = np.mean(stream[3000:4000]) - baseline vals[i] = val concs[i] = conc self.ax_mean_plots.plot(conc, val, '.', color=color) minlen = 500000000 for i in trial_streams: minlen = min(len(i), minlen) streams_array = np.empty((ntrials, minlen)) for i in xrange(ntrials): streams_array[i, :] = trial_streams[i][:minlen] for g in all_groups: mask = np.empty(ntrials, dtype=bool) for i in xrange(ntrials): groups = groups_by_trial[i] mask[i] = g in groups c = concs[mask] groupstreams = streams_array[mask] if len(np.unique(c)) < 2: self.ax_pid.plot(groupstreams.mean(axis=0), color='k', linewidth=2) else: v = vals[mask] a, b, _, _, _ = stats.linregress(c, v) color = self.trial_group_list.get_group_color(g) minn, maxx = self.ax_mean_plots.get_xlim() x = np.array([minn, maxx]) self.ax_mean_plots.plot(x, a * x + b, color=color) self.ax_pid.relim() self.ax_mean_plots.set_yscale('log') self.ax_mean_plots.set_xscale('log') self.ax_mean_plots.relim() self.canvas.draw() @QtCore.pyqtSlot() def _select_none_filters(self): for filter in self.filters: filter.filterChanged.disconnect(self._filters_changed) filter.clearSelection() filter.filterChanged.connect(self._filters_changed) self._filters_changed() @QtCore.pyqtSlot() def _select_all_filters(self): for filter in self.filters: filter.filterChanged.disconnect(self._filters_changed) filter.selectAll() filter.filterChanged.connect(self._filters_changed) self._filters_changed()