def initUI(self): """"Assembles the basic Gui layout, status bar, menubar toolbar etc.""" # status bar self.statusBar().showMessage('Ready') # actions soundAction = QtGui.QAction(QtGui.QIcon.fromTheme('media-playback-start'), 'Play Sound', self) soundAction.setShortcut('Ctrl+S') soundAction.setStatusTip('Play data as sound') soundAction.triggered.connect(self.playSound) exitAction = QtGui.\ QAction(QtGui.QIcon.fromTheme('window-close'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(QtGui.qApp.quit) openAction = QtGui.\ QAction(QtGui.QIcon.fromTheme('document-open'), 'Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open an arf file') openAction.triggered.connect(self.showDialog) exportAction = QtGui.QAction(QtGui.QIcon.fromTheme('document-save-as'), 'Export checked', self) exportAction.setShortcut('Ctrl+e') exportAction.setStatusTip('Export dataset as wav') exportAction.triggered.connect(self.export) plotcheckedAction = QtGui.QAction(QtGui.QIcon.fromTheme('face-smile'), 'Plot checked', self) plotcheckedAction.setShortcut('Ctrl+k') plotcheckedAction.setStatusTip('plot checked') plotcheckedAction.triggered.connect(self.toggleplotchecked) self.plotcheckedAction = plotcheckedAction refreshAction = QtGui.QAction(QtGui.QIcon.fromTheme('view-refresh'), 'Refresh Data View', self) refreshAction.setShortcut('Ctrl+r') refreshAction.setStatusTip('Refresh Data View') refreshAction.triggered.connect(self.refresh_data_view) labelAction = QtGui.QAction(QtGui.QIcon.fromTheme('insert-object'), 'Add Label', self) labelAction.setVisible(False) labelAction.setShortcut('Ctrl+l') labelAction.setStatusTip('Add label entry to current group') labelAction.triggered.connect(self.add_label) self.labelAction = labelAction addPlotAction = QtGui.QAction('Add Plot', self) addPlotAction.setVisible(False) addPlotAction.setStatusTip('Add checked datasets to current plot') addPlotAction.triggered.connect(self.add_plot) self.addPlotAction = addPlotAction # menubar menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(exitAction) fileMenu.addAction(openAction) fileMenu.addAction(exportAction) fileMenu.addAction(plotcheckedAction) fileMenu.addAction(refreshAction) # toolbar self.toolbar = self.addToolBar('Toolbar') self.toolbar.addAction(exitAction) self.toolbar.addAction(openAction) self.toolbar.addAction(soundAction) self.toolbar.addAction(exportAction) self.toolbar.addAction(plotcheckedAction) self.toolbar.addAction(refreshAction) self.toolbar.addAction(labelAction) self.toolbar.addAction(addPlotAction) # file tree self.tree_view = DataTreeView() self.tree_view.currentItemChanged.connect(self.selectEntry) if self.current_file: self.populateTree() # tree_toolbar self.tree_toolbar = treeToolBar(self.tree_view) #attribute table self.attr_table = QtGui.QTableWidget(10, 2) self.attr_table.setHorizontalHeaderLabels(('key','value')) #plot region self.data_layout = pg.GraphicsLayoutWidget() self.subplots=[] #settings panel self.settings_panel = settingsPanel() # final steps self.area = pgd.DockArea() tree_dock = pgd.Dock("Tree", size=(200, 100)) data_dock = pgd.Dock("Data", size=(500, 200)) attr_table_dock = pgd.Dock("Attributes", size=(200, 50)) settings_dock = pgd.Dock('Settings', size=(150,1)) self.area.addDock(tree_dock, 'left') self.area.addDock(data_dock, 'right') self.area.addDock(attr_table_dock, 'bottom', tree_dock) self.area.addDock(settings_dock, 'bottom', attr_table_dock) tree_dock.addWidget(self.tree_view) tree_dock.addWidget(self.tree_toolbar) tree_dock.addAction(exitAction) data_dock.addWidget(self.data_layout) attr_table_dock.addWidget(self.attr_table) settings_dock.addWidget(self.settings_panel) self.settings_panel.show() self.setCentralWidget(self.area) self.setWindowTitle('arfview') self.resize(1300, 700) self.show()
class MainWindow(QtGui.QMainWindow): '''the main window of the program''' def __init__(self): super(MainWindow, self).__init__() self.current_file = None self.open_files = [] # TODO replace current_file with list self.plotchecked = False self.initUI() def initUI(self): """"Assembles the basic Gui layout, status bar, menubar toolbar etc.""" # status bar self.statusBar().showMessage('Ready') # actions soundAction = QtGui.QAction(QtGui.QIcon.fromTheme('media-playback-start'), 'Play Sound', self) soundAction.setShortcut('Ctrl+S') soundAction.setStatusTip('Play data as sound') soundAction.triggered.connect(self.playSound) exitAction = QtGui.\ QAction(QtGui.QIcon.fromTheme('window-close'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(QtGui.qApp.quit) openAction = QtGui.\ QAction(QtGui.QIcon.fromTheme('document-open'), 'Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open an arf file') openAction.triggered.connect(self.showDialog) exportAction = QtGui.QAction(QtGui.QIcon.fromTheme('document-save-as'), 'Export checked', self) exportAction.setShortcut('Ctrl+e') exportAction.setStatusTip('Export dataset as wav') exportAction.triggered.connect(self.export) plotcheckedAction = QtGui.QAction(QtGui.QIcon.fromTheme('face-smile'), 'Plot checked', self) plotcheckedAction.setShortcut('Ctrl+k') plotcheckedAction.setStatusTip('plot checked') plotcheckedAction.triggered.connect(self.toggleplotchecked) self.plotcheckedAction = plotcheckedAction refreshAction = QtGui.QAction(QtGui.QIcon.fromTheme('view-refresh'), 'Refresh Data View', self) refreshAction.setShortcut('Ctrl+r') refreshAction.setStatusTip('Refresh Data View') refreshAction.triggered.connect(self.refresh_data_view) labelAction = QtGui.QAction(QtGui.QIcon.fromTheme('insert-object'), 'Add Label', self) labelAction.setVisible(False) labelAction.setShortcut('Ctrl+l') labelAction.setStatusTip('Add label entry to current group') labelAction.triggered.connect(self.add_label) self.labelAction = labelAction addPlotAction = QtGui.QAction('Add Plot', self) addPlotAction.setVisible(False) addPlotAction.setStatusTip('Add checked datasets to current plot') addPlotAction.triggered.connect(self.add_plot) self.addPlotAction = addPlotAction # menubar menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(exitAction) fileMenu.addAction(openAction) fileMenu.addAction(exportAction) fileMenu.addAction(plotcheckedAction) fileMenu.addAction(refreshAction) # toolbar self.toolbar = self.addToolBar('Toolbar') self.toolbar.addAction(exitAction) self.toolbar.addAction(openAction) self.toolbar.addAction(soundAction) self.toolbar.addAction(exportAction) self.toolbar.addAction(plotcheckedAction) self.toolbar.addAction(refreshAction) self.toolbar.addAction(labelAction) self.toolbar.addAction(addPlotAction) # file tree self.tree_view = DataTreeView() self.tree_view.currentItemChanged.connect(self.selectEntry) if self.current_file: self.populateTree() # tree_toolbar self.tree_toolbar = treeToolBar(self.tree_view) #attribute table self.attr_table = QtGui.QTableWidget(10, 2) self.attr_table.setHorizontalHeaderLabels(('key','value')) #plot region self.data_layout = pg.GraphicsLayoutWidget() self.subplots=[] #settings panel self.settings_panel = settingsPanel() # final steps self.area = pgd.DockArea() tree_dock = pgd.Dock("Tree", size=(200, 100)) data_dock = pgd.Dock("Data", size=(500, 200)) attr_table_dock = pgd.Dock("Attributes", size=(200, 50)) settings_dock = pgd.Dock('Settings', size=(150,1)) self.area.addDock(tree_dock, 'left') self.area.addDock(data_dock, 'right') self.area.addDock(attr_table_dock, 'bottom', tree_dock) self.area.addDock(settings_dock, 'bottom', attr_table_dock) tree_dock.addWidget(self.tree_view) tree_dock.addWidget(self.tree_toolbar) tree_dock.addAction(exitAction) data_dock.addWidget(self.data_layout) attr_table_dock.addWidget(self.attr_table) settings_dock.addWidget(self.settings_panel) self.settings_panel.show() self.setCentralWidget(self.area) self.setWindowTitle('arfview') self.resize(1300, 700) self.show() def toggleplotchecked(self): self.plotchecked = not self.plotchecked print('plot checked: ' + str(self.plotchecked)) if self.plotchecked: self.plotcheckedAction.setIcon(QtGui.QIcon.fromTheme('face-cool')) self.plotcheckedAction.setStatusTip('click to turn check mode off') self.plotcheckedAction.setText('check mode is on') self.plotcheckedAction.setIconText('check mode is on') self.addPlotAction.setVisible(True) else: self.plotcheckedAction.setIcon(QtGui.QIcon.fromTheme('face-smile')) self.plotcheckedAction.setStatusTip('click to turn check mode on') self.plotcheckedAction.setText('check mode is off') self.plotcheckedAction.setIconText('check mode is off') self.addPlotAction.setVisible(False) def export(self): items = self.tree_view.all_checked_dataset_elements() if not items: return savedir, filename = os.path.split(items[0].file.filename) savepath = os.path.join(savedir,os.path.splitext(filename)[0] + '_' + items[0].name.replace('/','_')) print(savepath) fname, fileextension = QtGui.QFileDialog.\ getSaveFileName(self, 'Save data as', savepath, 'wav (*.wav);;text (*.csv, *.dat)') for i,item in enumerate(items): if 'datatype' in item.attrs.keys() and item.attrs['datatype'] < 1000: if i: fname = os.path.join(savedir,os.path.splitext(filename)[0] + '_' + item.name.replace('/','_')) export(item, fileextension.split(' ')[0], fname) def playSound(self): item = self.tree_view.currentItem().getData() playSound(item, self) def showDialog(self): extensions = '*.arf *.hdf5 *.h5 *.mat *.wav *.lbl' #added because not all of arfx compiles on OS X try: from arfx import pcmio extensions += ' *.pcm' except ImportError: pass fname, fileextension = QtGui.QFileDialog.\ getOpenFileName(self, 'Open file', '.', extensions) if not fname: return print(fileextension) ext = os.path.splitext(fname)[-1] if ext not in ('.arf','.hdf5','.h5','.mat'): if ext in ('.lbl', '.wav'): temp_h5f = createtemparf(fname) elif ext in ('.pcm', '.pcm_seq2'): # reversing value and key to access type number from datatype_name sampled_types = {value:key for key,value in named_types.items() if key > 0 and key < 1000} datatype_name,ok = QtGui.QInputDialog.getItem(self, "", "Select datatype of file", sampled_types.keys()) if not ok: return temp_h5f = createtemparf(fname, datatype=sampled_types[datatype_name]) fname = temp_h5f.file.filename print("%s opened" % (fname)) self.statusBar().showMessage("%s opened" % (fname)) self.current_file = h5py.File(str(fname)) self.populateTree() # selects first entry if first file opened item=self.tree_view.topLevelItem(0) if item.getData().file.filename == fname: #self.selectEntry(item.child(0)) self.tree_view.setCurrentItem(item.child(0)) def populateTree(self): f = self.current_file root = f['/'] self.tree_view.recursivePopulateTree(root) def refresh_data_view(self): checked_datasets = self.tree_view.all_checked_dataset_elements() if len(checked_datasets) > 0 and self.plotchecked: self.plot_dataset_list(checked_datasets, self.data_layout) else: item = self.tree_view.currentItem().getData() if type(item) == h5py.Dataset: datasets = [item] else: datasets = [x for x in item.values() if type(x) == h5py.Dataset] self.plot_dataset_list(datasets, self.data_layout) def add_plot(self): checked_datasets = self.tree_view.all_checked_dataset_elements() if len(checked_datasets) > 0 and self.plotchecked: new_layout = self.data_layout.addLayout(row=len(self.subplots),col=0) self.plot_dataset_list(checked_datasets, new_layout) def selectEntry(self, treeItem): item = treeItem.getData() populateAttrTable(self.attr_table, item) if not self.plotchecked: self.refresh_data_view() if (isinstance(item, h5py.Dataset) or isinstance(item, h5py.Group) and item.name != '/'): self.labelAction.setVisible(True) else: self.labelAction.setVisible(False) def add_label(self): item = self.tree_view.currentItem() if isinstance(item.getData(), h5py.Group): lbl_parent = item elif isinstance(item.getData(), h5py.Dataset): lbl_parent = item.parent() lbl_rec = np.zeros((0,),dtype=[('name', 'a8'), ('start',float), ('stop', float)]) dset_name = 'lbl' #naming new label dataset if 'lbl' is already in group idx = 1 while dset_name in lbl_parent.getData().keys(): dset_name = 'lbl_%d' %(idx) idx += 1 dset = lbl_parent.getData().create_dataset(dset_name, data=lbl_rec, maxshape=(None,)) dset.attrs.create('units','ms') dset.attrs.create('datatype',2002) self.tree_view.add(dset, parent_node=lbl_parent) self.refresh_data_view() def plot_dataset_list(self, dataset_list, data_layout, append=False): ''' plots a list of datasets to a data layout''' data_layout.clear() if not append: self.subplots = [] # rasterQPainterPath = QtGui.QPainterPath().addRect(-.1,-5,.2,1) # TODO make a better raster # shape that works toes = [] for dataset in dataset_list: print(dataset) if 'datatype' not in dataset.attrs.keys(): print('{} is not an arf dataset'.format(repr(dataset))) if os.path.basename(dataset.name) == 'jill_log': print(dataset.value) continue '''sampled data''' if dataset.attrs['datatype'] < 1000: # sampled data if (self.settings_panel.oscillogram_check.checkState() ==QtCore.Qt.Checked): pl = downsamplePlot(dataset, title=dataset.name, name=str(len(self.subplots))) data_layout.addItem(pl,row=len(self.subplots), col=0) pl.setXRange(0, dataset.size/float(dataset.attrs['sampling_rate'])) pl.setYRange(np.min(dataset), np.max(dataset)) self.subplots.append(pl) pl.showGrid(x=True, y=True) ''' simple events ''' elif utils.is_simple_event(dataset): if dataset.attrs['units'] == 'ms': data = dataset.value / 1000. elif dataset.attrs['units'] == 'samples': data = dataset.value / dataset.attrs['sampling_rate'] else: data = dataset.value if (self.settings_panel.raster_check.checkState()==QtCore.Qt.Checked or self.settings_panel.psth_check.checkState()==QtCore.Qt.Checked or self.settings_panel.isi_check.checkState()==QtCore.Qt.Checked): toes.append(data) continue ''' complex event ''' elif utils.is_complex_event(dataset): if (self.settings_panel.label_check.checkState() ==QtCore.Qt.Checked): #creating new extensible dataset if not extensible if dataset.maxshape != (None,): data = dataset[:] name = dataset.name group= dataset.parent attributes = dataset.attrs del group[name] del dataset dataset = arf.create_dataset(group, name, data, maxshape=(None,),**attributes) pl = labelPlot(dataset, title=dataset.name, name=str(len(self.subplots))) data_layout.addItem(pl, row=len(self.subplots), col=0) pl.showLabel('left', show=False) self.subplots.append(pl) else: print('I don\'t know how to plot {} of type {} \ with datatype {}'.format(dataset, type(dataset), dataset.attrs['datatype'])) continue '''adding spectrograms''' if dataset.attrs['datatype'] in [0, 1]: # show spectrogram if (self.settings_panel.spectrogram_check.checkState() ==QtCore.Qt.Checked): #getting spectrogram settings sr = float(dataset.attrs['sampling_rate']) win_size_text = self.settings_panel.win_size.text() t_step_text = self.settings_panel.step.text() min_text = self.settings_panel.freq_min.text() max_text = self.settings_panel.freq_max.text() if win_size_text: win_size = int(float(win_size_text)) else: win_size = self.settings_panel.defaults['win_size'] self.settings_panel.win_size.setText(str(win_size)) if t_step_text: t_step = int(float(t_step_text) * sr/1000.) else: t_step = self.settings_panel.defaults['step'] self.settings_panel.win_size.setText(str(int(tstep*1000))) if min_text: freq_min = int(min_text) else: freq_min = self.settings_panel.defaults['freq_min'] self.settings_panel.freq_min.setText(str(freq_min)) if max_text: freq_max = int(max_text) else: freq_max = self.settings_panel.defaults['freq_max'] self.settings_panel.freq_max.setText(str(freq_max)) window_name = self.settings_panel.window.currentText() if window_name == "Hann": window = scipy.signal.hann(win_size) elif window_name == "Bartlett": window = scipy.signal.bartlett(win_size) elif window_name == "Blackman": window = scipy.signal.blackman(win_size) elif window_name == "Boxcar": window = scipy.signal.boxcar(win_size) elif window_name == "Hamming": window = scipy.signal.hamming(win_size) elif window_name == "Parzen": window = scipy.signal.parzen(win_size) #computing and interpolating image Pxx = libtfr.stft(dataset,w=window,step=t_step) spec = np.log(Pxx.T) res_factor = 1.0 #factor by which resolution is increased # spec = interpolate_spectrogram(spec, res_factor=res_factor) #making color lookup table pos = np.linspace(0,1,7) color = np.array([[100,100,255,255],[0,0,255,255],[0,255,255,255],[0,255,0,255], [255,255,0,255],[255,0,0,255],[100,0,0,255]], dtype=np.ubyte) color_map = pg.ColorMap(pos,color) lut = color_map.getLookupTable(0.0,1.0,256) img = pg.ImageItem(spec,lut=lut) #img.setLevels((-5, 10)) pl = data_layout.addPlot(name=str(len(self.subplots)), row=len(self.subplots), col=0) self.subplots.append(pl) pl.addItem(img) image_scale = t_step/sr/res_factor img.setScale(image_scale) df = sr/float(win_size) plot_scale = df/res_factor/image_scale pl.getAxis('left').setScale(plot_scale) pl.setXRange(0, dataset.size / dataset.attrs['sampling_rate']) pl.setYRange(freq_min/plot_scale, freq_max/plot_scale) pl.setMouseEnabled(x=True, y=False) if toes: if self.settings_panel.raster_check.checkState()==QtCore.Qt.Checked: pl= rasterPlot(toes) data_layout.addItem(pl, row=len(self.subplots), col=0) pl.showLabel('left', show=False) self.subplots.append(pl) if self.settings_panel.psth_check.checkState()==QtCore.Qt.Checked: all_toes = np.zeros(sum(len(t) for t in toes)) k=0 for t in toes: all_toes[k:k+len(t)] = t k += len(t) if self.settings_panel.psth_bin_size.text(): bin_size = float(self.settings_panel.psth_bin_size.text())/1000. else: bin_size = .01 bins = np.arange(all_toes.min(),all_toes.max()+bin_size,bin_size) y,x = np.histogram(all_toes,bins=bins) psth = pg.PlotCurveItem(x, y, stepMode=True, fillLevel=0, brush=(0, 0, 255, 80)) pl = data_layout.addPlot(row=len(self.subplots), col=0) pl.addItem(psth) pl.setMouseEnabled(y=False) self.subplots.append(pl) if self.settings_panel.isi_check.checkState()==QtCore.Qt.Checked: isis = np.zeros(sum(len(t)-1 for t in toes)) k=0 for t in toes: isis[k:k+len(t)-1] = np.diff(t) k += len(t)-1 if self.settings_panel.psth_bin_size.text(): bin_size = float(self.settings_panel.psth_bin_size.text())/1000. else: bin_size = .01 bins = np.arange(isis.min(),isis.max()+bin_size,bin_size) y,x = np.histogram(isis,bins=bins,normed=True) isi_hist = pg.PlotCurveItem(x, y, stepMode=True, fillLevel=0, brush=(0, 0, 255, 80)) pl = data_layout.addPlot(row=len(self.subplots), col=0) pl.addItem(isi_hist) pl.setMouseEnabled(y=False) self.subplots.append(pl) '''linking x axes''' masterXLink = None for pl in self.subplots: if not masterXLink: masterXLink = pl pl.setXLink(masterXLink)