class MplWidget(QtGui.QWidget): def __init__(self, parent=None): super(MplWidget, self).__init__(parent) self.figure = Figure() self.ax = self.figure.add_subplot(111) self.canvas = FigureCanvas(self.figure) self.toolbar = NavigationToolbar(self.canvas, self) layout = QtGui.QVBoxLayout() layout.addWidget(self.toolbar) layout.addWidget(self.canvas) self.setLayout(layout) self.cb = None self.im = None self.imsz = None def imshow(self, img): if self.im: self.imsz = self.im.get_size() newsz = img.shape self.im.set_data(img) if self.imsz[0] != newsz[0] or self.imsz[1] != newsz[1]: # update extent self.im.set_extent((-0.5, newsz[1]-0.5, newsz[0]-0.5, -0.5)) else: self.im = self.ax.imshow(img,interpolation='none') if self.cb: self.im.autoscale() else: self.cb = self.figure.colorbar(self.im) report_pixel = lambda x, y : "(%6.3f, %6.3f) %.3f" % (x,y, img[np.floor(y+0.5),np.floor(x+0.5)]) self.ax.format_coord = report_pixel self.canvas.draw() self.canvas.flush_events()
class RoachPhaseStreamWindow(QMainWindow): thresholdClicked = QtCore.pyqtSignal() phaseSnapClicked = QtCore.pyqtSignal() phaseTimestreamClicked = QtCore.pyqtSignal() resetRoach = QtCore.pyqtSignal(int) def __init__(self,roach,config,parent=None): """ Window for showing snapshot of phase timestream of resonators INPUTS: roach - A RoachStateMachine Object. We need this to access all the relevent settings config - ConfigParser object parent - Leave as default """ QMainWindow.__init__(self,parent=parent) self._want_to_close = False self.roach=roach self.roachNum = self.roach.num self.config = config self.setWindowTitle('r'+str(self.roachNum)+': Phase Timestream') self.create_main_frame() self.snapDataList = [] self.phaseNoiseDataList = [] self.oldPhaseNoiseDataList = [] self.thresholdDataList = [] self.roach.snapPhase.connect(self.plotSnap) self.roach.timestreamPhase.connect(self.plotPhaseNoise) def initFreqs(self): """ After we've loaded the frequency file in RoachStateMachine object then we can initialize some GUI elements """ freqs = self.roach.roachController.freqList ch=self.spinbox_channel.value() self.spinbox_channel.setRange(0,len(freqs)-1) self.label_freq.setText('Freq: '+str(freqs[ch]/1.e9)+' GHz') if len(self.snapDataList)!=len(freqs): self.snapDataList = [None]*len(freqs) if len(self.phaseNoiseDataList)!=len(freqs): self.phaseNoiseDataList = [None]*len(freqs) if len(self.oldPhaseNoiseDataList)!=len(freqs): self.oldPhaseNoiseDataList = [None]*len(freqs) def initThresh(self): """ After we've loaded the thresholds we can show them Also everytime we change the channel we need to replot """ try: ch=self.spinbox_channel.value() #thresh = self.roach.roachController.thresholds[ch] thresh = self.thresholdDataList[ch] self.label_thresh.setText('Threshold: '+str(thresh)+' deg') self.plotSnap() except: pass def appendThresh(self, thresholds): ''' This function is called whenever the roach finishes a load threshold command INPUTS: thresholds - [nFreqs, 1] list of thresholds for each channel in radians ''' self.thresholdDataList = thresholds self.initThresh() def plotPhaseNoise(self,ch=None, data=None,**kwargs): #self.spinbox_channel.setEnabled(False) currentCh = self.spinbox_channel.value() if ch is None: ch=currentCh if data is not None: self.appendPhaseNoiseData(ch,data) if self.isVisible() and ch==currentCh: self.makePhaseNoisePlot(**kwargs) self.draw() #self.spinbox_channel.setEnabled(True) def appendPhaseNoiseData(self, ch, data): fftlen = self.config.getint('Roach '+str(self.roachNum),'nLongsnapFftSamples') nFftAvg = int(np.floor(len(data)/fftlen)) noiseData = np.zeros(fftlen) data = np.reshape(data[:nFftAvg*fftlen],(nFftAvg,fftlen)) noiseData=np.fft.rfft(data) noiseData=np.abs(noiseData)**2 #power spectrum noiseData = 1.*np.average(noiseData,axis=0)/fftlen if np.all(noiseData>0): print 'Adding noise Data' if self.phaseNoiseDataList[ch] is not None: print 'adding old noise data' self.oldPhaseNoiseDataList[ch] = np.copy(self.phaseNoiseDataList[ch]) self.phaseNoiseDataList[ch]=noiseData else: print "Phase noise was all zeros!" def makePhaseNoisePlot(self, **kwargs): ch = self.spinbox_channel.value() fftlen = self.config.getint('Roach '+str(self.roachNum),'nLongsnapFftSamples') if self.oldPhaseNoiseDataList[ch] is not None: ydata = np.copy(self.oldPhaseNoiseDataList[ch]) dt = 1.*self.roach.roachController.params['nChannelsPerStream']/self.roach.roachController.params['fpgaClockRate'] x = np.fft.rfftfreq(fftlen,dt) self.line2.set_data(x,ydata) self.ax1.relim() self.ax1.autoscale_view(True,True,True) else: self.line2.set_data([],[]) if self.phaseNoiseDataList[ch] is not None: ydata = np.copy(self.phaseNoiseDataList[ch]) dt = 1.*self.roach.roachController.params['nChannelsPerStream']/self.roach.roachController.params['fpgaClockRate'] x = np.fft.rfftfreq(fftlen,dt) self.line1.set_data(x,ydata) self.ax1.relim() self.ax1.autoscale_view(True,True,True) else: self.line1.set_data([],[]) def phaseTimeStream(self): """ This function executes when you press the collect phase timestream button. After running any commands that need running, it gets a new phase timestream and plots the noise Works similiarly to phaseSnapShot() """ ch=self.spinbox_channel.value() timelen = self.config.getfloat('Roach '+str(self.roachNum),'longsnaptime') QtCore.QMetaObject.invokeMethod(self.roach, 'getPhaseStream', Qt.QueuedConnection, QtCore.Q_ARG(int, ch),QtCore.Q_ARG(float, timelen)) self.phaseTimestreamClicked.emit() def plotSnap(self,ch=None, data=None,**kwargs): self.spinbox_channel.setEnabled(False) currentCh = self.spinbox_channel.value() if ch is None: ch=currentCh if data is not None: self.appendSnapData(ch,data) if self.isVisible() and ch==currentCh: self.makeSnapPlot(**kwargs) self.draw() self.spinbox_channel.setEnabled(True) def appendSnapData(self,ch,data): self.snapDataList[ch]=data def makeSnapPlot(self,**kwargs): ch = self.spinbox_channel.value() self.ax2.clear() if self.snapDataList[ch] is not None: snapDict = self.snapDataList[ch] t = np.asarray(snapDict['time'])*1.e6 data=np.asarray(snapDict['phase']) #print snapDict['trig'] #print np.where(np.asarray(snapDict['time'])) #print np.where(np.asarray(snapDict['time'])>0) trig=np.asarray(snapDict['trig']) data*=180./np.pi fmt = 'b.-' self.ax2.plot(t, data, fmt,**kwargs) print 'nPhotons: ',np.sum(trig) self.ax2.plot(t[np.where(trig)], data[np.where(trig)], 'ro') median=np.median(data) self.label_median.setText('Median: '+str(median)+' deg') self.ax2.axhline(y=median,color='k') try: #thresh = self.roach.roachController.thresholds[ch]*180./np.pi thresh = self.thresholdDataList[ch] thresh*=180./np.pi #self.ax2.axhline(y=median-thresh,color='r') self.ax2.axhline(y=median+thresh,color='r') except: pass self.ax2.set_xlabel('Time [us]') self.ax2.set_ylabel('Phase [deg]') def phaseSnapShot(self): """ This function executes when you press the phase snap button. After running any commands that need running, it gets a new phase snap shot and plots it The way it works is: The RoachStateMachine object is told that we want to run the function getPhaseFromSnap() But it won't run unless the roach thread is in it's event loop. We emit a signal to the HighTemplar GUI telling it we want the phase snap shot --That's the end of this function-- (but next...) HighTemplar tells the RoachStateMachine object to add all commands (as if you clicked a button 1 below load thresholds) Then HighTemplar starts the roach thread's event loop The roach thread automatically starts executing any needed commands in it's queue (ie. loadFreq, DefineLUT, etc..) When the commands are done executing it executes anything waiting for the thread event loop (ie. getPhaseFromSnap()) getPhaseFromSnap() runs on the RoachStateMachine object and when done emits a snapPhase signal with the data This window object sees that signal and updates the plot """ ch=self.spinbox_channel.value() QtCore.QMetaObject.invokeMethod(self.roach, 'getPhaseFromSnap', Qt.QueuedConnection, QtCore.Q_ARG(int, ch)) self.phaseSnapClicked.emit() def create_main_frame(self): """ Makes GUI elements on the window """ self.main_frame = QWidget() self.dpi = 100 self.fig = Figure((9.0, 5.0), dpi=self.dpi) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) self.ax1 = self.fig.add_subplot(211) self.ax1.set_ylabel('Noise Power Spectrum') self.ax1.set_xlabel('f [Hz]') self.line2, = self.ax1.loglog([],[],color='cyan') self.line1, = self.ax1.loglog([],[],color='blue') # line 1 on top of line 2 self.ax2 = self.fig.add_subplot(212) self.ax2.set_xlabel('Time [us]') self.ax2.set_ylabel('Phase [Deg]') # Create the navigation toolbar, tied to the canvas self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame) label_channel = QLabel('Channel:') self.spinbox_channel = QSpinBox() #initializes to 0 self.spinbox_channel.setRange(0,0) #set the range after we read the freq file self.spinbox_channel.setWrapping(True) self.spinbox_channel.valueChanged.connect(lambda x: self.plotSnap()) self.spinbox_channel.valueChanged.connect(lambda x: self.plotPhaseNoise()) self.spinbox_channel.valueChanged.connect(lambda x: self.initFreqs()) self.spinbox_channel.valueChanged.connect(lambda x: self.initThresh()) self.label_freq = QLabel('Freq: 0 GHz') self.label_freq.setMinimumWidth(150) self.label_freq.setMaximumWidth(150) self.label_thresh = QLabel('Thresh: 0 deg') self.label_thresh.setMinimumWidth(150) self.label_thresh.setMaximumWidth(150) self.label_median = QLabel('Median: 0 deg') button_snapPhase = QPushButton("Phase Snapshot") button_snapPhase.setEnabled(True) button_snapPhase.clicked.connect(self.phaseSnapShot) numSnapsThresh = self.config.getint('Roach '+str(self.roachNum),'numsnaps_thresh') spinbox_numSnapsThresh = QSpinBox() spinbox_numSnapsThresh.setValue(numSnapsThresh) spinbox_numSnapsThresh.setRange(1,100) spinbox_numSnapsThresh.setSuffix(" *2 msec") spinbox_numSnapsThresh.setWrapping(False) spinbox_numSnapsThresh.setButtonSymbols(QAbstractSpinBox.NoButtons) spinbox_numSnapsThresh.setCorrectionMode(QAbstractSpinBox.CorrectToNearestValue) spinbox_numSnapsThresh.valueChanged.connect(partial(self.changedSetting,'numsnaps_thresh')) threshSigs = self.config.getfloat('Roach '+str(self.roachNum),'numsigs_thresh') spinbox_threshSigs = QDoubleSpinBox() spinbox_threshSigs.setValue(threshSigs) spinbox_threshSigs.setRange(0,100) spinbox_threshSigs.setSuffix(" sigmas") spinbox_threshSigs.setWrapping(False) spinbox_threshSigs.setButtonSymbols(QAbstractSpinBox.NoButtons) spinbox_threshSigs.setCorrectionMode(QAbstractSpinBox.CorrectToNearestValue) spinbox_threshSigs.valueChanged.connect(partial(self.changedSetting,'numsigs_thresh')) spinbox_threshSigs.valueChanged.connect(lambda x: self.resetRoach.emit(RoachStateMachine.LOADTHRESHOLD)) # reset state of roach button_loadThresh = QPushButton("Load Thresholds") button_loadThresh.setEnabled(True) button_loadThresh.clicked.connect(self.thresholdClicked) longSnapTime = self.config.getfloat('Roach '+str(self.roachNum),'longsnaptime') spinbox_longSnapTime = QDoubleSpinBox() spinbox_longSnapTime.setValue(longSnapTime) spinbox_longSnapTime.setRange(0,1000) spinbox_longSnapTime.setSuffix(" seconds") spinbox_longSnapTime.setWrapping(False) spinbox_longSnapTime.setButtonSymbols(QAbstractSpinBox.NoButtons) spinbox_longSnapTime.setCorrectionMode(QAbstractSpinBox.CorrectToNearestValue) spinbox_longSnapTime.valueChanged.connect(partial(self.changedSetting,'longsnaptime')) button_longSnap = QPushButton("Collect Phase Timestream") button_longSnap.setEnabled(True) button_longSnap.clicked.connect(self.phaseTimeStream) vbox_plot = QVBoxLayout() vbox_plot.addWidget(self.canvas) vbox_plot.addWidget(self.mpl_toolbar) hbox_ch = QHBoxLayout() hbox_ch.addWidget(label_channel) hbox_ch.addWidget(self.spinbox_channel) hbox_ch.addWidget(self.label_freq) hbox_ch.addWidget(self.label_thresh) hbox_ch.addWidget(self.label_median) hbox_ch.addWidget(button_snapPhase) hbox_ch.addStretch() hbox_thresh = QHBoxLayout() hbox_thresh.addWidget(spinbox_numSnapsThresh) hbox_thresh.addWidget(spinbox_threshSigs) hbox_thresh.addWidget(button_loadThresh) hbox_thresh.addStretch() hbox_phaseTimestream = QHBoxLayout() hbox_phaseTimestream.addWidget(spinbox_longSnapTime) hbox_phaseTimestream.addWidget(button_longSnap) hbox_phaseTimestream.addStretch() vbox1 = QVBoxLayout() vbox1.addLayout(vbox_plot) vbox1.addLayout(hbox_ch) vbox1.addLayout(hbox_thresh) vbox1.addLayout(hbox_phaseTimestream) self.main_frame.setLayout(vbox1) self.setCentralWidget(self.main_frame) def draw(self): #print 'r'+str(self.roachNum)+' drawing data - '+str(self.counter) self.canvas.draw() self.canvas.flush_events() def changedSetting(self,settingID,setting): """ When a setting is changed, reflect the change in the config object which is shared across all GUI elements. INPUTS: settingID - the key in the configparser setting - the value """ self.config.set('Roach '+str(self.roachNum),settingID,str(setting)) #If we don't force the setting value to be a string then the configparser has trouble grabbing the value later on for some unknown reason newSetting = self.config.get('Roach '+str(self.roachNum),settingID) print 'setting ',settingID,' to ',newSetting def closeEvent(self, event): if self._want_to_close: event.accept() self.close() else: event.ignore() self.hide()
class mpl_widget(QWidget): def __init__(self, parent=None, mainWidget=None): self._SELECTEDCELLS = list() # container for instances of selected cells, so we can delete them when we want self._SELECTEDCELLS_IJ = list() # container for coords of selected cells, so we can delete them when we want self._SELECTEDCELLLINES = list() # container for instances of selected cells, so we can delete them when we want self._GRIDLINES = None QWidget.__init__(self, parent) self.mainWidget = mainWidget self.create_main_frame() self.mpl_menu = mpl_menu(self) self.shift_is_held = False #self.connect(self.mpl_menu, QtCore.SIGNAL('mySignal'), self.mySlot) #print 'my parent is:', parent self.clear_selection() self.init_tooltips() def init_tooltips(self): self.canvas.setToolTip('If 2D plot => RMB click toggles menu <br> - RMB click selects cell <br> - selected cells are drawn with black border') self.grid_cb.setToolTip('If 2D plot => show computational grid <br> If 1D plot => show normal gridlines') self.cbar_button.setToolTip('If 2D plot => controls the color range. <br> Note: <br> - pressing UP and DOWN arrows cycles through colormaps <br> - dragging colorbar with RMB scales the color-range <br> - dragging colorbar with LMB shifts the color-range') self.mpl_toolbar.setToolTip('Shows coordinates (i,j, lat,lon) and data-value(z) under the cursor. <br> if you see <i>>>></i> coordinates are not visible. Enlarge the window') def create_main_frame(self): self.fig = Figure(dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( Qt.ClickFocus ) self.canvas.setFocus() self.mpl_toolbar = myNavigationToolbar(self.canvas, self) self.canvas.mpl_connect('button_press_event', self.on_click) self.canvas.mpl_connect('key_press_event', self.on_key_press) self.canvas.mpl_connect('key_release_event', self.on_key_release) #self.canvas.mpl_connect('button_press_event', self.disable_clicks) self.cbar_button = QPushButton("Color Range") self.cbar_button.setFocusPolicy( Qt.NoFocus ) self.grid_cb = QCheckBox("Show Grid") self.grid_cb.setFocusPolicy( Qt.NoFocus ) self.grid_cb.stateChanged.connect(self.showGrid) vbox = QVBoxLayout() hbox = QHBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas hbox.addWidget(self.mpl_toolbar) hbox.addWidget(self.cbar_button) hbox.addWidget(self.grid_cb) vbox.addLayout(hbox) self.setLayout(vbox) def on_click(self, event): if event.inaxes != self.get_axes()[0]: return #if self.get_axes()[0].format_coord(event.x, event.y) == 'outside data area': return if self.allow_menu(): self.allow_popup_menu = True if self.shift_is_held: self.allow_popup_menu = False point = [int(event.xdata + .5), int(event.ydata + .5)] #print '>>>', point, '\t currently {0} selected'.format(len(self._SELECTEDCELLS)) if event.button == 3 : #if RMB is clicked # working with dialog for transect! if self.mainWidget.transect_dlg: if self.mainWidget.transect_dlg.toogle_show_after_selected_cell: realx, realy = self.get_real_xy(event.xdata, event.ydata, self.mainWidget.detect_variable_dimensions()) realpoint = [realy, realx] #print 'real xy:', realpoint if self.mainWidget.transect_dlg.toogle_show_after_selected_cell == 1: # select point 1 self.allow_popup_menu = False self.mainWidget.transect_dlg.data.set_p1(realpoint) elif self.mainWidget.transect_dlg.toogle_show_after_selected_cell == 2: # select point 2 self.allow_popup_menu = False self.mainWidget.transect_dlg.data.set_p2(realpoint) self.mainWidget.transect_dlg.update() self.mainWidget.transect_dlg.show() # working with dialog for flux! if self.mainWidget.flux_dlg: if self.mainWidget.flux_dlg.toogle_show_after_selected_cell: if self.mainWidget.flux_dlg.toogle_show_after_selected_cell == 1: # select point 1 self.allow_popup_menu = False self.mainWidget.flux_dlg.data.set_p1(point) elif self.mainWidget.flux_dlg.toogle_show_after_selected_cell == 2: # select point 2 self.allow_popup_menu = False self.mainWidget.flux_dlg.data.set_p2(point) self.mainWidget.flux_dlg.update() self.mainWidget.flux_dlg.show() if len(self._SELECTEDCELLS) == 0: # if no cell is selected self.add_selected_cell(point) else: # if some cells are already selected if self.mpl_menu.allow_rmb_select_cells() or self.shift_is_held: # check if this point is already selected: already_selected = False for p in self._SELECTEDCELLS_IJ: if (point[0] == p[0]) and (point[1] == p[1]): already_selected = True print 'cell already selected... is not added' if not already_selected: self.add_selected_cell(point) else: pass #self.clear_selection() #self.add_selected_cell(point) def cells_selected(self): if self._SELECTEDCELLS: return len(self._SELECTEDCELLS) else: return False def add_selected_cell(self, point): ''' point = [i, j]''' print 'selected cell:', point[0], point[1] c = self.draw_picked_cell(point) self._SELECTEDCELLS.append(c) self._SELECTEDCELLS_IJ.append(point) def get_selected_cells_ij(self): return self._SELECTEDCELLS_IJ def clear_selection(self): ''' delete all graphical objects of selected cells redraw canvas ''' print 'clearing stuff' if len(self._SELECTEDCELLLINES) > 0: for line in self._SELECTEDCELLLINES: l = line.pop(0) l.remove() del l del self._SELECTEDCELLLINES[:] #print 'cells ---- before:', len(self._SELECTEDCELLS) if len(self._SELECTEDCELLS) > 0: for cell in self._SELECTEDCELLS: for line in cell: l = line.pop(0) l.remove() del l del self._SELECTEDCELLS[:] #print 'cells ---- left:', len(self._SELECTEDCELLS) #print 'cells-coords ----' #print len(self._SELECTEDCELLS_IJ) if self._SELECTEDCELLS_IJ: for cellcoords in self._SELECTEDCELLS_IJ: #cc = cellcoords.pop(0) #cellcoords.remove() del cellcoords del self._SELECTEDCELLS_IJ[:] #print 'cells ---- left,', len(self._SELECTEDCELLS_IJ) if len(self._SELECTEDCELLS) != 0: raise ValueError('List "self._SELECTEDCELLS" was not flushed') if len(self._SELECTEDCELLLINES) != 0: raise ValueError('List "self._SELECTEDCELLLINES" was not flushed') if len(self._SELECTEDCELLS_IJ) != 0: raise ValueError('List "self._SELECTEDCELLLINES" was not flushed') # update plot self.canvas.draw() #print 'finishing clear: cells left', len(self._SELECTEDCELLS) def showGrid(self, state): if self.fig.axes: current_plot = self.mainWidget.get_plotType() current_plot2D = self.mainWidget.get_plotType_for_timeseries() if state == Qt.Checked: if current_plot == '1D' or (current_plot2D =="2DZT"): self.fig.axes[0].grid(True) elif current_plot == '2D' and (not current_plot2D =="2DZT"): self.draw_pixel_grid(True) else: if current_plot == '1D' or (current_plot2D =="2DZT"): self.fig.axes[0].grid(False) elif current_plot == '2D' and (not current_plot2D =="2DZT"): self.draw_pixel_grid(False) self.canvas.draw() def draw_picked_cell(self, point): x = point[0] y = point[1] ''' approach drawing a patch... not working cell_bnd = patches.Rectangle((x-.5, y-.5), 1, 1, fill=False, edgecolor="black", hatch=None, linewidth=1.) cell_instance = self.fig.axes[0].add_patch(cell_bnd) ''' b_line = [(x-.5, x+.5), (y-.5, y-.5)] r_line = [(x+.5, x+.5), (y-.5, y+.5)] t_line = [(x-.5, x+.5), (y+.5, y+.5)] l_line = [(x-.5, x-.5), (y-.5, y+.5)] cell = [b_line, r_line, t_line, l_line] for i, l in enumerate(cell): ll = self.fig.axes[0].plot(l[0], l[1], 'k-', lw=.8) cell[i] = ll # overwriting current Line2D object with object binded to an axes #self._SELECTEDCELLS.append(cell) # collecting reference to this cell to be able to delete it #self._SELECTEDCELLS_IJ.append(point) # collecting reference to this cell to be able to delete it self.canvas.draw() return cell def draw_line(self, point1, point2): line = [(point1[0], point2[0]), (point1[1], point2[1])] l = self.fig.axes[0].plot(line[0], line[1], 'k-', lw=2) return l def draw_pixel_grid(self, enable=True): if enable: dx = 1 dy = 1 x0 = -.5 y0 = -.5 if self.mainWidget.get_plotType_for_timeseries() == '2DXY': nx = self.mainWidget.get_nX() ny = self.mainWidget.get_nY() elif self.mainWidget.get_plotType_for_timeseries() == '2DZY': nx = self.mainWidget.get_nY() ny = self.mainWidget.get_nZ() elif self.mainWidget.get_plotType_for_timeseries() == '2DZX': nx = self.mainWidget.get_nX() ny = self.mainWidget.get_nZ() self._GRIDLINES = list() for n_hline in np.arange(ny+1): hline = [(x0, x0+nx), (y0+n_hline, y0+n_hline)] l = self.fig.axes[0].plot(hline[0], hline[1], 'k-', lw=.2) self._GRIDLINES.append(l) # collecting reference to this line to be able to delete it for n_vline in np.arange(nx+1): vline = [(x0+n_vline, x0+n_vline), (y0, y0+ny)] l = self.fig.axes[0].plot(vline[0], vline[1], 'k-', lw=.2) self._GRIDLINES.append(l) # collecting reference to this line to be able to delete it if not enable: #print 'deleting lines...' if self._GRIDLINES: # if lines were created #print 'lines are here...' for line in self._GRIDLINES: #print line l = line.pop(0) l.remove() del l self.fig.canvas.draw() def on_key_press(self, event): #print 'key pressed:', event.key if event.key == 'shift': self.shift_is_held = True def on_key_release(self, event): #print 'key released:', event.key if event.key == 'shift': self.shift_is_held = False elif event.key == 'escape': self.clear_selection() def change_coordinate_formatter(self, ax, data2d, bruteforce_flag=None, bruteforce_dims=None): ''' see http://stackoverflow.com/questions/14754931/matplotlib-values-under-cursor ''' numrows, numcols = data2d.shape bruteforce_mode_on = False bruteforce_mode_on = (bruteforce_flag == '2DXY' and bruteforce_dims[-1] and bruteforce_dims[-2]) def format_coord(x, y): col = int(x+0.5) row = int(y+0.5) if not bruteforce_mode_on: if col >= 0 and col < numcols and row >= 0 and row < numrows: #z = data2d[row, col] # sice we have artificially reversed y-coordinate axes, now reverse data! # numrows-1, because if nrows=10 => row=[0:9] z = data2d[numrows-1-row, col] #return 'x=%1.1f y=%1.1f z=%1.6f' % (x, y, z) return 'i=%d j=%d z=%.6f' % (col, row, z) else: #return 'x=%1.4f, y=%1.4f' % (x, y) return 'outside data area' elif bruteforce_flag == '2DXY' and bruteforce_dims[-1] and bruteforce_dims[-2]: ''' our extend in X=[-0.5:numcols-0.5], Y=[-0.5:numrows-0.5], because col,row is cell center! ''' if col >= 0 and col < numcols and row >= 0 and row < numrows: #z = data2d[row, col] # sice we have artificially reversed y-coordinate axes, now reverse data! # numrows-1, because if nrows=10 => row=[0:9] z = data2d[numrows-1-row, col] real_x, real_y = self.get_real_xy(x, y, bruteforce_dims) #return 'x=%1.1f y=%1.1f z=%1.6f' % (x, y, z) #return 'i=%d j=%d z=%.3f x=%.4f y=%.4f' % (col, row, z, real_x, real_y) return 'i=%d j=%d z=%.3f, %s=%.2f %s=%.2f' % ( col, row, z, bruteforce_dims[-1], real_x, bruteforce_dims[-2], real_y) else: #return 'x=%1.4f, y=%1.4f' % (x, y) return 'outside data area' else: raise ValueError('bruteforce_flag can be $None$ or $"2DXY"$. Passed %s' % bruteforce_flag) ax.format_coord = format_coord def allow_menu(self): allow = False #print "self.mainWidget.get_plotType():", self.mainWidget.get_plotType() #print "self.mainWidget.get_plotType_for_timeseries():", self.mainWidget.get_plotType_for_timeseries() if self.mainWidget.get_plotType() == "2D" and not self.mainWidget.get_plotType_for_timeseries() == "2DZT": allow = True return allow def get_real_xy(self, i, j, dimension_list): ''' functions returns values of x,y based on passed indexes i, j ''' if any(dimension_list[-2:-1]) is None: print 'Dimensions X,Y of current variable are not specified (variables that have same name as dimensions not found)' raise ValueError('Dimensions X,Y of current variable are not specified (variables that have same name as dimensions not found)') nc = self.mainWidget.get_selected_ncfile_instance() try: x_var = nc.variables[dimension_list[-1]] y_var = nc.variables[dimension_list[-2]] except: print ('Failed to load variables: {0}, {1}'.format(dimension_list[-1], dimension_list[-2])) raise ValueError('Failed to load variables: {0}, {1}'.format(dimension_list[-1], dimension_list[-2])) x_ratio = (x_var[-1]-x_var[0])/(len(x_var)-1) y_ratio = (y_var[-1]-y_var[0])/(len(y_var)-1) #x[i] = x_var[0]+x_ratio*i #y[j] = y_var[0]+y_ratio*j x = x_var[0] + x_ratio*i y = y_var[0] + y_ratio*j nc.close() return (x, y) def get_axes(self): return self.fig.get_axes() def fast_redraw(self, artist): background = [self.canvas.copy_from_bbox(self.get_axes()[0].bbox)] self.get_axes()[0].draw_artist(artist) self.canvas.restore_region(background) self.canvas.blit(self.get_axes()[0].bbox) self.canvas.update() self.canvas.flush_events()
class Main(QMainWindow, Ui_MainWindow): def __init__(self, ): super(Main, self).__init__() self.setupUi(self) self.pushButton_Start.clicked.connect(self.StartButton) self.pushButton_Stop.clicked.connect(self.StopButton) #self.pushButton_Start.setIcon(QtGui.QIcon('/home/insu13.yu/Works/PyQT/QtDesign/EmbedQtChart/start.png')) #self.pushButton_Stop.setIcon(QtGui.QIcon('/home/insu13.yu/Works/PyQT/QtDesign/EmbedQtChart/stop.png')) #self.pushButton_Start.setGeometry(200,20, 50,40) self.mCPU0 = [] self.mCPU1 = [] self.mCPU2 = [] self.mCPU3 = [] self.mCPU4 = [] self.mCPU5 = [] self.mCPU6 = [] self.mCPU7 = [] self.mDVFS_Max = [] self.mDVFS_Min = [] self.mDDR = [] self.mBUS = [] self.mGPUFreq = [] self.mGPUUtil = [] self.mAPT = [] self.mPST = [] self.mCPUG0 = [] self.mCPUG1 = [] self.mGPU = [] #time index self.timeindex = 0 #init CPU information panel self.fig1 = Figure() self.canvas1 = FigureCanvas(self.fig1) self.Layout_CPU.addWidget(self.canvas1) self.ax1 = [ self.fig1.add_subplot(811), self.fig1.add_subplot(812), self.fig1.add_subplot(813), self.fig1.add_subplot(814), self.fig1.add_subplot(815), self.fig1.add_subplot(816), self.fig1.add_subplot(817), self.fig1.add_subplot(818) ] #init System information panel self.fig2 = Figure() self.canvas2 = FigureCanvas(self.fig2) self.Layout_System.addWidget(self.canvas2) # make plots self.ax2 = [ self.fig2.add_subplot(811), self.fig2.add_subplot(812), self.fig2.add_subplot(813), self.fig2.add_subplot(814), self.fig2.add_subplot(815), self.fig2.add_subplot(816), self.fig2.add_subplot(817), self.fig2.add_subplot(818) ] # draw horizontal line #ax[0].axhline(y=0.5, xmin=0, xmax=1, color='#FF0000', linewidth=4) # draw vertical line #ax[0].axvline(x=50, ymin=0, ymax=1, color='#006000', linewidth=4) def setup_CPU_chart(self): ## add navigation toolbar #self.toolbar = NavigationToolbar(canvas, self.mplwindow, coordinates=True) #self.mplvl.addWidget(self.toolbar) # make plots for i in xrange(0,8): self.ax1[i].clear() # ============================================ # Setup chart properties, tick and grid etcs # ============================================ ticklines = self.ax1[i].get_xticklines() ticklines.extend( self.ax1[i].get_yticklines() ) gridlines = self.ax1[i].get_xgridlines() gridlines.extend( self.ax1[i].get_ygridlines() ) ticklabels = self.ax1[i].get_xticklabels() ticklabels.extend( self.ax1[i].get_yticklabels() ) for line in ticklines: line.set_color('#00C040') line.set_linewidth(1) for line in gridlines: line.set_color('#00C040') line.set_linestyle('-') for label in ticklabels: label.set_color('#404040') # drak grey label.set_fontsize('8') # or 'small' #self.ax1[0].axis([0,100,0,2100]) self.ax1[i].set_autoscale_on(False) # show grid self.ax1[i].grid(True) # set your xticks manually (10 ticks) self.ax1[i].xaxis.set_ticks(numpy.arange(0,100,2.5)) # [i for i in range(0,100, 10)] # set your yticks manually (10 ticks) self.ax1[i].yaxis.set_ticks(numpy.arange(0, 1401 if i < 4 else 2201, 200)) # remove label self.ax1[i].set_xticklabels([]) self.ax1[i].set_axis_bgcolor((0, 0, 0)) # Y labels self.ax1[0].set_ylabel('CPU0') self.ax1[1].set_ylabel('CPU1') self.ax1[2].set_ylabel('CPU2') self.ax1[3].set_ylabel('CPU3') self.ax1[4].set_ylabel('CPU4') self.ax1[5].set_ylabel('CPU5') self.ax1[6].set_ylabel('CPU6') self.ax1[7].set_ylabel('CPU7') self.fig1.subplots_adjust(left=0.10, bottom=0.03, right=0.98, top=0.99, wspace=0.2, hspace=0.1) def setup_System_chart(self): ## add navigation toolbar #self.toolbar = NavigationToolbar(canvas, self.mplwindow, coordinates=True) #self.mplvl.addWidget(self.toolbar) for i in xrange(0,8): # ============================================ # Setup chart properties, tick and grid etcs # ============================================ ticklines = self.ax2[i].get_xticklines() ticklines.extend( self.ax2[i].get_yticklines() ) gridlines = self.ax2[i].get_xgridlines() gridlines.extend( self.ax2[i].get_ygridlines() ) ticklabels = self.ax2[i].get_xticklabels() ticklabels.extend( self.ax2[i].get_yticklabels() ) for line in ticklines: line.set_color('#00C040') line.set_linewidth(1) for line in gridlines: line.set_color('#00C040') line.set_linestyle('-') for label in ticklabels: label.set_color('#404040') # drak grey if(i == 0 or i == 1): label.set_fontsize('8') # or 'small' else: label.set_fontsize('9') # or 'small' # show grid self.ax2[i].grid(True) # set your xticks manually (10 ticks) self.ax2[i].xaxis.set_ticks(numpy.arange(0,100,3)) # [i for i in range(0,100, 10)] # remove label self.ax2[i].set_xticklabels([]) self.ax2[i].set_axis_bgcolor((0, 0, 0)) self.ax2[i].set_autoscale_on(False) # Y ticks self.ax2[0].yaxis.set_ticks(numpy.arange(0, 1201, 200)) # DVFS self.ax2[1].yaxis.set_ticks(numpy.arange(0, 1301, 200)) # DDR self.ax2[2].yaxis.set_ticks(numpy.arange(0, 1001, 100)) # BUS self.ax2[3].yaxis.set_ticks(numpy.arange(0, 1001, 100)) # GPU Freq self.ax2[4].yaxis.set_ticks(numpy.arange(0, 101, 10)) # GPU Util #self.ax2[5].yaxis.set_ticks(numpy.arange(30, 71, 5)) # APT #self.ax2[6].yaxis.set_ticks(numpy.arange(30, 71, 5)) # PST self.ax2[7].yaxis.set_ticks(numpy.arange(0, 71, 10)) # Temperature self.ax2[5].axis([0, 100, 30,70]) self.ax2[6].axis([0, 100, 30,70]) # Y labels self.ax2[0].set_ylabel('DVFS (MHz)') self.ax2[1].set_ylabel('DDR (MHz)') self.ax2[2].set_ylabel('BUS (MHz)') self.ax2[3].set_ylabel('GPU Freq (MHz)') self.ax2[4].set_ylabel('GPU Util (%)') self.ax2[5].set_ylabel('APT (C)') self.ax2[6].set_ylabel('PST (C)') self.ax2[7].set_ylabel('Temperature (C)') self.fig2.subplots_adjust(left=0.10, bottom=0.03, right=0.98, top=0.99, wspace=0.2, hspace=0.1) def update(self): values = self.showfreq.GetValues() print ('value=', values) if values == None: values = self.showfreq.GetValues() print ('value=', values) self.mCPU0.append(values[1]) self.mCPU1.append(values[2]) self.mCPU2.append(values[3]) self.mCPU3.append(values[4]) self.mCPU4.append(values[5]) self.mCPU5.append(values[6]) self.mCPU6.append(values[7]) self.mCPU7.append(values[8]) self.mDVFS_Max.append(values[15]) self.mDVFS_Min.append(values[16]) self.mDDR.append(values[17]) self.mBUS.append(values[18]) self.mGPUFreq.append(values[13]) self.mGPUUtil.append(values[14]) self.mAPT.append(values[22]) self.mPST.append(values[23]) self.mCPUG0.append(values[19]) self.mCPUG1.append(values[20]) self.mGPU.append(values[21]) self.timeindex += 1 loc = self.timeindex Max_Temperature = 40.0 # DVFX Max if (values[15] == -1): self.LCD_DVFS_MAX.setStyleSheet( "color: #C0C0C0;" ) else: self.LCD_DVFS_MAX.setStyleSheet( "color: #FF0000;" ) # DVFX Min if (values[16] == -1): self.LCD_DVFS_MIN.setStyleSheet( "color: #C0C0C0;" ) else: self.LCD_DVFS_MIN.setStyleSheet( "color: #FF0000;" ) # GPU Freq if (values[13] == 0): self.LCD_GPU_FREQ.setStyleSheet( "color: #C0C0C0;" ) else: self.LCD_GPU_FREQ.setStyleSheet( "color: #0000FF;" ) # GPU Util if (values[14] <= 0): self.LCD_GPU_UTIL.setStyleSheet( "color: #C0C0C0;" ) elif (values[14] >= 80): # default self.LCD_GPU_UTIL.setStyleSheet( "color: #FF0000;" ) else: self.LCD_GPU_UTIL.setStyleSheet( "color: #0000FF;" ) # APT if (values[22] >= Max_Temperature): self.LCD_APT.setStyleSheet( "color: #FF0000;" ) else: self.LCD_APT.setStyleSheet( "color: #000000;" ) # PST if (values[23] >= Max_Temperature): self.LCD_PST.setStyleSheet( "color: #FF0000;" ) else: self.LCD_PST.setStyleSheet( "color: #000000;" ) # GPU if (values[21] <= 0): self.LCD_GPU.setStyleSheet( "color: #C0C0C0;" ) elif (values[14] >= 60): self.LCD_GPU.setStyleSheet( "color: #FF0000;" ) else: self.LCD_GPU.setStyleSheet( "color: #000000;" ) self.LCD_DVFS_MAX.display('%.f' % values[15]) self.LCD_DVFS_MIN.display('%.f' % values[16]) self.LCD_GPU_FREQ.display('%.f' % values[13]) self.LCD_GPU_UTIL.display('%.f' % values[14]) self.LCD_DDR.display('%.f' % values[17]) self.LCD_BUS.display('%.f' % values[18]) self.LCD_APT.display('%.1f\'' % values[22]) self.LCD_PST.display('%.1f\'' % values[23]) self.LCD_CPU_G0.display('%.1f\'' % values[19]) self.LCD_CPU_G1.display('%.1f\'' % values[20]) self.LCD_GPU.display('%.1f\'' % values[21]) self.LCD_CPU0.display('%.f' % values[1]) self.LCD_CPU1.display('%.f' % values[2]) self.LCD_CPU2.display('%.f' % values[3]) self.LCD_CPU3.display('%.f' % values[4]) self.LCD_CPU4.display('%.f' % values[5]) self.LCD_CPU5.display('%.f' % values[6]) self.LCD_CPU6.display('%.f' % values[7]) self.LCD_CPU7.display('%.f' % values[8]) # graph x = arange(100) padd = [None]*(100-loc) #draw graph, style, color, width = 1.0 anti = False self.ax1[0].plot(x, self.mCPU0[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[1].plot(x, self.mCPU1[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[2].plot(x, self.mCPU2[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[3].plot(x, self.mCPU3[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[4].plot(x, self.mCPU4[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[5].plot(x, self.mCPU5[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[6].plot(x, self.mCPU6[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[7].plot(x, self.mCPU7[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) #self.ax1[0].axvline(x=loc, ymin=0, ymax=1, color='#006000', linewidth=3) self.ax2[0].plot(x, self.mDVFS_Max[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # DVFS self.ax2[0].plot(x, self.mDVFS_Min[-100:] + padd, linestyle='-', color='#0000FF', linewidth=width, antialiased=anti) # DVFS self.ax2[1].plot(x, self.mDDR[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # DDR self.ax2[2].plot(x, self.mBUS[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # BUS self.ax2[3].plot(x, self.mGPUFreq[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # GPU Freq self.ax2[4].plot(x, self.mGPUUtil[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # GPU Util self.ax2[5].plot(x, self.mAPT[-100:] + padd, linestyle='-', color='#FF0000', linewidth=width, antialiased=anti) # APT self.ax2[6].plot(x, self.mPST[-100:] + padd, linestyle='-', color='#FF0000', linewidth=width, antialiased=anti) # PST self.ax2[7].plot(x, self.mCPUG0[-100:] + padd, linestyle='-', color='#FF0000', linewidth=width, antialiased=anti) # C0 Temperature self.ax2[7].plot(x, self.mCPUG1[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) # C1 Temperature self.ax2[7].plot(x, self.mGPU[-100:] + padd, linestyle='-', color='#0000FF', linewidth=width, antialiased=anti) # C2 Temperature self.canvas1.draw() self.canvas2.draw() self.canvas1.flush_events() self.canvas2.flush_events() #self.show() self.thread = Timer(self.duration/1000.0, self.update) self.thread.start() """ax1 = self.ax1 x = np.arange(0,100.0) y1 = (np.cos(2*np.pi*x/50.0)+1.0) * 1000 #ax1[0].clear() ax1[0].plot(x, y1, linestyle='-', color='#00FF00', linewidth=2) self.canvas1.draw() self.canvas1.flush_events() self.show()""" print ('Update is done') def StartButton(self): print ('StartButton') Device_Info(self.listWidget) self.duration = 1000 self.showfreq = ShowFreq(self.duration) self.update() self.thread = Timer(0.5, self.update) self.thread.start() #ani animation.FuncAnimation(fig, animate, interval = 10) def StopButton(self): print ('StopButton')
class SamplingWidget(QtGui.QWidget): def __init__(self): super(SamplingWidget, self).__init__() self.serial_con = serial.Serial(DEVICE_ADDRESS, BAUD_RATE) self.batch_size = None self.data = None self.figure = Figure() self.canvas = FigureCanvas(self.figure) self.axes = self.figure.add_subplot(111) self.left_mean_label = None self.left_std_label = None self.right_mean_label = None self.right_std_label = None self.batch_size_label = None self.label_edit = None self.accept_btn = None self.reject_btn = None layout = QtGui.QHBoxLayout() layout.addWidget(self.canvas) layout.addWidget(self.toolbar()) self.setLayout(layout) self.get_sample() self.canvas.draw() def toolbar(self): self.left_mean_label = QtGui.QLabel("0.00000") self.left_std_label = QtGui.QLabel("0.00000") self.right_mean_label = QtGui.QLabel("0.00000") self.right_std_label = QtGui.QLabel("0.00000") self.batch_size_label = QtGui.QLabel("0") self.label_edit = QtGui.QLineEdit() self.accept_btn = QtGui.QPushButton("Accept") self.accept_btn.clicked.connect(self.accept_sample) self.reject_btn = QtGui.QPushButton("Reject") self.reject_btn.clicked.connect(self.get_sample) layout = QtGui.QVBoxLayout() info_widget = QtGui.QWidget() info_layout = QtGui.QGridLayout() info_widget.setLayout(info_layout) info_layout.addWidget(QtGui.QLabel("Batch size: "), 1, 1) info_layout.addWidget(QtGui.QLabel("Left mean: "), 2, 1) info_layout.addWidget(QtGui.QLabel("Left std: "), 3, 1) info_layout.addWidget(QtGui.QLabel("Right mean: "), 4, 1) info_layout.addWidget(QtGui.QLabel("Right std: "), 5, 1) info_layout.addWidget(self.batch_size_label, 1, 2) info_layout.addWidget(self.left_mean_label, 2, 2) info_layout.addWidget(self.left_std_label, 3, 2) info_layout.addWidget(self.right_mean_label, 4, 2) info_layout.addWidget(self.right_std_label, 5, 2) layout.addWidget(info_widget) layout.addSpacerItem( QtGui.QSpacerItem(1, 10, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)) layout.addWidget(QtGui.QLabel("Label:")) layout.addWidget(self.label_edit) layout.addWidget(self.accept_btn) layout.addWidget(self.reject_btn) widget = QtGui.QWidget() widget.setFixedWidth(100) widget.setLayout(layout) return widget def set_data(self, batch_size, data): self.left_mean_label.setText(str(round(np.mean(data[0]), 5))) self.left_std_label.setText(str(round(np.std(data[0]), 5))) self.right_mean_label.setText(str(round(np.mean(data[1]), 5))) self.right_std_label.setText(str(round(np.std(data[1]), 5))) self.batch_size_label.setText(str(batch_size)) print("Plotting data...") plot_data(self.axes, data) self.canvas.draw() self.canvas.flush_events() self.batch_size = batch_size self.data = data def accept_sample(self): label = None try: label = float(self.label_edit.text()) except ValueError: try: label = int(self.label_edit.text()) except ValueError: print("Failed to interpret label") return if label < -90.0 or 90.0 < label: print("Label not in range") return print("Saving sample...") save_sample(FILE_PATH + '32kHz_' + str(self.batch_size) + '.csv', self.data, label) self.get_sample() def get_sample(self): print("Getting sample...") batch_size, data = sample(self.serial_con, 1000) self.set_data(batch_size, data) return
class Main(QMainWindow, Ui_MainWindow): def __init__(self, ): super(Main, self).__init__() self.setupUi(self) self.pushButton_Start.clicked.connect(self.StartButton) self.pushButton_Stop.clicked.connect(self.StopButton) #self.pushButton_Start.setIcon(QtGui.QIcon('/home/insu13.yu/Works/PyQT/QtDesign/EmbedQtChart/start.png')) #self.pushButton_Stop.setIcon(QtGui.QIcon('/home/insu13.yu/Works/PyQT/QtDesign/EmbedQtChart/stop.png')) #self.pushButton_Start.setGeometry(200,20, 50,40) self.mCPU0 = [] self.mCPU1 = [] self.mCPU2 = [] self.mCPU3 = [] self.mCPU4 = [] self.mCPU5 = [] self.mCPU6 = [] self.mCPU7 = [] self.mDVFS_Max = [] self.mDVFS_Min = [] self.mDDR = [] self.mBUS = [] self.mGPUFreq = [] self.mGPUUtil = [] self.mAPT = [] self.mPST = [] self.mCPUG0 = [] self.mCPUG1 = [] self.mGPU = [] #time index self.timeindex = 0 #init CPU information panel self.fig1 = Figure() self.canvas1 = FigureCanvas(self.fig1) self.Layout_CPU.addWidget(self.canvas1) self.ax1 = [ self.fig1.add_subplot(811), self.fig1.add_subplot(812), self.fig1.add_subplot(813), self.fig1.add_subplot(814), self.fig1.add_subplot(815), self.fig1.add_subplot(816), self.fig1.add_subplot(817), self.fig1.add_subplot(818) ] #init System information panel self.fig2 = Figure() self.canvas2 = FigureCanvas(self.fig2) self.Layout_System.addWidget(self.canvas2) # make plots self.ax2 = [ self.fig2.add_subplot(811), self.fig2.add_subplot(812), self.fig2.add_subplot(813), self.fig2.add_subplot(814), self.fig2.add_subplot(815), self.fig2.add_subplot(816), self.fig2.add_subplot(817), self.fig2.add_subplot(818) ] # draw horizontal line #ax[0].axhline(y=0.5, xmin=0, xmax=1, color='#FF0000', linewidth=4) # draw vertical line #ax[0].axvline(x=50, ymin=0, ymax=1, color='#006000', linewidth=4) def setup_CPU_chart(self): ## add navigation toolbar #self.toolbar = NavigationToolbar(canvas, self.mplwindow, coordinates=True) #self.mplvl.addWidget(self.toolbar) # make plots for i in xrange(0, 8): self.ax1[i].clear() # ============================================ # Setup chart properties, tick and grid etcs # ============================================ ticklines = self.ax1[i].get_xticklines() ticklines.extend(self.ax1[i].get_yticklines()) gridlines = self.ax1[i].get_xgridlines() gridlines.extend(self.ax1[i].get_ygridlines()) ticklabels = self.ax1[i].get_xticklabels() ticklabels.extend(self.ax1[i].get_yticklabels()) for line in ticklines: line.set_color('#00C040') line.set_linewidth(1) for line in gridlines: line.set_color('#00C040') line.set_linestyle('-') for label in ticklabels: label.set_color('#404040') # drak grey label.set_fontsize('8') # or 'small' #self.ax1[0].axis([0,100,0,2100]) self.ax1[i].set_autoscale_on(False) # show grid self.ax1[i].grid(True) # set your xticks manually (10 ticks) self.ax1[i].xaxis.set_ticks(numpy.arange( 0, 100, 2.5)) # [i for i in range(0,100, 10)] # set your yticks manually (10 ticks) self.ax1[i].yaxis.set_ticks( numpy.arange(0, 1401 if i < 4 else 2201, 200)) # remove label self.ax1[i].set_xticklabels([]) self.ax1[i].set_axis_bgcolor((0, 0, 0)) # Y labels self.ax1[0].set_ylabel('CPU0') self.ax1[1].set_ylabel('CPU1') self.ax1[2].set_ylabel('CPU2') self.ax1[3].set_ylabel('CPU3') self.ax1[4].set_ylabel('CPU4') self.ax1[5].set_ylabel('CPU5') self.ax1[6].set_ylabel('CPU6') self.ax1[7].set_ylabel('CPU7') self.fig1.subplots_adjust(left=0.10, bottom=0.03, right=0.98, top=0.99, wspace=0.2, hspace=0.1) def setup_System_chart(self): ## add navigation toolbar #self.toolbar = NavigationToolbar(canvas, self.mplwindow, coordinates=True) #self.mplvl.addWidget(self.toolbar) for i in xrange(0, 8): # ============================================ # Setup chart properties, tick and grid etcs # ============================================ ticklines = self.ax2[i].get_xticklines() ticklines.extend(self.ax2[i].get_yticklines()) gridlines = self.ax2[i].get_xgridlines() gridlines.extend(self.ax2[i].get_ygridlines()) ticklabels = self.ax2[i].get_xticklabels() ticklabels.extend(self.ax2[i].get_yticklabels()) for line in ticklines: line.set_color('#00C040') line.set_linewidth(1) for line in gridlines: line.set_color('#00C040') line.set_linestyle('-') for label in ticklabels: label.set_color('#404040') # drak grey if (i == 0 or i == 1): label.set_fontsize('8') # or 'small' else: label.set_fontsize('9') # or 'small' # show grid self.ax2[i].grid(True) # set your xticks manually (10 ticks) self.ax2[i].xaxis.set_ticks(numpy.arange( 0, 100, 3)) # [i for i in range(0,100, 10)] # remove label self.ax2[i].set_xticklabels([]) self.ax2[i].set_axis_bgcolor((0, 0, 0)) self.ax2[i].set_autoscale_on(False) # Y ticks self.ax2[0].yaxis.set_ticks(numpy.arange(0, 1201, 200)) # DVFS self.ax2[1].yaxis.set_ticks(numpy.arange(0, 1301, 200)) # DDR self.ax2[2].yaxis.set_ticks(numpy.arange(0, 1001, 100)) # BUS self.ax2[3].yaxis.set_ticks(numpy.arange(0, 1001, 100)) # GPU Freq self.ax2[4].yaxis.set_ticks(numpy.arange(0, 101, 10)) # GPU Util #self.ax2[5].yaxis.set_ticks(numpy.arange(30, 71, 5)) # APT #self.ax2[6].yaxis.set_ticks(numpy.arange(30, 71, 5)) # PST self.ax2[7].yaxis.set_ticks(numpy.arange(0, 71, 10)) # Temperature self.ax2[5].axis([0, 100, 30, 70]) self.ax2[6].axis([0, 100, 30, 70]) # Y labels self.ax2[0].set_ylabel('DVFS (MHz)') self.ax2[1].set_ylabel('DDR (MHz)') self.ax2[2].set_ylabel('BUS (MHz)') self.ax2[3].set_ylabel('GPU Freq (MHz)') self.ax2[4].set_ylabel('GPU Util (%)') self.ax2[5].set_ylabel('APT (C)') self.ax2[6].set_ylabel('PST (C)') self.ax2[7].set_ylabel('Temperature (C)') self.fig2.subplots_adjust(left=0.10, bottom=0.03, right=0.98, top=0.99, wspace=0.2, hspace=0.1) def update(self): values = self.showfreq.GetValues() print('value=', values) if values == None: values = self.showfreq.GetValues() print('value=', values) self.mCPU0.append(values[1]) self.mCPU1.append(values[2]) self.mCPU2.append(values[3]) self.mCPU3.append(values[4]) self.mCPU4.append(values[5]) self.mCPU5.append(values[6]) self.mCPU6.append(values[7]) self.mCPU7.append(values[8]) self.mDVFS_Max.append(values[15]) self.mDVFS_Min.append(values[16]) self.mDDR.append(values[17]) self.mBUS.append(values[18]) self.mGPUFreq.append(values[13]) self.mGPUUtil.append(values[14]) self.mAPT.append(values[22]) self.mPST.append(values[23]) self.mCPUG0.append(values[19]) self.mCPUG1.append(values[20]) self.mGPU.append(values[21]) self.timeindex += 1 loc = self.timeindex Max_Temperature = 40.0 # DVFX Max if (values[15] == -1): self.LCD_DVFS_MAX.setStyleSheet("color: #C0C0C0;") else: self.LCD_DVFS_MAX.setStyleSheet("color: #FF0000;") # DVFX Min if (values[16] == -1): self.LCD_DVFS_MIN.setStyleSheet("color: #C0C0C0;") else: self.LCD_DVFS_MIN.setStyleSheet("color: #FF0000;") # GPU Freq if (values[13] == 0): self.LCD_GPU_FREQ.setStyleSheet("color: #C0C0C0;") else: self.LCD_GPU_FREQ.setStyleSheet("color: #0000FF;") # GPU Util if (values[14] <= 0): self.LCD_GPU_UTIL.setStyleSheet("color: #C0C0C0;") elif (values[14] >= 80): # default self.LCD_GPU_UTIL.setStyleSheet("color: #FF0000;") else: self.LCD_GPU_UTIL.setStyleSheet("color: #0000FF;") # APT if (values[22] >= Max_Temperature): self.LCD_APT.setStyleSheet("color: #FF0000;") else: self.LCD_APT.setStyleSheet("color: #000000;") # PST if (values[23] >= Max_Temperature): self.LCD_PST.setStyleSheet("color: #FF0000;") else: self.LCD_PST.setStyleSheet("color: #000000;") # GPU if (values[21] <= 0): self.LCD_GPU.setStyleSheet("color: #C0C0C0;") elif (values[14] >= 60): self.LCD_GPU.setStyleSheet("color: #FF0000;") else: self.LCD_GPU.setStyleSheet("color: #000000;") self.LCD_DVFS_MAX.display('%.f' % values[15]) self.LCD_DVFS_MIN.display('%.f' % values[16]) self.LCD_GPU_FREQ.display('%.f' % values[13]) self.LCD_GPU_UTIL.display('%.f' % values[14]) self.LCD_DDR.display('%.f' % values[17]) self.LCD_BUS.display('%.f' % values[18]) self.LCD_APT.display('%.1f\'' % values[22]) self.LCD_PST.display('%.1f\'' % values[23]) self.LCD_CPU_G0.display('%.1f\'' % values[19]) self.LCD_CPU_G1.display('%.1f\'' % values[20]) self.LCD_GPU.display('%.1f\'' % values[21]) self.LCD_CPU0.display('%.f' % values[1]) self.LCD_CPU1.display('%.f' % values[2]) self.LCD_CPU2.display('%.f' % values[3]) self.LCD_CPU3.display('%.f' % values[4]) self.LCD_CPU4.display('%.f' % values[5]) self.LCD_CPU5.display('%.f' % values[6]) self.LCD_CPU6.display('%.f' % values[7]) self.LCD_CPU7.display('%.f' % values[8]) # graph x = arange(100) padd = [None] * (100 - loc) #draw graph, style, color, width = 1.0 anti = False self.ax1[0].plot(x, self.mCPU0[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[1].plot(x, self.mCPU1[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[2].plot(x, self.mCPU2[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[3].plot(x, self.mCPU3[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[4].plot(x, self.mCPU4[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[5].plot(x, self.mCPU5[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[6].plot(x, self.mCPU6[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) self.ax1[7].plot(x, self.mCPU7[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) #self.ax1[0].axvline(x=loc, ymin=0, ymax=1, color='#006000', linewidth=3) self.ax2[0].plot(x, self.mDVFS_Max[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # DVFS self.ax2[0].plot(x, self.mDVFS_Min[-100:] + padd, linestyle='-', color='#0000FF', linewidth=width, antialiased=anti) # DVFS self.ax2[1].plot(x, self.mDDR[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # DDR self.ax2[2].plot(x, self.mBUS[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # BUS self.ax2[3].plot(x, self.mGPUFreq[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # GPU Freq self.ax2[4].plot(x, self.mGPUUtil[-100:] + padd, linestyle='-', color='#FFFF00', linewidth=width, antialiased=anti) # GPU Util self.ax2[5].plot(x, self.mAPT[-100:] + padd, linestyle='-', color='#FF0000', linewidth=width, antialiased=anti) # APT self.ax2[6].plot(x, self.mPST[-100:] + padd, linestyle='-', color='#FF0000', linewidth=width, antialiased=anti) # PST self.ax2[7].plot(x, self.mCPUG0[-100:] + padd, linestyle='-', color='#FF0000', linewidth=width, antialiased=anti) # C0 Temperature self.ax2[7].plot(x, self.mCPUG1[-100:] + padd, linestyle='-', color='#00FF00', linewidth=width, antialiased=anti) # C1 Temperature self.ax2[7].plot(x, self.mGPU[-100:] + padd, linestyle='-', color='#0000FF', linewidth=width, antialiased=anti) # C2 Temperature self.canvas1.draw() self.canvas2.draw() self.canvas1.flush_events() self.canvas2.flush_events() #self.show() self.thread = Timer(self.duration / 1000.0, self.update) self.thread.start() """ax1 = self.ax1 x = np.arange(0,100.0) y1 = (np.cos(2*np.pi*x/50.0)+1.0) * 1000 #ax1[0].clear() ax1[0].plot(x, y1, linestyle='-', color='#00FF00', linewidth=2) self.canvas1.draw() self.canvas1.flush_events() self.show()""" print('Update is done') def StartButton(self): print('StartButton') Device_Info(self.listWidget) self.duration = 1000 self.showfreq = ShowFreq(self.duration) self.update() self.thread = Timer(0.5, self.update) self.thread.start() #ani animation.FuncAnimation(fig, animate, interval = 10) def StopButton(self): print('StopButton')
class PlotHandler(object): def __init__(self, parent): self.figure = Figure(tight_layout=True) self.canvas = FigureCanvas(self.figure) self.canvas.setContentsMargins(0,0,0,0) self.axes = self.figure.add_subplot(111, projection='3d') Axes3D.set_autoscale_on(self.axes, True) Axes3D.autoscale_view(self.axes) self.canvas.setParent(parent) self.activePlot = None self.activePopulation = None self.surface = None self.scatter = None def get_widget(self): return self.canvas def updatePlot(self, X, Y, Z, population=None): self.activePlot = (X,Y,Z) x, y = np.meshgrid(X,Y) if self.surface is not None: self.surface.remove() if self.scatter is not None: self.scatter.remove() # surface self.surface = Axes3D.plot_surface( self.axes, x, y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False, shade=False, alpha=0.5 ) # population if population is not None: self.activePopulation = population x, y, z = self.preparePopulationData(population) self.scatter = Axes3D.scatter(self.axes, x, y, z, c="r", marker="o") self.scatter.set_alpha(1.0) # Draw all self.canvas.draw() self.canvas.flush_events() def updatePopulation(self, population): self.activePopulation = population x, y, z = self.preparePopulationData(population) if self.scatter is not None: self.scatter.remove() self.scatter = Axes3D.scatter(self.axes, x, y, z, c="r", marker="o") # self.surface.set_zorder(2) # self.scatter.set_zorder(100) self.scatter.set_alpha(1.0) self.canvas.draw() self.canvas.flush_events() def preparePopulationData(self, population): x = [] y = [] z = [] for p in population: # x.append(p.parameters[0]) # y.append(p.parameters[1]) # z.append(p.fitness) x.append(p[0]) y.append(p[1]) z.append(p[2]+0.1) return (x, y, z)
class mGraph(QtGui.QWidget): def __init__(self, device, parent=None): QtGui.QWidget.__init__(self, parent) # Create a matplotlib figure. self.figure = plt.figure() self.figure.set_facecolor('r') # Create a QFrame to house the plot. This is not necessary, # just makes it look nice. self.matframe = QtGui.QFrame() self.matLayout = QtGui.QVBoxLayout() self.matLayout.setSpacing(0) self.matframe.setLayout(self.matLayout) self.matframe.setFrameShape(QtGui.QFrame.Panel) self.matframe.setFrameShadow(QtGui.QFrame.Plain) self.matframe.setStyleSheet( "background-color: rgb(70,80,88); " "margin:0px; border:2px solid rgb(0, 0, 0); ") self.canvas = FigureCanvas(self.figure) self.canvas.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) # This is the device we want to use. self.device = device # This sets up axis on which to plot. color = (189. / 255, 195. / 255, 199. / 255) self.ax = self.figure.add_subplot(111, axisbg=color) ax = self.ax # Add the matplotlib canvas to the QFrame. self.matLayout.addWidget(self.canvas) # The following lines set up all the colors, makes it look nice. # The code to do it is far from pretty and I am planning # on cleaning this up a bit. self.figure.patch.set_color((70. / 255, 80. / 255, 88. / 255)) self.figure.patch.set_edgecolor((70. / 255, 80. / 255, 88. / 255)) ax.spines['bottom'].set_color(color) ax.spines['top'].set_color(color) ax.spines['right'].set_color(color) ax.spines['left'].set_color(color) ax.tick_params(axis='x', colors=color) ax.tick_params(axis='y', colors=color) ax.title.set_color(color) ax.yaxis.label.set_color(color) ax.xaxis.label.set_color(color) ax.xaxis.get_offset_text().set_color(color) ax.yaxis.get_offset_text().set_color(color) # This is an array of all the lines on the plot. A line for # every parameter. self.line = [] self.mins = 0 self.maxes = 1 # Each element of line holds a plot, to be combined onto # the same graph. self.line.append(ax.plot(1, 1, label="Getting Data...")[0]) # In order to handle interactivity, I had to do some odd stuff # with the toolbar buttons: self.home holds the original # function called when the home button on the toolbar # is clicked. self.home = NavigationToolbar.home # We now change the function that is called when the toolbar is # clicked. NavigationToolbar.home = self.enableAutoScaling self.toolbar = NavigationToolbar(self.canvas, self) self.cid = self.canvas.mpl_connect('button_press_event', self.disableAutoScaling) self.setStyleSheet("QPushButton{\ color:rgb(189,195, 199); \ background:rgb(70, 80, 88)};") self.fullGraphBtn = QtGui.QPushButton("Show Interactive Graph") self.fullGraphBtn.clicked.connect(self.openFullGraphGui) self.toolbarFrame = QtGui.QFrame() toolbarFrameLayout = QtGui.QVBoxLayout() toolbarFrameLayout.addWidget(self.toolbar) self.toolbar.setParent(None) self.toolbarFrame.setLayout(toolbarFrameLayout) self.toolbarFrame.setStyleSheet("\ border:2px solid rgb(0,0,0);\ color:rgb(189,195,199); \ background:rgb(70, 80, 88);") self.toolbar.setStyleSheet("\ border:0px solid rgb(0,0,0);\ QDialog{background:rgb(70, 80, 88)}") self.matPlotInfo = QtGui.QLabel() self.alertFont = QtGui.QFont() self.alertFont.setPointSize(12) self.matPlotInfo.setStyleSheet("color:rgb(200, 69, 50);") self.matPlotInfo.setText("Auto refresh disabled, " "click HOME button to enable.") self.matPlotInfo.setFont(self.alertFont) #self.refreshRateSec = device.getFrame().getPlotRefreshRate() self.refreshRateSec = device.getFrame().getPlotRefreshRate() self.timer = QtCore.QTimer(self) self.hidden = True self.home = True self.initialized = False self.currTimeRange = 120 self.lineSelect = MCheckableComboBox() self.lineSelect.setSizeAdjustPolicy(0) self.lineSelect.setStyleSheet("\ background-color:rgb(70, 80, 88);\ color:rgb(189,195, 199);") self.plot(self.currTimeRange) self.timer.timeout.connect(partial(self.plot, self.currTimeRange)) self.timer.start(self.refreshRateSec * 1000) # Did it store data? self.dataOk = True self.hideButton = QtGui.QPushButton("Show Plot") self.hideButton.clicked.connect(self.togglePlot) self.oneMinButton = QtGui.QPushButton("1 min") self.oneMinButton.clicked.connect(partial(self.plot, 60)) self.tenMinButton = QtGui.QPushButton("10 min") self.tenMinButton.clicked.connect(partial(self.plot, 600)) self.twoHrButton = QtGui.QPushButton("2 hr") self.twoHrButton.clicked.connect(partial(self.plot, 7200)) self.twelveHrButton = QtGui.QPushButton("12 hr") self.twelveHrButton.clicked.connect(partial(self.plot, 43200)) self.threeDayButton = QtGui.QPushButton("3 day") self.threeDayButton.clicked.connect(partial(self.plot, 259200)) self.oneWkButton = QtGui.QPushButton("1 week") self.oneWkButton.clicked.connect(partial(self.plot, 604800)) self.allButton = QtGui.QPushButton("All Time") self.allButton.clicked.connect(partial(self.plot, None)) self.canvas.hide() self.toolbar.hide() # Set the layout. buttonLayout1 = QtGui.QHBoxLayout() buttonLayout1.addWidget(self.hideButton) buttonLayout1.addWidget(self.fullGraphBtn) buttonLayout1.addStretch(0) buttonLayout2 = QtGui.QHBoxLayout() settingsbuttons1 = QtGui.QHBoxLayout() buttonLayout2.addWidget(self.oneMinButton) buttonLayout2.addWidget(self.tenMinButton) buttonLayout2.addWidget(self.twoHrButton) buttonLayout2.addWidget(self.twelveHrButton) buttonLayout2.addWidget(self.threeDayButton) buttonLayout2.addWidget(self.oneWkButton) buttonLayout2.addWidget(self.allButton) buttonLayout2.addStretch(0) self.oneMinButton.hide() self.tenMinButton.hide() self.twoHrButton.hide() self.twelveHrButton.hide() self.threeDayButton.hide() self.oneWkButton.hide() self.allButton.hide() self.lineSelect.hide() self.matframe.hide() self.matPlotInfo.hide() self.toolbarFrame.hide() settingsbuttons1.addWidget(self.lineSelect) layout = QtGui.QVBoxLayout() allButtonsLayout = QtGui.QHBoxLayout() timeButtonsLayout = QtGui.QVBoxLayout() allButtonsLayout.addLayout(timeButtonsLayout) layout.addLayout(allButtonsLayout) allButtonsLayout.addLayout(settingsbuttons1) timeButtonsLayout.addLayout(buttonLayout1) timeButtonsLayout.addLayout(buttonLayout2) timeButtonsLayout.addWidget(self.matPlotInfo) layout.addWidget(self.matframe) layout.addWidget(self.toolbarFrame) self.setLayout(layout) def enableAutoScaling(self): self.timer.start(self.refreshRateSec * 1000) self.home = True self.matPlotInfo.hide() self.plot(self.currTimeRange) def disableAutoScaling(self, event): self.home = False self.matPlotInfo.show() self.canvas.update() self.timer.stop() def togglePlot(self): if not self.hidden: self.canvas.hide() self.toolbar.hide() self.oneMinButton.hide() self.tenMinButton.hide() self.twoHrButton.hide() self.twelveHrButton.hide() self.threeDayButton.hide() self.oneWkButton.hide() self.allButton.hide() self.matPlotInfo.hide() self.matframe.hide() self.lineSelect.hide() self.toolbarFrame.hide() self.timer.stop() self.hideButton.setText("Show Plot") self.hidden = True elif self.hidden: self.canvas.show() self.toolbar.show() self.oneMinButton.show() self.tenMinButton.show() self.twoHrButton.show() self.twelveHrButton.show() self.threeDayButton.show() self.oneWkButton.show() self.allButton.show() self.plot(self.currTimeRange) self.matframe.show() self.lineSelect.show() self.toolbarFrame.show() self.timer.start(self.refreshRateSec * 1000) self.hideButton.setText("Hide Plot") self.enableAutoScaling() self.hidden = False def initializePlot(self, dataSet): if dataSet: varNames = dataSet.getVariables() varNames = [varNames[1][i][0] for i in range(len(varNames[1]))] self.dropdownFont = QtGui.QFont() self.dropdownFont.setPointSize(12) if dataSet is not None: self.initialized = True self.line[0].remove() self.line = [] for i in range(len(varNames)): self.line.append(self.ax.plot(1, 1, label=varNames[i])[0]) text = QtCore.QString(varNames[i]) self.lineSelect.addItem(text) self.lineSelect.setFont(self.dropdownFont) self.lineSelect.setChecked(i, True) def changeIndependenVarRange(self, timeRange): if not self.hidden: if timeRange != self.currTimeRange: self.timer.stop() self.timer.timeout.disconnect() self.currTimeRange = timeRange self.timer.timeout.connect( lambda: self.plot(self.currTimeRange)) self.timer.start(self.refreshRateSec * 1000) plotRefreshRate = self.device.getFrame().getPlotRefreshRate() if self.refreshRateSec != plotRefreshRate: self.refreshRateSec = plotRefreshRate self.timer.stop() self.timer.timeout.disconnect() self.currTimeRange = timeRange self.timer.timeout.connect( lambda: self.plot(self.currTimeRange)) self.timer.start(self.refreshRateSec * 1000) def getDataRangeFromDataSet(self, dataSet, time): if dataSet: data = dataSet.getData() i = len(data) - 1 if time: while data[i][0] > (data[-1][0] - time): i -= 1 if -1 * i > len(data): return data data = data[i:-1] return data else: return None def openFullGraphGui(self): # print "opening full graph gui." dataSet = self.device.getFrame().getDataSet().getData() # print dataSet times = [dt.datetime.fromtimestamp(elem[0]) for elem in dataSet] vars = self.device.getFrame().getDataSet().getVariables() self.fullgraphcont = fullGraphContainer(times, vars, dataSet) self.fullgraphcont.show() def plot(self, time): times = None self.changeIndependenVarRange(time) dataSet = self.device.getFrame().getDataSet() if not self.initialized: self.initializePlot(dataSet) self.legend = self.ax.legend(loc='upper left') # This is the ONLY time canvas.draw is called. It should # NOT be called anywhere else if the graphing speed is # to be fast. self.canvas.draw() else: data = self.getDataRangeFromDataSet(dataSet, time) for i in range(len(data[0]) - 1): if self.lineSelect.isChecked(i): times = [dt.datetime.fromtimestamp(row[0]) for row in data] column = [row[i + 1] for row in data] if not self.line[i].get_visible(): self.line[i].set_visible(True) self.line[i].set_data(times, column) self.legend = self.ax.legend(loc='upper left') self.ax.grid(True) self.ax.hold(True) else: self.line[i].set_visible(False) pass self.ax.set_title(self.device.getFrame().getTitle(), color=(189. / 255, 195. / 255, 199. / 255)) if self.home and times: self.ax.set_xlim(times[0], times[-1]) self.ax.relim(visible_only=True) self.ax.autoscale(axis='y') frame = self.device.getFrame() yLabel = frame.getYLabel() if yLabel is not None: if frame.getCustomUnits(): self.ax.set_ylabel("%s (%s)" % (yLabel, frame.getCustomUnits())) elif frame.getUnits()[i - 1]: self.ax.set_ylabel("%s (%s)" % (yLabel, frame.getUnits()[i - 1])) locator = AutoDateLocator() self.ax.xaxis.set_major_locator(locator) self.ax.xaxis.set_major_formatter(DateFormatter('%m/%d %H:%M:%S')) self.figure.autofmt_xdate() self.ax.draw_artist(self.figure) self.ax.draw_artist(self.ax.patch) self.ax.draw_artist(self.ax.yaxis) self.ax.draw_artist(self.ax.xaxis) for i, line in enumerate(self.line): self.ax.draw_artist(line) self.ax.set_xlabel("Time") self.ax.draw_artist(self.legend) self.canvas.update() self.canvas.flush_events()
class streamPick(QtGui.QMainWindow): def __init__(self, stream=None, parent=None): # Initialising QtGui QtCore.QLocale.setDefault(QtCore.QLocale.c()) qApp = QtGui.QApplication(sys.argv) # Init vars if stream is None: msg = 'Define stream = obspy.core.Stream()' raise ValueError(msg) self.st = stream.copy() self._picks = [] self.savefile = None self.onset_types = ['emergent', 'impulsive', 'questionable'] # Load filters from pickle try: self.bpfilter = pickle.load(open('.pick_filters', 'r')) except: self.bpfilter = [] # Internal variables # Gui vars self._shortcuts = {'st_next': 'c', 'st_previous': 'x', 'filter_apply': 'f', 'pick_p': 'q', 'pick_s': 'w', 'pick_custom': 't', 'pick_remove': 'r', } self._plt_drag = None self._current_filter = None # Init stations self._initStations() # defines list self._stations self._stationCycle = cycle(self._stations) self._streamStation(self._stationCycle.next()) # Init QtGui QtGui.QMainWindow.__init__(self) self.setupUI() # exec QtApp qApp.exec_() def setupUI(self): ''' Setup the UI ''' self.main_widget = QtGui.QWidget(self) # Init parts of the UI self._initMenu() self._createStatusBar() self._initPlots() self._wadatiPlt = None # Define layout l = QtGui.QVBoxLayout(self.main_widget) l.addLayout(self.btnbar) l.addWidget(self.canvas) self.setCentralWidget(self.main_widget) self.setGeometry(300, 300, 1200, 800) self.setWindowTitle('obspy.core.Stream-Picker') self.show() def _initPlots(self): self.fig = Figure(facecolor='.86', dpi=72, frameon=True) # Change facecolor self.canvas = FigureCanvas(self.fig) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) # Draw the matplotlib figure self._drawFig() # Connect the events self.fig.canvas.mpl_connect('scroll_event', self._pltOnScroll) self.fig.canvas.mpl_connect('motion_notify_event', self._pltOnDrag) self.fig.canvas.mpl_connect('button_release_event', self._pltOnButtonRelease) self.fig.canvas.mpl_connect('button_press_event', self._pltOnButtonPress) def _initMenu(self): # Next and Prev Button nxt = QtGui.QPushButton('Next >>', shortcut=self._shortcuts['st_next']) nxt.clicked.connect(self._pltNextStation) nxt.setToolTip('shortcut <b>c</d>') nxt.setMaximumWidth(150) prv = QtGui.QPushButton('<< Prev', shortcut=self._shortcuts['st_previous']) prv.clicked.connect(self._pltPrevStation) prv.setToolTip('shortcut <b>x</d>') prv.setMaximumWidth(150) # Stations drop-down self.stcb = QtGui.QComboBox(self) for st in self._stations: self.stcb.addItem(st) self.stcb.activated.connect(self._pltStation) self.stcb.setMaximumWidth(100) self.stcb.setMinimumWidth(80) # Filter buttons self.fltrbtn = QtGui.QPushButton('Filter Trace', shortcut=self._shortcuts['filter_apply']) self.fltrbtn.setToolTip('shortcut <b>f</b>') self.fltrbtn.setCheckable(True) #self.fltrbtn.setAutoFillBackground(True) self.fltrbtn.setStyleSheet(QtCore.QString( 'QPushButton:checked {background-color: lightgreen;}')) self.fltrbtn.clicked.connect(self._appFilter) self.fltrcb = QtGui.QComboBox(self) self.fltrcb.activated.connect(self._changeFilter) self.fltrcb.setMaximumWidth(170) self.fltrcb.setMinimumWidth(150) self._updateFilterCB() # fill QComboBox # edit/delete filer buttons fltredit = QtGui.QPushButton('Edit') fltredit.resize(fltredit.sizeHint()) fltredit.clicked.connect(self._editFilter) fltrdel = QtGui.QPushButton('Delete') fltrdel.resize(fltrdel.sizeHint()) fltrdel.clicked.connect(self._deleteFilter) btnstyle = QtGui.QFrame(fltredit) btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) btnstyle = QtGui.QFrame(fltrdel) btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) # onset type _radbtn = [] for _o in self.onset_types: _radbtn.append(QtGui.QRadioButton(str(_o[0].upper()))) _radbtn[-1].setToolTip('Onset ' + _o) _radbtn[-1].clicked.connect(self._drawPicks) if _o == 'impulsive': _radbtn[-1].setChecked(True) self.onsetGrp = QtGui.QButtonGroup() self.onsetGrp.setExclusive(True) onsetbtns = QtGui.QHBoxLayout() for _i, _btn in enumerate(_radbtn): self.onsetGrp.addButton(_btn, _i) onsetbtns.addWidget(_btn) # Arrange buttons vline = QtGui.QFrame() vline.setFrameStyle(QtGui.QFrame.VLine | QtGui.QFrame.Raised) self.btnbar = QtGui.QHBoxLayout() self.btnbar.addWidget(prv) self.btnbar.addWidget(nxt) self.btnbar.addWidget(QtGui.QLabel('Station')) self.btnbar.addWidget(self.stcb) ## self.btnbar.addWidget(vline) self.btnbar.addWidget(self.fltrbtn) self.btnbar.addWidget(self.fltrcb) self.btnbar.addWidget(fltredit) self.btnbar.addWidget(fltrdel) ## self.btnbar.addWidget(vline) self.btnbar.addWidget(QtGui.QLabel('Pick Onset: ')) self.btnbar.addLayout(onsetbtns) self.btnbar.addStretch(3) # Menubar menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(QtGui.QIcon().fromTheme('document-save'), 'Save', self._saveCatalog) fileMenu.addAction(QtGui.QIcon().fromTheme('document-save'), 'Save as QuakeML File', self._saveCatalogDlg) fileMenu.addAction(QtGui.QIcon().fromTheme('document-open'), 'Load QuakeML File', self._openCatalogDlg) fileMenu.addSeparator() fileMenu.addAction('Save Plot', self._savePlotDlg) fileMenu.addSeparator() fileMenu.addAction(QtGui.QIcon().fromTheme('application-exit'), 'Exit', self.close) #windowMenu = menubar.addMenu('&Windows') #windowMenu.addAction('Wadati Diagram', self._opnWadatiPlot) aboutMenu = menubar.addMenu('&About') aboutMenu.addAction(QtGui.QIcon().fromTheme('info'), 'Info', self._infoDlg) def _drawFig(self): ''' Draws all matplotlib figures ''' num_plots = len(self._current_st) self.fig.clear() self._appFilter(draw=False) for _i, tr in enumerate(self._current_st): ax = self.fig.add_subplot(num_plots, 1, _i) ax.plot(tr.data, 'k', antialiased=True, rasterized=True, lod=False) ax.axhline(0, color='k', alpha=.05) ax.set_xlim([0, tr.data.size]) ax.text(.02, .925, self._current_st[_i].id, transform=ax.transAxes, va='top', ha='left', alpha=.75) ax.channel = tr.stats.channel if _i == 0: ax.set_xlabel('Seconds') # plot picks self._drawPicks(draw=False) self.fig.suptitle('%s - %s - %s / %.1f Hz / %d samples per chanel' % (self._current_st[-1].stats.network, self._current_st[-1].stats.station, self._current_st[-1].stats.starttime.isoformat(), 1./self._current_st[-1].stats.delta, self._current_st[-1].stats.npts), x=.2) self._updateSB() self._canvasDraw() def _initStations(self): ''' Creates a list holding unique station names ''' self._stations = [] for _tr in self.st: if _tr.stats.station not in self._stations: self._stations.append(_tr.stats.station) self._stations.sort() def _getPhases(self): ''' Creates a list holding unique phase names ''' phases = [] for _pick in self._picks: if _pick.phase_hint not in phases: phases.append(_pick.phase_hint) return phases def _streamStation(self, station): ''' Copies the current stream object from self.st through obspy.stream.select(station=) ''' if station not in self._stations: return self._current_st = self.st.select(station=station).copy() self._current_stname = station self._current_network = self._current_st[0].stats.network # Sort and detrend streams self._current_st.sort(['channel']) self._current_st.detrend('linear') def _setPick(self, xdata, phase, channel, polarity='undecideable', overwrite_existing=False): ''' Write obspy.core.event.Pick into self._picks list ''' picktime = self._current_st[0].stats.starttime +\ (xdata * self._current_st[0].stats.delta) this_pick = event.Pick() overwrite = True # Overwrite existing phase's picktime if overwrite_existing: for _pick in self._getPicks(): if _pick.phase_hint == phase and\ _pick.waveform_id.channel_code == channel: this_pick = _pick overwrite = False break creation_info = event.CreationInfo( author='ObsPy.StreamPick', creation_time=UTCDateTime()) # Create new event.Pick() this_pick.time = picktime this_pick.phase_hint = phase this_pick.waveform_id = event.WaveformStreamID( network_code=self._current_st[0].stats.network, station_code=self._current_st[0].stats.station, location_code=self._current_st[0].stats.location, channel_code=channel) this_pick.evaluation_mode = 'manual' this_pick.creation_info = creation_info this_pick.onset = self.onset_types[self.onsetGrp.checkedId()] this_pick.evaluation_status = 'preliminary' this_pick.polarity = polarity #if self._current_filter is not None: # this_pick.comments.append(event.Comment( # text=str(self.bpfilter[self.fltrcb.currentIndex()]))) if overwrite: self._picks.append(this_pick) def _delPicks(self, network, station, channel): ''' Deletes pick from catalog ''' for _i, _pick in enumerate(self._picks): if _pick.waveform_id.network_code == network\ and _pick.waveform_id.station_code == station\ and _pick.waveform_id.channel_code == channel: self._picks.remove(_pick) def _getPicks(self): ''' Create a list of picks for the current plot ''' this_st_picks = [] for _i, pick in enumerate(self._picks): if pick.waveform_id.station_code == self._current_stname and\ self._current_st[0].stats.starttime <\ pick.time < self._current_st[0].stats.endtime: this_st_picks.append(_i) return [self._picks[i] for i in this_st_picks] def _getPickXPosition(self, picks): ''' Convert picktimes into relative positions along x-axis ''' xpicks = [] for _pick in picks: xpicks.append((_pick.time-self._current_st[0].stats.starttime) / self._current_st[0].stats.delta) return np.array(xpicks) def _drawPicks(self, draw=True): ''' Draw picklines onto axes ''' picks = self._getPicks() xpicks = self._getPickXPosition(picks) for _ax in self.fig.get_axes(): lines = [] labels = [] points = [] transOffset = offset_copy(_ax.transData, fig=self.fig, x=5, y=0, units='points') for _i, _xpick in enumerate(xpicks): if picks[_i].phase_hint == 'S': color = 'r' elif picks[_i].phase_hint == 'P': color = 'g' else: color = 'b' if _ax.channel != picks[_i].waveform_id.channel_code: alpha = .2 else: alpha = .8 lines.append(matplotlib.lines.Line2D([_xpick, _xpick], [_ax.get_ylim()[0]*.9, _ax.get_ylim()[1]*.8], color=color, alpha=alpha, rasterized=True)) lines[-1].obspy_pick = picks[_i] points.append(matplotlib.lines.Line2D([_xpick], [_ax.lines[0].get_ydata()[int(_xpick)]], marker='o', mfc=color, mec=color, alpha=alpha, ms=5)) labels.append(matplotlib.text.Text(_xpick, _ax.get_ylim()[0]*.8, text=picks[_i].phase_hint, color=color, size=10, alpha=alpha, transform=transOffset)) # delete all artists del _ax.artists[0:] # add updated objects for li, la, po in zip(lines, labels, points): _ax.add_artist(li) _ax.add_artist(la) _ax.add_artist(po) if draw: self._canvasDraw() # Plot Controls def _pltOnScroll(self, event): ''' Scrolls/Redraws the plots along x axis ''' if event.inaxes is None: return if event.key == 'control': axes = [event.inaxes] else: axes = self.fig.get_axes() for _ax in axes: left = _ax.get_xlim()[0] right = _ax.get_xlim()[1] extent = right - left dzoom = .2 * extent aspect_left = (event.xdata - _ax.get_xlim()[0]) / extent aspect_right = (_ax.get_xlim()[1] - event.xdata) / extent if event.button == 'up': left += dzoom * aspect_left right -= dzoom * aspect_right elif event.button == 'down': left -= dzoom * aspect_left right += dzoom * aspect_right else: return _ax.set_xlim([left, right]) self._canvasDraw() def _pltOnDrag(self, event): ''' Drags/Redraws the plot upon drag ''' if event.inaxes is None: return if event.key == 'control': axes = [event.inaxes] else: axes = self.fig.get_axes() if event.button == 2: if self._plt_drag is None: self._plt_drag = event.xdata return for _ax in axes: _ax.set_xlim([_ax.get_xlim()[0] + (self._plt_drag - event.xdata), _ax.get_xlim()[1] + (self._plt_drag - event.xdata)]) else: return self._canvasDraw() def _pltOnButtonRelease(self, event): ''' On Button Release Reset drag variable ''' self._plt_drag = None def _pltOnButtonPress(self, event): ''' This Function is evoked when the user picks ''' if event.key is not None: event.key = event.key.lower() if event.inaxes is None: return channel = event.inaxes.channel tr_amp = event.inaxes.lines[0].get_ydata()[int(event.xdata)+3] -\ event.inaxes.lines[0].get_ydata()[int(event.xdata)] if tr_amp < 0: polarity = 'negative' elif tr_amp > 0: polarity = 'positive' else: polarity = 'undecideable' if event.key == self._shortcuts['pick_p'] and event.button == 1: self._setPick(event.xdata, phase='P', channel=channel, polarity=polarity) elif event.key == self._shortcuts['pick_s'] and event.button == 1: self._setPick(event.xdata, phase='S', channel=channel, polarity=polarity) elif event.key == self._shortcuts['pick_custom'] and event.button == 1: text, ok = QtGui.QInputDialog.getItem(self, 'Custom Phase', 'Enter phase name:', self._getPhases()) if ok: self._setPick(event.xdata, phase=text, channel=channel, polarity=polarity) elif event.key == self._shortcuts['pick_remove']: self._delPicks(network=self._current_network, station=self._current_stname, channel=channel) else: return self._updateSB() self._drawPicks() def _pltNextStation(self): ''' Plot next station ''' self._streamStation(self._stationCycle.next()) self._drawFig() def _pltPrevStation(self): ''' Plot previous station ''' for _i in range(len(self._stations)-1): prevStation = self._stationCycle.next() self._streamStation(prevStation) self._drawFig() def _pltStation(self): ''' Plot station from DropDown Menu ''' _i = self.stcb.currentIndex() while self._stationCycle.next() != self._stations[_i]: pass self._streamStation(self._stations[_i]) self._drawFig() # Filter functions def _appFilter(self, button=True, draw=True): ''' Apply bandpass filter ''' _i = self.fltrcb.currentIndex() self._streamStation(self._current_stname) if self.fltrbtn.isChecked() is False: self._current_filter = None else: self._current_st.filter('bandpass', freqmin=self.bpfilter[_i]['freqmin'], freqmax=self.bpfilter[_i]['freqmax'], corners=self.bpfilter[_i]['corners'], zerophase=True) self._current_filter = _i for _i, _ax in enumerate(self.fig.get_axes()): if len(_ax.lines) == 0: continue _ax.lines[0].set_ydata(self._current_st[_i].data) _ax.relim() _ax.autoscale_view() if draw is True: self._drawPicks(draw=False) self._canvasDraw() self._updateSB() def _newFilter(self): ''' Create new filter ''' newFilter = self.defFilter(self) if newFilter.exec_(): self.bpfilter.append(newFilter.getValues()) self._updateFilterCB() self.fltrcb.setCurrentIndex(len(self.bpfilter)-1) self._appFilter() def _editFilter(self): ''' Edit existing filter ''' _i = self.fltrcb.currentIndex() this_filter = self.bpfilter[_i] editFilter = self.defFilter(self, this_filter) if editFilter.exec_(): self.bpfilter[_i] = editFilter.getValues() self._updateFilterCB() self.fltrcb.setCurrentIndex(_i) self._appFilter() def _deleteFilter(self): ''' Delete filter ''' _i = self.fltrcb.currentIndex() self.fltrbtn.setChecked(False) self.bpfilter.pop(_i) self._updateFilterCB() self._appFilter() def _changeFilter(self, index): ''' Evoke this is filter in drop-down is changed ''' if index == len(self.bpfilter): return self._newFilter() else: return self._appFilter() def _updateFilterCB(self): ''' Update the filter QComboBox ''' self.fltrcb.clear() self.fltrcb.setCurrentIndex(-1) for _i, _f in enumerate(self.bpfilter): self.fltrcb.addItem('%s [%.2f - %.2f Hz]' % (_f['name'], _f['freqmin'], _f['freqmax'])) self.fltrcb.addItem('Create new Filter...') # Status bar functions def _createStatusBar(self): ''' Creates the status bar ''' sb = QtGui.QStatusBar() sb.setFixedHeight(18) self.setStatusBar(sb) self.statusBar().showMessage('Ready') def _updateSB(self, statustext=None): ''' Updates the statusbar text ''' if statustext is None: self.stcb.setCurrentIndex( self._stations.index(self._current_stname)) msg = 'Station %i/%i - %i Picks' % ( self._stations.index(self._current_stname)+1, len(self._stations), len(self._getPicks())) if self._current_filter is not None: msg += ' - Bandpass %s [%.2f - %.2f Hz]' % ( self.bpfilter[self._current_filter]['name'], self.bpfilter[self._current_filter]['freqmin'], self.bpfilter[self._current_filter]['freqmax']) else: msg += ' - Raw Data' self.statusBar().showMessage(msg) def _openCatalogDlg(self): filename = QtGui.QFileDialog.getOpenFileName(self, 'Load QuakeML Picks', os.getcwd(), 'QuakeML Format (*.xml)', '20') if filename: self._openCatalog(str(filename)) self.savefile = str(filename) def _openCatalog(self, filename): ''' Open existing QuakeML catalog ''' try: print 'Opening QuakeML Catalog %s' % filename cat = event.readEvents(filename) self._picks = cat[0].picks self._drawPicks() except: msg = 'Could not open QuakeML file %s' % (filename) raise IOError(msg) def _saveCatalogDlg(self): ''' Save catalog through QtDialog ''' self.savefile = QtGui.QFileDialog.getSaveFileName(self, 'Save QuakeML Picks', os.getcwd(), 'QuakeML Format (*.xml)') if not self.savefile: self.savefile = None return self.savefile = str(self.savefile) if os.path.splitext(self.savefile)[1].lower() != '.xml': self.savefile += '.xml' self._saveCatalog() def _saveCatalog(self, filename=None): ''' Saves the catalog to filename ''' if self.savefile is None and filename is None: return self._saveCatalogDlg() if filename is not None: savefile = filename else: savefile = self.savefile cat = event.Catalog() cat.events.append(event.Event(picks=self._picks)) cat.write(savefile, format='QUAKEML') print 'Picks saved as %s' % savefile def _savePlotDlg(self): ''' Save Plot Image Qt Dialog and Matplotlib wrapper ''' filename = QtGui.QFileDialog.getSaveFileName(self, 'Save Plot', os.getcwd(), 'Image Format (*.png *.pdf *.ps *.svg *.eps)') if not filename: return filename = str(filename) format = os.path.splitext(filename)[1][1:].lower() if format not in ['png', 'pdf', 'ps', 'svg', 'eps']: format = 'png' filename += '.' + format self.fig.savefig(filename=filename, format=format, dpi=72) def getPicks(self): return self._picks def _opnWadatiPlot(self): self._wadatiPlt = QtGui.NewWindow() self._wadatiPlt.show() def _infoDlg(self): msg = """ <h3><b>obspy.core.stream-Picker</b></h3> <br><br> <div> StreamPick is a lightweight seismological wave time picker for <code>obspy.core.Stream()</code> objects. It further utilises the <code>obspy.core.event</code> class to store picks in the QuakeML format. </div> <h4>Controls:</h4> <blockquote> <table> <tr> <td width=20><b>%s</b></td><td>Next station</td> </tr> <tr> <td width=20><b>%s</b></td><td>Previous station</td> </tr> <tr> <td width=20><b>%s</b></td><td>Toggle filter</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set P-Phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set S-Phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set custom phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Remove last pick in trace</td> </tr> </table> </blockquote> <h4>Plot Controls:</h4> <blockquote> Use mouse wheel to zoom in- and out. Middle mouse button moves plot along x-axis.<br> Hit <b>Ctrl</b> to manipulate a single plot. <br> </blockquote> <div> Programm stores filter parameters in <code>.pick_filter</code> and a backup of recent picks in <code>.picks-obspy.xml.bak</code>.<br><br> See <a href=http://www.github.org/miili/StreamPick> http://www.github.org/miili/StreamPick</a> and <a href=http://www.obspy.org>http://www.obspy.org</a> for further documentation. </div> """ % ( self._shortcuts['st_next'], self._shortcuts['st_previous'], self._shortcuts['filter_apply'], self._shortcuts['pick_p'], self._shortcuts['pick_s'], self._shortcuts['pick_custom'], self._shortcuts['pick_remove'], ) QtGui.QMessageBox.about(self, 'About', msg) def _canvasDraw(self): ''' Redraws the canvas and re-sets mouse focus ''' for _i, _ax in enumerate(self.fig.get_axes()): _ax.set_xticklabels(_ax.get_xticks() * self._current_st[_i].stats.delta) self.canvas.draw_idle() self.canvas.flush_events() self.canvas.setFocus() return def closeEvent(self, evnt): ''' This function is called upon closing the QtGui ''' # Save Picks pickle.dump(self.bpfilter, open('.pick_filters', 'w')) # Save Catalog if len(self._picks) > 0: self._saveCatalog('.picks-obspy.xml.bak') if self.savefile is None and len(self._picks) > 0: ask = QtGui.QMessageBox.question(self, 'Save Picks?', 'Do you want to save your picks?', QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) if ask == QtGui.QMessageBox.Save: self._saveCatalog() elif ask == QtGui.QMessageBox.Cancel: evnt.ignore() print self._picks # Filter Dialog class defFilter(QtGui.QDialog): def __init__(self, parent=None, filtervalues=None): ''' Bandpass filter dialog... Qt layout and stuff ''' QtGui.QDialog.__init__(self, parent) self.setWindowTitle('Create new Bandpass-Filter') # Frequency QDoubleSpinBoxes self.frqmin = QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=0.1) self.frqmax = QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=10.0) # Radio buttons for corners _corners = [2, 4, 8] _radbtn = [] for _c in _corners: _radbtn.append(QtGui.QRadioButton(str(_c))) if _c == 4: _radbtn[-1].setChecked(True) self.corner = QtGui.QButtonGroup() self.corner.setExclusive(True) radiogrp = QtGui.QHBoxLayout() for _i, _r in enumerate(_radbtn): self.corner.addButton(_r, _corners[_i]) radiogrp.addWidget(_radbtn[_i]) # Filter name self.fltname = QtGui.QLineEdit('Filter Name') self.fltname.selectAll() # Make Layout grid = QtGui.QGridLayout() grid.addWidget(QtGui.QLabel('Filter Name'), 0, 0) grid.addWidget(self.fltname, 0, 1) grid.addWidget(QtGui.QLabel('Min. Frequency'), 1, 0) grid.addWidget(self.frqmin, 1, 1) grid.addWidget(QtGui.QLabel('Max. Frequency'), 2, 0) grid.addWidget(self.frqmax, 2, 1) grid.addWidget(QtGui.QLabel('Corners'), 3, 0) grid.addLayout(radiogrp, 3, 1) grid.setVerticalSpacing(10) btnbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) btnbox.accepted.connect(self.accept) btnbox.rejected.connect(self.reject) layout = QtGui.QVBoxLayout() layout.addWidget(QtGui.QLabel('Define a minimum and maximum' + ' frequency\nfor the bandpass filter.\nFunction utilises ' + 'obspy.signal.filter (zerophase=True).\n')) layout.addLayout(grid) layout.addWidget(btnbox) if filtervalues is not None: self.fltname.setText(filtervalues['name']) self.frqmin.setValue(filtervalues['freqmin']) self.frqmax.setValue(filtervalues['freqmax']) self.corner.button(filtervalues['corners']).setChecked(True) self.setLayout(layout) self.setSizeGripEnabled(False) def getValues(self): ''' Return filter dialogs values as a dictionary ''' return dict(name=str(self.fltname.text()), freqmin=float(self.frqmin.cleanText()), freqmax=float(self.frqmax.cleanText()), corners=int(int(self.corner.checkedId())))
class testWindow(QMainWindow): def __init__(self,parent=None): QMainWindow.__init__(self,parent=parent) self.setWindowTitle('Truncate DAC Attenuation') self.create_main_frame() self.powerSweepDataPath = '/' def plotTruncatedHistogram(self,*args): #clear the axes self.ax1.clear() #get the roach number roachNum = self.spinbox_roachNumber.value() #set the new range for the cutoff atten spinbox, custom for each roach self.spinbox_cutoffAtten.setRange(np.amin(self.roachList[roachNum].attens),100) self.cutoff = self.spinbox_cutoffAtten.value() #print a warning if the cutoff value is out of range of DAC attens in file if np.logical_or(self.cutoff<np.amin(self.roachList[roachNum].attens),self.cutoff>np.amax(self.roachList[roachNum].attens)): print 'cutoff attenuation is out of range of measured values' #find where the DAC atten array has values < cutoff value, update the truncatedAttens array #modify the roach object self.violatingIndices = np.where(self.roachList[roachNum].attens < self.cutoff)[0] self.roachList[roachNum].truncatedAttens = np.copy(self.roachList[roachNum].attens) self.roachList[roachNum].truncatedAttens[self.violatingIndices] = self.cutoff #set up the bins for the histogram plot self.bins = range(int(np.amin(self.roachList[roachNum].attens)),int(np.amax(self.roachList[roachNum].attens))) #plot the truncatedAttens histogram self.ax1.hist(self.roachList[roachNum].truncatedAttens,self.bins) self.draw() #plot the pre-truncated attens histogram for comparison self.ax1.hist(self.roachList[roachNum].attens,self.bins,alpha = 0.7) #alpha sets the transparency self.ax1.set_ylabel('number of resonators') self.ax1.set_xlabel('DAC atten [dB]') #set plot label as filename self.ax1.set_title(self.roachList[roachNum].filename[len(self.powerSweepDataPath)+1:]) self.draw() #update the roach object with new cutoff value self.roachList[roachNum].cutoff = self.cutoff if 0: print 'plotting roach: ',self.roachList[roachNum].filename[len(self.powerSweepDataPath):] def setCutoffAttenSpinboxValue(self): #call this function when changing the roach number spinbox value roachNum = self.spinbox_roachNumber.value() #get the roach number #catch the situation when the new cutoff value is the same as the previous value if self.spinbox_cutoffAtten.value() == self.roachList[roachNum].cutoff: self.plotTruncatedHistogram() self.spinbox_cutoffAtten.setRange(0,100) self.spinbox_cutoffAtten.setValue(self.roachList[roachNum].cutoff) def getFilenameFromUser(self): #create an open file dialog box to prompt user to select a file to load filename = str(QFileDialog.getOpenFileName(self, 'Select One File', '/')) print os.path.dirname(filename) #set the data path variable self.powerSweepDataPath = os.path.dirname(filename) #load in the data. Look for all files ending with ".txt" and add them to list of files to load in. #ignore files that end with "_trunc.txt", because those are what this program outputs fileListRaw = [] for file in os.listdir(self.powerSweepDataPath): if file.endswith(".txt"): if file.endswith("_trunc.txt"): print 'skipping loading of ' + str(file) else: fileListRaw = fileListRaw + [os.path.join(self.powerSweepDataPath, file)] self.fileListRaw = fileListRaw print '\nloading data\n' #create list of roach objects. One roach per file loaded. self.roachList = [] for ii in range(len(self.fileListRaw)): self.roachList = self.roachList + [roach(self.fileListRaw[ii])] #plot the first roach by setting the cutoff atten spinbox value self.setCutoffAttenSpinboxValue() def saveOneRoach(self): #save data of currently displayed histogram in a new file with "_trunc.txt" at end. roachNum = self.spinbox_roachNumber.value() self.roachList[roachNum].dataTruncated[:,2] = self.roachList[roachNum].truncatedAttens print '\nWriting ',self.fileListRaw[roachNum][:-4]+'_trunc.txt' np.savetxt(self.fileListRaw[roachNum][:-4]+'_trunc.txt', self.roachList[roachNum].dataTruncated,fmt='%6i %10.9e %4i') def saveAllRoach(self): #save all roach truncated histograms. for ii in range(len(self.fileListRaw)): self.roachList[ii].dataTruncated[:,2] = self.roachList[ii].truncatedAttens print '\nWriting ',self.fileListRaw[ii][:-4]+'_trunc.txt' np.savetxt(self.fileListRaw[ii][:-4]+'_trunc.txt', self.roachList[ii].dataTruncated,fmt='%6i %10.9e %4i') print '\nSAVE ALL OPERATION COMPLETE.' def create_main_frame(self): """ Makes GUI elements on the window """ #Define the plot window. self.main_frame = QWidget() self.dpi = 100 self.fig = Figure((9.0, 5.0), dpi=self.dpi) #define the figure, set the size and resolution self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self.main_frame) self.ax1 = self.fig.add_subplot(111) # self.ax1.set_ylabel('y axis label') # self.ax1.set_xlabel('resonator attenuation [dB]') #Define the button that will save one roach. button_save = QPushButton("Save") button_save.setEnabled(True) button_save.setToolTip('Saves current roach.') button_save.clicked.connect(self.saveOneRoach) #Define the button that will save all roaches. button_saveAll = QPushButton("Save All") button_saveAll.setEnabled(True) button_saveAll.clicked.connect(self.saveAllRoach) #Define the button that will load data button_loadData = QPushButton("Open") button_loadData.setEnabled(True) button_loadData.setToolTip('Select one of the power sweep files you want to look at.\n All other files in the same directory will be loaded as well.') button_loadData.clicked.connect(self.getFilenameFromUser) #make a label for the roach number spinbox label_roachNumber = QLabel('Roach Number') #make a label for the roach cutoff attenuation label_cutoff = QLabel('Cutoff Attenuation') #Let's draw a spin box for the roach number. roachNumber = 0 self.spinbox_roachNumber = QSpinBox() self.spinbox_roachNumber.setValue(roachNumber) self.spinbox_roachNumber.setRange(0,9) self.spinbox_roachNumber.setWrapping(False) self.spinbox_roachNumber.setToolTip('Use up/down arrows on keyboard!.') self.spinbox_roachNumber.valueChanged.connect(self.setCutoffAttenSpinboxValue) # Using .connect will send self.makePlot an argument which is equal to the new value. #Let's draw spin box for the cutoff attenuation. initCutoff = 0 self.spinbox_cutoffAtten = QSpinBox() self.spinbox_cutoffAtten.setValue(initCutoff) self.spinbox_cutoffAtten.setRange(0,100) self.spinbox_cutoffAtten.setWrapping(False) self.spinbox_cutoffAtten.setToolTip('Use up/down arrows on keyboard!.') self.spinbox_cutoffAtten.valueChanged.connect(self.plotTruncatedHistogram) #create a vertical box for the plot to go in. vbox_plot = QVBoxLayout() vbox_plot.addWidget(self.canvas) #create a vbox for the roach label and spinbox to go in vbox_roachNumber = QVBoxLayout() vbox_roachNumber.addWidget(label_roachNumber) vbox_roachNumber.addWidget(self.spinbox_roachNumber) #create a vbox for the atten cutoff label and atten cutoff spinbox to go in vbox_cutoffAtten = QVBoxLayout() vbox_cutoffAtten.addWidget(label_cutoff) vbox_cutoffAtten.addWidget(self.spinbox_cutoffAtten) #Create an h box for the buttons and spinboxes to go in. hbox_ch = QHBoxLayout() hbox_ch.addWidget(button_loadData) hbox_ch.addLayout(vbox_roachNumber) hbox_ch.addLayout(vbox_cutoffAtten) hbox_ch.addWidget(button_save) hbox_ch.addWidget(button_saveAll) #Now create another vbox, and add the plot vbox and the button's hbox to the new vbox. vbox_combined = QVBoxLayout() vbox_combined.addLayout(vbox_plot) vbox_combined.addLayout(hbox_ch) #Set the main_frame's layout to be vbox_combined self.main_frame.setLayout(vbox_combined) #Set the overall QWidget to have the layout of the main_frame. self.setCentralWidget(self.main_frame) def draw(self): #The plot window calls this function self.canvas.draw() self.canvas.flush_events()
class mGraph(QtGui.QWidget): def __init__(self, device, parent=None): QtGui.QWidget.__init__(self, parent) # Create a matplotlib figure self.figure = plt.figure() self.figure.set_facecolor("r") # Create a QFrame to house the plot. This is not necessary, just makes it look nice self.matframe = QtGui.QFrame() self.matLayout = QtGui.QVBoxLayout() self.matLayout.setSpacing(0) self.matframe.setLayout(self.matLayout) self.matframe.setFrameShape(QtGui.QFrame.Panel) self.matframe.setFrameShadow(QtGui.QFrame.Plain) self.matframe.setStyleSheet("background-color: rgb(70,80,88); margin:0px; border:2px solid rgb(0, 0, 0); ") self.canvas = FigureCanvas(self.figure) self.canvas.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) # This is the device we want to use self.device = device # This sets up axis on which to plot self.ax = self.figure.add_subplot(111, axisbg=(189.0 / 255, 195.0 / 255, 199.0 / 255)) # Add the matplotlib canvas to the QFrame self.matLayout.addWidget(self.canvas) # The following lines set up all the colors, makes it look nice. The code to do it is # far from pretty and I am planning on cleaning this up a bit. self.figure.patch.set_color((70.0 / 255, 80.0 / 255, 88.0 / 255)) self.figure.patch.set_edgecolor((70.0 / 255, 80.0 / 255, 88.0 / 255)) self.ax.spines["bottom"].set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.spines["top"].set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.spines["right"].set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.spines["left"].set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.tick_params(axis="x", colors=(189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.tick_params(axis="y", colors=(189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.title.set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.yaxis.label.set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.xaxis.label.set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.xaxis.get_offset_text().set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) self.ax.yaxis.get_offset_text().set_color((189.0 / 255, 195.0 / 255, 199.0 / 255)) # This is an array of all the lines on the plot. A line for every parameter self.line = [] # Each element of line holds a plot, to be combined onto the same graph self.line.append(self.ax.plot(1, 1, label="Getting Data...")[0]) # This is the ONLY time canvas.draw is called. It should NOT be called anywhere else if # the graphing speed is to be fast. self.canvas.draw() # In order to handle interactivity, I had to do some odd stuff with the # toolbar buttons. Self.home holds the original function called when the home button on the toolbar # is clicked. self.home = NavigationToolbar.home # We now change the function that is called when the toolbar is clicked. NavigationToolbar.home = self.enableAutoScaling self.toolbar = NavigationToolbar(self.canvas, self) # print [item for item in dir(self.toolbar) if type(item) == QtGui.QDialog] self.cid = self.canvas.mpl_connect("button_press_event", self.disableAutoScaling) self.setStyleSheet( "QPushButton{\ color:rgb(189,195, 199); \ background:rgb(70, 80, 88)}" ) self.toolbarFrame = QtGui.QFrame() toolbarFrameLayout = QtGui.QVBoxLayout() toolbarFrameLayout.addWidget(self.toolbar) self.toolbar.setParent(None) self.toolbarFrame.setLayout(toolbarFrameLayout) self.toolbarFrame.setStyleSheet( "\ border:2px solid rgb(0,0,0);\ color:rgb(189,195,199); \ background:rgb(70, 80, 88);\ " ) self.toolbar.setStyleSheet( "\ border:0px solid rgb(0,0,0);\ QDialog{background:rgb(250, 80, 88)}\ " ) # print dir(self.toolbar) # print self.toolbar.children() # print self.toolbar.setPalette self.matPlotInfo = QtGui.QLabel() self.alertFont = QtGui.QFont() self.alertFont.setPointSize(12) self.matPlotInfo.setStyleSheet("color:rgb(200, 69, 50);") self.matPlotInfo.setText("Auto refresh disabled, click HOME button to enable.") self.matPlotInfo.setFont(self.alertFont) self.refreshRateSec = device.getFrame().getPlotRefreshRate() self.timer = QtCore.QTimer(self) self.hidden = True self.home = True self.currTimeRange = 120 self.plot(self.currTimeRange) self.timer.timeout.connect(partial(self.plot, self.currTimeRange)) self.timer.start(self.refreshRateSec * 1000) # did it store data? self.dataOk = True self.hideButton = QtGui.QPushButton("Show Plot") self.hideButton.clicked.connect(self.togglePlot) self.thrtysecButton = QtGui.QPushButton("30 Sec") self.thrtysecButton.clicked.connect(partial(self.plot, 30)) self.twoMinButton = QtGui.QPushButton("2 Min") self.twoMinButton.clicked.connect(partial(self.plot, 120)) self.fiveMinButton = QtGui.QPushButton("5 Min") self.fiveMinButton.clicked.connect(partial(self.plot, 300)) self.thrtyMinButton = QtGui.QPushButton("30 Min") self.thrtyMinButton.clicked.connect(partial(self.plot, 1800)) self.twoHrButton = QtGui.QPushButton("2 Hr") self.twoHrButton.clicked.connect(partial(self.plot, 7200)) self.tenHrButton = QtGui.QPushButton("10 Hr") self.tenHrButton.clicked.connect(partial(self.plot, 36000)) self.oneDayButton = QtGui.QPushButton("24 Hr") self.oneDayButton.clicked.connect(partial(self.plot, 86400)) self.oneWkButton = QtGui.QPushButton("1 Wk") self.oneWkButton.clicked.connect(partial(self.plot, 604800)) self.twoWkButton = QtGui.QPushButton("2 Wk") self.twoWkButton.clicked.connect(partial(self.plot, 1209600)) self.allButton = QtGui.QPushButton("All Time") self.allButton.clicked.connect(partial(self.plot, None)) self.canvas.hide() self.toolbar.hide() # set the layout buttonLayout = QtGui.QHBoxLayout() buttonLayout.addWidget(self.hideButton) buttonLayout.addStretch(0) buttonLayout2 = QtGui.QHBoxLayout() buttonLayout3 = QtGui.QHBoxLayout() buttonLayout2.addWidget(self.thrtysecButton) buttonLayout2.addWidget(self.twoMinButton) buttonLayout2.addWidget(self.fiveMinButton) buttonLayout2.addWidget(self.thrtyMinButton) buttonLayout2.addWidget(self.twoHrButton) buttonLayout2.addStretch(0) buttonLayout3.addWidget(self.tenHrButton) buttonLayout3.addWidget(self.oneDayButton) buttonLayout3.addWidget(self.oneWkButton) buttonLayout3.addWidget(self.twoWkButton) buttonLayout3.addWidget(self.allButton) buttonLayout3.addStretch(0) self.thrtysecButton.hide() self.twoMinButton.hide() self.fiveMinButton.hide() self.thrtyMinButton.hide() self.twoHrButton.hide() self.tenHrButton.hide() self.oneDayButton.hide() self.oneWkButton.hide() self.twoWkButton.hide() self.allButton.hide() self.matframe.hide() self.matPlotInfo.hide() self.toolbarFrame.hide() layout = QtGui.QVBoxLayout() layout.addLayout(buttonLayout) layout.addLayout(buttonLayout2) layout.addLayout(buttonLayout3) layout.addWidget(self.matPlotInfo) layout.addWidget(self.matframe) layout.addWidget(self.toolbarFrame) self.setLayout(layout) def enableAutoScaling(self): self.timer.start(self.refreshRateSec * 1000) # self.canvas.mpl_disconnect(self.cid) # self.cid = self.canvas.mpl_connect('button_press_event', self.disableAutoScaling) self.home = True self.matPlotInfo.hide() # self.deviceThread = threading.Thread(target = # self.plot, args=[self.currTimeRange]) # If the main thread stops, stop the child thread # self.deviceThread.daemon = True # Start the thread # self.deviceThread.start() self.plot(self.currTimeRange) def disableAutoScaling(self, event): self.home = False self.matPlotInfo.show() self.canvas.update() # plt.show() # print event.name # self.canvas.mpl_disconnect(self.cid) # self.cid = self.canvas.mpl_connect('button_press_event', self.enableAutoScaling) self.timer.stop() # self.zoom(self.toolbar) def togglePlot(self): if not self.hidden: self.canvas.hide() self.toolbar.hide() self.thrtysecButton.hide() self.twoMinButton.hide() self.fiveMinButton.hide() self.thrtyMinButton.hide() self.twoHrButton.hide() self.tenHrButton.hide() self.oneDayButton.hide() self.oneWkButton.hide() self.twoWkButton.hide() self.allButton.hide() self.matPlotInfo.hide() self.matframe.hide() self.toolbarFrame.hide() self.timer.stop() self.hideButton.setText("Show Plot") self.hidden = True elif self.hidden: self.canvas.show() self.toolbar.show() self.thrtysecButton.show() self.twoMinButton.show() self.fiveMinButton.show() self.thrtyMinButton.show() self.twoHrButton.show() self.tenHrButton.show() self.oneDayButton.show() self.oneWkButton.show() self.twoWkButton.show() self.allButton.show() self.plot(self.currTimeRange) self.matframe.show() self.toolbarFrame.show() self.timer.start(self.refreshRateSec * 1000) self.hideButton.setText("Hide Plot") self.enableAutoScaling() self.hidden = False def plot(self, timeRange): if not self.hidden: if timeRange != self.currTimeRange: self.timer.stop() self.timer.timeout.disconnect() self.currTimeRange = timeRange self.timer.timeout.connect(lambda: self.plot(self.currTimeRange)) self.timer.start(self.refreshRateSec * 1000) if self.refreshRateSec != self.device.getFrame().getPlotRefreshRate(): # print "New plot refresh rate: ", self.device.getFrame().getPlotRefreshRate() self.refreshRateSec = self.device.getFrame().getPlotRefreshRate() self.timer.stop() self.timer.timeout.disconnect() self.currTimeRange = timeRange self.timer.timeout.connect(lambda: self.plot(self.currTimeRange)) self.timer.start(self.refreshRateSec * 1000) dataSet = self.device.getFrame().getDataSet() # If the dataset exists if dataSet is not None: # Get all data from the dataset data = dataSet.getData() self.ax.hold(False) try: # for each entry in the dataset [[time], [[data], [data], [data...]]] # print data # Get the corresponding times that the values were recorded for i in range(1, len(data[-1])): # Get colum. aka all values from parameter i over time column = [row[i] for row in data] # print times # If the there is no defined a time range if self.currTimeRange is None: times = [datetime.datetime.fromtimestamp(row[0]) for row in data] # Plot all of the data (columns) vs time # self.ax.plot_date(times, column, label = # dataSet.getVariables()[1][i-1][0]) pass else: # Otherwise, if the user PREVIOUSLY defined a time range, # we need to look for the beginning of it. # Start by getting the current time dstamp = dateStamp() # The dataset should be from now to -timerange # time(now)-time(range) startTime = dstamp.utcNowFloat() - self.currTimeRange # If timeRange is not None, then we know we need # to display only a certain range of values # However, if the starttime defined is less than the lowest time, we # do not have enough data to display the whole thing, so we must # display all that we have instead. We do this by setting # currTimeRange = 0. if timeRange is not None and startTime < float(data[0][0]): self.currTimeRange = None # For all entries in data for y in range(len(data)): # We are searching backwards through the dataset to find a time # just before the time range specified if data[len(data) - y - 1][0] < startTime: # once we find it, we know the beginning index of the data to be # displayed index = y # Get the times and datafrom the index and columns to the end of the dataset times = [datetime.datetime.fromtimestamp(row[0]) for row in data[-index:]] # print times[0] column = [row[i] for row in data[-index:]] # Exit the loop break try: while len(self.line) <= i: self.line.append(self.ax.plot(1, 1, label=dataSet.getVariables()[1][i - 1][0])[0]) self.line[i].set_data(times, column) self.ax.legend(loc="upper left", shadow=True, fancybox=True) # maxi = max(column) # mini = min(column) # newMax = max(column) # newMini = min(column) # if(newMax>maxi) # maxi=newMax # self.ax.set_ylim(mini-mini/2, maxi+maxi/2) # if(newMini<mini) # self.ax.set_ylim(mini-mini/2, maxi+maxi/2) # maxi = max(column) # mini = min(column) # self.ax.set_ylim(mini-mini/2, maxi+maxi/2) # self.ax.set_xlim(min(times), max(times)) # self.ax.draw_artist(self.line[i]) except: traceback.print_exc() # print "Failed to log data" # Add a legend legend = self.ax.legend(loc="upper left") self.ax.set_title( self.device.getFrame().getTitle(), color=(189.0 / 255, 195.0 / 255, 199.0 / 255) ) if ( self.device.getFrame().getYLabel() is not None and len(self.device.getFrame().getCustomUnits()) is not 0 ): self.ax.set_ylabel( self.device.getFrame().getYLabel() + " (" + self.device.getFrame().getCustomUnits() + ")" ) elif ( self.device.getFrame().getYLabel() is not None and len(self.device.getFrame().getUnits()[i - 1]) is not 0 ): self.ax.set_ylabel( self.device.getFrame().getYLabel() + " (" + self.device.getFrame().getUnits()[i - 1] + ")" ) self.ax.set_xlabel("Time") self.ax.hold(True) # locator = AutoDateLocator() # self.ax.fmt_xdata = AutoDateFormatter() # self.ax.xaxis.set_major_locator(locator) # self.ax.xaxis.set_major_locator(locator) # self.ax.xaxis.set_major_formatter(DateFormatter('%m/%d')) # self.ax.fmt_xdata = mdates.DateFormatter('%m/%d %H:%M:%S') # print "type: ", type(times[-1]) # print "time[-1]: ",times[-1] # self.ax.set_ylim(bottom = 733681, top = 733682) # self.figure.tight_layout() self.ax.grid(True) except Exception as e: print "Error" try: self.ax.grid(True) # self.ax.clear(self.ax.yaxis) # self.ax.cla() if self.home: self.ax.set_xlim(times[0], times[-1]) self.ax.relim() self.ax.autoscale() # print self.ax.get_data_interval() self.ax.draw_artist(self.figure) self.ax.draw_artist(self.ax.patch) locator = AutoDateLocator() self.ax.xaxis.set_major_locator(locator) self.ax.xaxis.set_major_formatter(DateFormatter("%m/%d %H:%M:%S")) self.figure.autofmt_xdate() # print [time.toordinal() for time in times] self.ax.draw_artist(self.ax.yaxis) self.ax.draw_artist(self.ax.xaxis) for line in self.line: self.ax.draw_artist(line) # self.ax.axis('off') self.ax.draw_artist(legend) self.canvas.update() self.canvas.flush_events() except: times = [datetime.datetime.fromtimestamp(row[0]) for row in data] traceback.print_exc() self.ax.set_xlim(times[0], times[-1]) self.ax.relim() self.ax.autoscale() # print self.ax.get_data_interval() pass
class streamPick(QtGui.QMainWindow): def __init__(self, stream=None, parent=None): # Initialising QtGui QtCore.QLocale.setDefault(QtCore.QLocale.c()) qApp = QtGui.QApplication(sys.argv) # Init vars if stream is None: msg = 'Define stream = obspy.core.Stream()' raise ValueError(msg) self.st = stream.copy() self._picks = [] self.savefile = None self.onset_types = ['emergent', 'impulsive', 'questionable'] # Load filters from pickle try: self.bpfilter = pickle.load(open('.pick_filters', 'r')) except: self.bpfilter = [] # Internal variables # Gui vars self._shortcuts = { 'st_next': 'c', 'st_previous': 'x', 'filter_apply': 'f', 'pick_p': 'q', 'pick_s': 'w', 'pick_custom': 't', 'pick_remove': 'r', } self._plt_drag = None self._current_filter = None # Init stations self._initStations() # defines list self._stations self._stationCycle = cycle(self._stations) self._streamStation(self._stationCycle.next()) # Init QtGui QtGui.QMainWindow.__init__(self) self.setupUI() # exec QtApp qApp.exec_() def setupUI(self): ''' Setup the UI ''' self.main_widget = QtGui.QWidget(self) # Init parts of the UI self._initMenu() self._createStatusBar() self._initPlots() self._wadatiPlt = None # Define layout l = QtGui.QVBoxLayout(self.main_widget) l.addLayout(self.btnbar) l.addWidget(self.canvas) self.setCentralWidget(self.main_widget) self.setGeometry(300, 300, 1200, 800) self.setWindowTitle('obspy.core.Stream-Picker') self.show() def _initPlots(self): self.fig = Figure(facecolor='.86', dpi=72, frameon=True) # Change facecolor self.canvas = FigureCanvas(self.fig) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) # Draw the matplotlib figure self._drawFig() # Connect the events self.fig.canvas.mpl_connect('scroll_event', self._pltOnScroll) self.fig.canvas.mpl_connect('motion_notify_event', self._pltOnDrag) self.fig.canvas.mpl_connect('button_release_event', self._pltOnButtonRelease) self.fig.canvas.mpl_connect('button_press_event', self._pltOnButtonPress) def _initMenu(self): # Next and Prev Button nxt = QtGui.QPushButton('Next >>', shortcut=self._shortcuts['st_next']) nxt.clicked.connect(self._pltNextStation) nxt.setToolTip('shortcut <b>c</d>') nxt.setMaximumWidth(150) prv = QtGui.QPushButton('<< Prev', shortcut=self._shortcuts['st_previous']) prv.clicked.connect(self._pltPrevStation) prv.setToolTip('shortcut <b>x</d>') prv.setMaximumWidth(150) # Stations drop-down self.stcb = QtGui.QComboBox(self) for st in self._stations: self.stcb.addItem(st) self.stcb.activated.connect(self._pltStation) self.stcb.setMaximumWidth(100) self.stcb.setMinimumWidth(80) # Filter buttons self.fltrbtn = QtGui.QPushButton( 'Filter Trace', shortcut=self._shortcuts['filter_apply']) self.fltrbtn.setToolTip('shortcut <b>f</b>') self.fltrbtn.setCheckable(True) #self.fltrbtn.setAutoFillBackground(True) self.fltrbtn.setStyleSheet( QtCore.QString( 'QPushButton:checked {background-color: lightgreen;}')) self.fltrbtn.clicked.connect(self._appFilter) self.fltrcb = QtGui.QComboBox(self) self.fltrcb.activated.connect(self._changeFilter) self.fltrcb.setMaximumWidth(170) self.fltrcb.setMinimumWidth(150) self._updateFilterCB() # fill QComboBox # edit/delete filer buttons fltredit = QtGui.QPushButton('Edit') fltredit.resize(fltredit.sizeHint()) fltredit.clicked.connect(self._editFilter) fltrdel = QtGui.QPushButton('Delete') fltrdel.resize(fltrdel.sizeHint()) fltrdel.clicked.connect(self._deleteFilter) btnstyle = QtGui.QFrame(fltredit) btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) btnstyle = QtGui.QFrame(fltrdel) btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) # onset type _radbtn = [] for _o in self.onset_types: _radbtn.append(QtGui.QRadioButton(str(_o[0].upper()))) _radbtn[-1].setToolTip('Onset ' + _o) _radbtn[-1].clicked.connect(self._drawPicks) if _o == 'impulsive': _radbtn[-1].setChecked(True) self.onsetGrp = QtGui.QButtonGroup() self.onsetGrp.setExclusive(True) onsetbtns = QtGui.QHBoxLayout() for _i, _btn in enumerate(_radbtn): self.onsetGrp.addButton(_btn, _i) onsetbtns.addWidget(_btn) # Arrange buttons vline = QtGui.QFrame() vline.setFrameStyle(QtGui.QFrame.VLine | QtGui.QFrame.Raised) self.btnbar = QtGui.QHBoxLayout() self.btnbar.addWidget(prv) self.btnbar.addWidget(nxt) self.btnbar.addWidget(QtGui.QLabel('Station')) self.btnbar.addWidget(self.stcb) ## self.btnbar.addWidget(vline) self.btnbar.addWidget(self.fltrbtn) self.btnbar.addWidget(self.fltrcb) self.btnbar.addWidget(fltredit) self.btnbar.addWidget(fltrdel) ## self.btnbar.addWidget(vline) self.btnbar.addWidget(QtGui.QLabel('Pick Onset: ')) self.btnbar.addLayout(onsetbtns) self.btnbar.addStretch(3) # Menubar menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(QtGui.QIcon().fromTheme('document-save'), 'Save', self._saveCatalog) fileMenu.addAction(QtGui.QIcon().fromTheme('document-save'), 'Save as QuakeML File', self._saveCatalogDlg) fileMenu.addAction(QtGui.QIcon().fromTheme('document-open'), 'Load QuakeML File', self._openCatalogDlg) fileMenu.addSeparator() fileMenu.addAction('Save Plot', self._savePlotDlg) fileMenu.addSeparator() fileMenu.addAction(QtGui.QIcon().fromTheme('application-exit'), 'Exit', self.close) #windowMenu = menubar.addMenu('&Windows') #windowMenu.addAction('Wadati Diagram', self._opnWadatiPlot) aboutMenu = menubar.addMenu('&About') aboutMenu.addAction(QtGui.QIcon().fromTheme('info'), 'Info', self._infoDlg) def _drawFig(self): ''' Draws all matplotlib figures ''' num_plots = len(self._current_st) self.fig.clear() self._appFilter(draw=False) for _i, tr in enumerate(self._current_st): ax = self.fig.add_subplot(num_plots, 1, _i) ax.plot(tr.data, 'k', antialiased=True, rasterized=True, lod=False) ax.axhline(0, color='k', alpha=.05) ax.set_xlim([0, tr.data.size]) ax.text(.02, .925, self._current_st[_i].id, transform=ax.transAxes, va='top', ha='left', alpha=.75) ax.channel = tr.stats.channel if _i == 0: ax.set_xlabel('Seconds') # plot picks self._drawPicks(draw=False) self.fig.suptitle('%s - %s - %s / %.1f Hz / %d samples per chanel' % (self._current_st[-1].stats.network, self._current_st[-1].stats.station, self._current_st[-1].stats.starttime.isoformat(), 1. / self._current_st[-1].stats.delta, self._current_st[-1].stats.npts), x=.2) self._updateSB() self._canvasDraw() def _initStations(self): ''' Creates a list holding unique station names ''' self._stations = [] for _tr in self.st: if _tr.stats.station not in self._stations: self._stations.append(_tr.stats.station) self._stations.sort() def _getPhases(self): ''' Creates a list holding unique phase names ''' phases = [] for _pick in self._picks: if _pick.phase_hint not in phases: phases.append(_pick.phase_hint) return phases def _streamStation(self, station): ''' Copies the current stream object from self.st through obspy.stream.select(station=) ''' if station not in self._stations: return self._current_st = self.st.select(station=station).copy() self._current_stname = station self._current_network = self._current_st[0].stats.network # Sort and detrend streams self._current_st.sort(['channel']) self._current_st.detrend('linear') def _setPick(self, xdata, phase, channel, polarity='undecideable', overwrite_existing=False): ''' Write obspy.core.event.Pick into self._picks list ''' picktime = self._current_st[0].stats.starttime +\ (xdata * self._current_st[0].stats.delta) this_pick = event.Pick() overwrite = True # Overwrite existing phase's picktime if overwrite_existing: for _pick in self._getPicks(): if _pick.phase_hint == phase and\ _pick.waveform_id.channel_code == channel: this_pick = _pick overwrite = False break creation_info = event.CreationInfo(author='ObsPy.StreamPick', creation_time=UTCDateTime()) # Create new event.Pick() this_pick.time = picktime this_pick.phase_hint = phase this_pick.waveform_id = event.WaveformStreamID( network_code=self._current_st[0].stats.network, station_code=self._current_st[0].stats.station, location_code=self._current_st[0].stats.location, channel_code=channel) this_pick.evaluation_mode = 'manual' this_pick.creation_info = creation_info this_pick.onset = self.onset_types[self.onsetGrp.checkedId()] this_pick.evaluation_status = 'preliminary' this_pick.polarity = polarity #if self._current_filter is not None: # this_pick.comments.append(event.Comment( # text=str(self.bpfilter[self.fltrcb.currentIndex()]))) if overwrite: self._picks.append(this_pick) def _delPicks(self, network, station, channel): ''' Deletes pick from catalog ''' for _i, _pick in enumerate(self._picks): if _pick.waveform_id.network_code == network\ and _pick.waveform_id.station_code == station\ and _pick.waveform_id.channel_code == channel: self._picks.remove(_pick) def _getPicks(self): ''' Create a list of picks for the current plot ''' this_st_picks = [] for _i, pick in enumerate(self._picks): if pick.waveform_id.station_code == self._current_stname and\ self._current_st[0].stats.starttime <\ pick.time < self._current_st[0].stats.endtime: this_st_picks.append(_i) return [self._picks[i] for i in this_st_picks] def _getPickXPosition(self, picks): ''' Convert picktimes into relative positions along x-axis ''' xpicks = [] for _pick in picks: xpicks.append((_pick.time - self._current_st[0].stats.starttime) / self._current_st[0].stats.delta) return np.array(xpicks) def _drawPicks(self, draw=True): ''' Draw picklines onto axes ''' picks = self._getPicks() xpicks = self._getPickXPosition(picks) for _ax in self.fig.get_axes(): lines = [] labels = [] points = [] transOffset = offset_copy(_ax.transData, fig=self.fig, x=5, y=0, units='points') for _i, _xpick in enumerate(xpicks): if picks[_i].phase_hint == 'S': color = 'r' elif picks[_i].phase_hint == 'P': color = 'g' else: color = 'b' if _ax.channel != picks[_i].waveform_id.channel_code: alpha = .2 else: alpha = .8 lines.append( matplotlib.lines.Line2D( [_xpick, _xpick], [_ax.get_ylim()[0] * .9, _ax.get_ylim()[1] * .8], color=color, alpha=alpha, rasterized=True)) lines[-1].obspy_pick = picks[_i] points.append( matplotlib.lines.Line2D( [_xpick], [_ax.lines[0].get_ydata()[int(_xpick)]], marker='o', mfc=color, mec=color, alpha=alpha, ms=5)) labels.append( matplotlib.text.Text(_xpick, _ax.get_ylim()[0] * .8, text=picks[_i].phase_hint, color=color, size=10, alpha=alpha, transform=transOffset)) # delete all artists del _ax.artists[0:] # add updated objects for li, la, po in zip(lines, labels, points): _ax.add_artist(li) _ax.add_artist(la) _ax.add_artist(po) if draw: self._canvasDraw() # Plot Controls def _pltOnScroll(self, event): ''' Scrolls/Redraws the plots along x axis ''' if event.inaxes is None: return if event.key == 'control': axes = [event.inaxes] else: axes = self.fig.get_axes() for _ax in axes: left = _ax.get_xlim()[0] right = _ax.get_xlim()[1] extent = right - left dzoom = .2 * extent aspect_left = (event.xdata - _ax.get_xlim()[0]) / extent aspect_right = (_ax.get_xlim()[1] - event.xdata) / extent if event.button == 'up': left += dzoom * aspect_left right -= dzoom * aspect_right elif event.button == 'down': left -= dzoom * aspect_left right += dzoom * aspect_right else: return _ax.set_xlim([left, right]) self._canvasDraw() def _pltOnDrag(self, event): ''' Drags/Redraws the plot upon drag ''' if event.inaxes is None: return if event.key == 'control': axes = [event.inaxes] else: axes = self.fig.get_axes() if event.button == 2: if self._plt_drag is None: self._plt_drag = event.xdata return for _ax in axes: _ax.set_xlim([ _ax.get_xlim()[0] + (self._plt_drag - event.xdata), _ax.get_xlim()[1] + (self._plt_drag - event.xdata) ]) else: return self._canvasDraw() def _pltOnButtonRelease(self, event): ''' On Button Release Reset drag variable ''' self._plt_drag = None def _pltOnButtonPress(self, event): ''' This Function is evoked when the user picks ''' if event.key is not None: event.key = event.key.lower() if event.inaxes is None: return channel = event.inaxes.channel tr_amp = event.inaxes.lines[0].get_ydata()[int(event.xdata)+3] -\ event.inaxes.lines[0].get_ydata()[int(event.xdata)] if tr_amp < 0: polarity = 'negative' elif tr_amp > 0: polarity = 'positive' else: polarity = 'undecideable' if event.key == self._shortcuts['pick_p'] and event.button == 1: self._setPick(event.xdata, phase='P', channel=channel, polarity=polarity) elif event.key == self._shortcuts['pick_s'] and event.button == 1: self._setPick(event.xdata, phase='S', channel=channel, polarity=polarity) elif event.key == self._shortcuts['pick_custom'] and event.button == 1: text, ok = QtGui.QInputDialog.getItem(self, 'Custom Phase', 'Enter phase name:', self._getPhases()) if ok: self._setPick(event.xdata, phase=text, channel=channel, polarity=polarity) elif event.key == self._shortcuts['pick_remove']: self._delPicks(network=self._current_network, station=self._current_stname, channel=channel) else: return self._updateSB() self._drawPicks() def _pltNextStation(self): ''' Plot next station ''' self._streamStation(self._stationCycle.next()) self._drawFig() def _pltPrevStation(self): ''' Plot previous station ''' for _i in range(len(self._stations) - 1): prevStation = self._stationCycle.next() self._streamStation(prevStation) self._drawFig() def _pltStation(self): ''' Plot station from DropDown Menu ''' _i = self.stcb.currentIndex() while self._stationCycle.next() != self._stations[_i]: pass self._streamStation(self._stations[_i]) self._drawFig() # Filter functions def _appFilter(self, button=True, draw=True): ''' Apply bandpass filter ''' _i = self.fltrcb.currentIndex() self._streamStation(self._current_stname) if self.fltrbtn.isChecked() is False: self._current_filter = None else: self._current_st.filter('bandpass', freqmin=self.bpfilter[_i]['freqmin'], freqmax=self.bpfilter[_i]['freqmax'], corners=self.bpfilter[_i]['corners'], zerophase=True) self._current_filter = _i for _i, _ax in enumerate(self.fig.get_axes()): if len(_ax.lines) == 0: continue _ax.lines[0].set_ydata(self._current_st[_i].data) _ax.relim() _ax.autoscale_view() if draw is True: self._drawPicks(draw=False) self._canvasDraw() self._updateSB() def _newFilter(self): ''' Create new filter ''' newFilter = self.defFilter(self) if newFilter.exec_(): self.bpfilter.append(newFilter.getValues()) self._updateFilterCB() self.fltrcb.setCurrentIndex(len(self.bpfilter) - 1) self._appFilter() def _editFilter(self): ''' Edit existing filter ''' _i = self.fltrcb.currentIndex() this_filter = self.bpfilter[_i] editFilter = self.defFilter(self, this_filter) if editFilter.exec_(): self.bpfilter[_i] = editFilter.getValues() self._updateFilterCB() self.fltrcb.setCurrentIndex(_i) self._appFilter() def _deleteFilter(self): ''' Delete filter ''' _i = self.fltrcb.currentIndex() self.fltrbtn.setChecked(False) self.bpfilter.pop(_i) self._updateFilterCB() self._appFilter() def _changeFilter(self, index): ''' Evoke this is filter in drop-down is changed ''' if index == len(self.bpfilter): return self._newFilter() else: return self._appFilter() def _updateFilterCB(self): ''' Update the filter QComboBox ''' self.fltrcb.clear() self.fltrcb.setCurrentIndex(-1) for _i, _f in enumerate(self.bpfilter): self.fltrcb.addItem('%s [%.2f - %.2f Hz]' % (_f['name'], _f['freqmin'], _f['freqmax'])) self.fltrcb.addItem('Create new Filter...') # Status bar functions def _createStatusBar(self): ''' Creates the status bar ''' sb = QtGui.QStatusBar() sb.setFixedHeight(18) self.setStatusBar(sb) self.statusBar().showMessage('Ready') def _updateSB(self, statustext=None): ''' Updates the statusbar text ''' if statustext is None: self.stcb.setCurrentIndex( self._stations.index(self._current_stname)) msg = 'Station %i/%i - %i Picks' % ( self._stations.index(self._current_stname) + 1, len(self._stations), len(self._getPicks())) if self._current_filter is not None: msg += ' - Bandpass %s [%.2f - %.2f Hz]' % ( self.bpfilter[self._current_filter]['name'], self.bpfilter[self._current_filter]['freqmin'], self.bpfilter[self._current_filter]['freqmax']) else: msg += ' - Raw Data' self.statusBar().showMessage(msg) def _openCatalogDlg(self): filename = QtGui.QFileDialog.getOpenFileName(self, 'Load QuakeML Picks', os.getcwd(), 'QuakeML Format (*.xml)', '20') if filename: self._openCatalog(str(filename)) self.savefile = str(filename) def _openCatalog(self, filename): ''' Open existing QuakeML catalog ''' try: print 'Opening QuakeML Catalog %s' % filename cat = event.readEvents(filename) self._picks = cat[0].picks self._drawPicks() except: msg = 'Could not open QuakeML file %s' % (filename) raise IOError(msg) def _saveCatalogDlg(self): ''' Save catalog through QtDialog ''' self.savefile = QtGui.QFileDialog.getSaveFileName( self, 'Save QuakeML Picks', os.getcwd(), 'QuakeML Format (*.xml)') if not self.savefile: self.savefile = None return self.savefile = str(self.savefile) if os.path.splitext(self.savefile)[1].lower() != '.xml': self.savefile += '.xml' self._saveCatalog() def _saveCatalog(self, filename=None): ''' Saves the catalog to filename ''' if self.savefile is None and filename is None: return self._saveCatalogDlg() if filename is not None: savefile = filename else: savefile = self.savefile cat = event.Catalog() cat.events.append(event.Event(picks=self._picks)) cat.write(savefile, format='QUAKEML') print 'Picks saved as %s' % savefile def _savePlotDlg(self): ''' Save Plot Image Qt Dialog and Matplotlib wrapper ''' filename = QtGui.QFileDialog.getSaveFileName( self, 'Save Plot', os.getcwd(), 'Image Format (*.png *.pdf *.ps *.svg *.eps)') if not filename: return filename = str(filename) format = os.path.splitext(filename)[1][1:].lower() if format not in ['png', 'pdf', 'ps', 'svg', 'eps']: format = 'png' filename += '.' + format self.fig.savefig(filename=filename, format=format, dpi=72) def getPicks(self): return self._picks def _opnWadatiPlot(self): self._wadatiPlt = QtGui.NewWindow() self._wadatiPlt.show() def _infoDlg(self): msg = """ <h3><b>obspy.core.stream-Picker</b></h3> <br><br> <div> StreamPick is a lightweight seismological wave time picker for <code>obspy.core.Stream()</code> objects. It further utilises the <code>obspy.core.event</code> class to store picks in the QuakeML format. </div> <h4>Controls:</h4> <blockquote> <table> <tr> <td width=20><b>%s</b></td><td>Next station</td> </tr> <tr> <td width=20><b>%s</b></td><td>Previous station</td> </tr> <tr> <td width=20><b>%s</b></td><td>Toggle filter</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set P-Phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set S-Phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set custom phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Remove last pick in trace</td> </tr> </table> </blockquote> <h4>Plot Controls:</h4> <blockquote> Use mouse wheel to zoom in- and out. Middle mouse button moves plot along x-axis.<br> Hit <b>Ctrl</b> to manipulate a single plot. <br> </blockquote> <div> Programm stores filter parameters in <code>.pick_filter</code> and a backup of recent picks in <code>.picks-obspy.xml.bak</code>.<br><br> See <a href=http://www.github.org/miili/StreamPick> http://www.github.org/miili/StreamPick</a> and <a href=http://www.obspy.org>http://www.obspy.org</a> for further documentation. </div> """ % ( self._shortcuts['st_next'], self._shortcuts['st_previous'], self._shortcuts['filter_apply'], self._shortcuts['pick_p'], self._shortcuts['pick_s'], self._shortcuts['pick_custom'], self._shortcuts['pick_remove'], ) QtGui.QMessageBox.about(self, 'About', msg) def _canvasDraw(self): ''' Redraws the canvas and re-sets mouse focus ''' for _i, _ax in enumerate(self.fig.get_axes()): _ax.set_xticklabels(_ax.get_xticks() * self._current_st[_i].stats.delta) self.canvas.draw_idle() self.canvas.flush_events() self.canvas.setFocus() return def closeEvent(self, evnt): ''' This function is called upon closing the QtGui ''' # Save Picks pickle.dump(self.bpfilter, open('.pick_filters', 'w')) # Save Catalog if len(self._picks) > 0: self._saveCatalog('.picks-obspy.xml.bak') if self.savefile is None and len(self._picks) > 0: ask = QtGui.QMessageBox.question( self, 'Save Picks?', 'Do you want to save your picks?', QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) if ask == QtGui.QMessageBox.Save: self._saveCatalog() elif ask == QtGui.QMessageBox.Cancel: evnt.ignore() print self._picks # Filter Dialog class defFilter(QtGui.QDialog): def __init__(self, parent=None, filtervalues=None): ''' Bandpass filter dialog... Qt layout and stuff ''' QtGui.QDialog.__init__(self, parent) self.setWindowTitle('Create new Bandpass-Filter') # Frequency QDoubleSpinBoxes self.frqmin = QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=0.1) self.frqmax = QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=10.0) # Radio buttons for corners _corners = [2, 4, 8] _radbtn = [] for _c in _corners: _radbtn.append(QtGui.QRadioButton(str(_c))) if _c == 4: _radbtn[-1].setChecked(True) self.corner = QtGui.QButtonGroup() self.corner.setExclusive(True) radiogrp = QtGui.QHBoxLayout() for _i, _r in enumerate(_radbtn): self.corner.addButton(_r, _corners[_i]) radiogrp.addWidget(_radbtn[_i]) # Filter name self.fltname = QtGui.QLineEdit('Filter Name') self.fltname.selectAll() # Make Layout grid = QtGui.QGridLayout() grid.addWidget(QtGui.QLabel('Filter Name'), 0, 0) grid.addWidget(self.fltname, 0, 1) grid.addWidget(QtGui.QLabel('Min. Frequency'), 1, 0) grid.addWidget(self.frqmin, 1, 1) grid.addWidget(QtGui.QLabel('Max. Frequency'), 2, 0) grid.addWidget(self.frqmax, 2, 1) grid.addWidget(QtGui.QLabel('Corners'), 3, 0) grid.addLayout(radiogrp, 3, 1) grid.setVerticalSpacing(10) btnbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) btnbox.accepted.connect(self.accept) btnbox.rejected.connect(self.reject) layout = QtGui.QVBoxLayout() layout.addWidget( QtGui.QLabel( 'Define a minimum and maximum' + ' frequency\nfor the bandpass filter.\nFunction utilises ' + 'obspy.signal.filter (zerophase=True).\n')) layout.addLayout(grid) layout.addWidget(btnbox) if filtervalues is not None: self.fltname.setText(filtervalues['name']) self.frqmin.setValue(filtervalues['freqmin']) self.frqmax.setValue(filtervalues['freqmax']) self.corner.button(filtervalues['corners']).setChecked(True) self.setLayout(layout) self.setSizeGripEnabled(False) def getValues(self): ''' Return filter dialogs values as a dictionary ''' return dict(name=str(self.fltname.text()), freqmin=float(self.frqmin.cleanText()), freqmax=float(self.frqmax.cleanText()), corners=int(int(self.corner.checkedId())))
class SecondUiClass(QtGui.QMainWindow): # class variables pressure = np.array([]) ion_pressure = np.array([]) date = np.array([]) import_pressure = np.array([]) import_date = np.array([]) Log_pressure = False Import = False def __init__(self, parent=None): super(SecondUiClass, self).__init__(parent) # create window self._main = QtGui.QWidget() self.setCentralWidget(self._main) self.layout = QtGui.QVBoxLayout(self._main) self.setGeometry(100, 100, 1000, 600) self.setWindowTitle("FHiRE Vacuum Controller - Graphing Window") #set up action menu actionPressure = QtGui.QAction("Graph Pressure", self) actionLog_Pressure = QtGui.QAction("Graph Log Pressure", self) actionPressure.triggered.connect(self.PlotPressure) actionLog_Pressure.triggered.connect(self.PlotLogPressure) mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('&Options') fileMenu.addAction(actionPressure) fileMenu.addAction(actionLog_Pressure) # set up figure self.figure = Figure() self.canvas = FigureCanvas(self.figure) self.layout.addWidget(self.canvas) self.toolbar = NavigationToolbar(self.canvas, self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar) # main plot process def Plot(self, dat_file): # set up graph self.ax = self.figure.add_subplot(111) self.ax.hold(False) # check if import or live data if dat_file == False: self.ax.plot(self.date, self.pressure, 'r-') else: self.Import = True self.ax.plot(self.import_date, self.import_pressure, 'r-') # format axes self.ax.set_xlabel('Time (h:m:s)') self.ax.set_ylabel('Pressure (Torr)') myFmt = mdates.DateFormatter('%H:%M:%S') self.ax.xaxis.set_major_formatter(myFmt) self.ax.xaxis.set_minor_locator(AutoMinorLocator()) self.ax.yaxis.set_minor_locator(AutoMinorLocator()) self.canvas.draw() self.canvas.flush_events() # modify plot to show pressure or log pressure def PlotPressure(self): self.Log_pressure = False self.updateThread() def PlotLogPressure(self): self.Log_pressure = True self.updateThread() # update graph def updateThread(self): update_thread = threading.Thread(target=self.UpdatePlot) update_thread.start() def UpdatePlot(self): # check if graphing imported data, live data, log pressure or pressure if self.Log_pressure == False and self.Import == False: self.ax.plot(self.date, self.pressure, 'r-') self.ax.set_ylabel('Pressure (Torr)') elif self.Log_pressure == False and self.Import == True: self.ax.plot(self.import_date, self.import_pressure, 'r-') self.ax.set_ylabel('Pressure (Torr)') elif self.Log_pressure == True and self.Import == False: self.ax.plot(self.date, np.log10(self.pressure), 'r-') self.ax.set_ylabel('Log Pressure (Torr)') else: self.ax.plot(self.import_date, np.log10(self.import_pressure), 'r-') self.ax.set_ylabel('Log Pressure (Torr)') # format axes self.ax.set_xlabel('Time (h:m:s)') myFmt = mdates.DateFormatter('%I:%M:%S') self.ax.xaxis.set_major_formatter(myFmt) self.ax.xaxis.set_minor_locator(AutoMinorLocator()) self.ax.yaxis.set_minor_locator(AutoMinorLocator()) self.ax.relim() self.ax.autoscale_view() self.toolbar.update() self.canvas.draw() self.canvas.flush_events()
class streamPick(QtGui.QMainWindow): def __init__(self, stream=None, parent=None): # Initialising QtGui QtCore.QLocale.setDefault(QtCore.QLocale.c()) qApp = QtGui.QApplication(sys.argv) # Init vars if stream is None: msg = "Define stream = obspy.core.Stream()" raise ValueError(msg) self.st = stream.copy() self._picks = [] self.savefile = None self.onset_types = ["emergent", "impulsive", "questionable"] # Load filters from pickle try: self.bpfilter = pickle.load(open(".pick_filters", "r")) except: self.bpfilter = [] # Internal variables # Gui vars self._shortcuts = { "st_next": "c", "st_previous": "x", "filter_apply": "f", "pick_p": "p", "pick_s": "s", "pick_custom": "t", "pick_remove": "r", } self._plt_drag = None self._current_filter = None # Init stations self._initStations() # defines list self._stations self._stationCycle = cycle(self._stations) self._streamStation(self._stationCycle.next()) # Init QtGui QtGui.QMainWindow.__init__(self) self.setupUI() # exec QtApp qApp.exec_() def setupUI(self): """ Setup the UI """ self.main_widget = QtGui.QWidget(self) # Init parts of the UI self._initMenu() self._createStatusBar() self._initPlots() self._wadatiPlt = None # Define layout l = QtGui.QVBoxLayout(self.main_widget) l.addLayout(self.btnbar) l.addWidget(self.canvas) self.setCentralWidget(self.main_widget) self.setGeometry(300, 300, 1200, 800) self.setWindowTitle("obspy.core.Stream-Picker") self.show() def _initPlots(self): self.fig = Figure(facecolor=".86", dpi=72, frameon=True) # Change facecolor self.canvas = FigureCanvas(self.fig) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) # Draw the matplotlib figure self._drawFig() # Connect the events self.fig.canvas.mpl_connect("scroll_event", self._pltOnScroll) self.fig.canvas.mpl_connect("motion_notify_event", self._pltOnDrag) self.fig.canvas.mpl_connect("button_release_event", self._pltOnButtonRelease) self.fig.canvas.mpl_connect("button_press_event", self._pltOnButtonPress) def _initMenu(self): # Next and Prev Button nxt = QtGui.QPushButton("Next >>", shortcut=self._shortcuts["st_next"]) nxt.clicked.connect(self._pltNextStation) nxt.setToolTip("shortcut <b>c</d>") nxt.setMaximumWidth(150) prv = QtGui.QPushButton("<< Prev", shortcut=self._shortcuts["st_previous"]) prv.clicked.connect(self._pltPrevStation) prv.setToolTip("shortcut <b>x</d>") prv.setMaximumWidth(150) # Stations drop-down self.stcb = QtGui.QComboBox(self) for st in self._stations: self.stcb.addItem(st) self.stcb.activated.connect(self._pltStation) self.stcb.setMaximumWidth(100) self.stcb.setMinimumWidth(80) # Filter buttons self.fltrbtn = QtGui.QPushButton("Filter Trace", shortcut=self._shortcuts["filter_apply"]) self.fltrbtn.setToolTip("shortcut <b>f</b>") self.fltrbtn.setCheckable(True) # self.fltrbtn.setAutoFillBackground(True) self.fltrbtn.setStyleSheet(QtCore.QString("QPushButton:checked {background-color: lightgreen;}")) self.fltrbtn.clicked.connect(self._appFilter) self.fltrcb = QtGui.QComboBox(self) self.fltrcb.activated.connect(self._changeFilter) self.fltrcb.setMaximumWidth(170) self.fltrcb.setMinimumWidth(150) self._updateFilterCB() # fill QComboBox # edit/delete filer buttons fltredit = QtGui.QPushButton("Edit") fltredit.resize(fltredit.sizeHint()) fltredit.clicked.connect(self._editFilter) fltrdel = QtGui.QPushButton("Delete") fltrdel.resize(fltrdel.sizeHint()) fltrdel.clicked.connect(self._deleteFilter) btnstyle = QtGui.QFrame(fltredit) btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) btnstyle = QtGui.QFrame(fltrdel) btnstyle.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain) # onset type _radbtn = [] for _o in self.onset_types: _radbtn.append(QtGui.QRadioButton(str(_o[0].upper()))) _radbtn[-1].setToolTip("Onset " + _o) _radbtn[-1].clicked.connect(self._drawPicks) if _o == "impulsive": _radbtn[-1].setChecked(True) self.onsetGrp = QtGui.QButtonGroup() self.onsetGrp.setExclusive(True) onsetbtns = QtGui.QHBoxLayout() for _i, _btn in enumerate(_radbtn): self.onsetGrp.addButton(_btn, _i) onsetbtns.addWidget(_btn) # Arrange buttons vline = QtGui.QFrame() vline.setFrameStyle(QtGui.QFrame.VLine | QtGui.QFrame.Raised) self.btnbar = QtGui.QHBoxLayout() self.btnbar.addWidget(prv) self.btnbar.addWidget(nxt) self.btnbar.addWidget(QtGui.QLabel("Station")) self.btnbar.addWidget(self.stcb) ## self.btnbar.addWidget(vline) self.btnbar.addWidget(self.fltrbtn) self.btnbar.addWidget(self.fltrcb) self.btnbar.addWidget(fltredit) self.btnbar.addWidget(fltrdel) ## self.btnbar.addWidget(vline) self.btnbar.addWidget(QtGui.QLabel("Pick Onset: ")) self.btnbar.addLayout(onsetbtns) self.btnbar.addStretch(3) # Menubar menubar = self.menuBar() fileMenu = menubar.addMenu("&File") fileMenu.addAction(QtGui.QIcon().fromTheme("document-save"), "Save", self._saveCatalog) fileMenu.addAction(QtGui.QIcon().fromTheme("document-save"), "Save as QuakeML File", self._saveCatalogDlg) fileMenu.addAction(QtGui.QIcon().fromTheme("document-open"), "Load QuakeML File", self._openCatalogDlg) fileMenu.addSeparator() fileMenu.addAction("Save Plot", self._savePlotDlg) fileMenu.addSeparator() fileMenu.addAction(QtGui.QIcon().fromTheme("application-exit"), "Exit", self.close) # windowMenu = menubar.addMenu('&Windows') # windowMenu.addAction('Wadati Diagram', self._opnWadatiPlot) aboutMenu = menubar.addMenu("&About") aboutMenu.addAction(QtGui.QIcon().fromTheme("info"), "Info", self._infoDlg) def _drawFig(self): """ Draws all matplotlib figures """ num_plots = len(self._current_st) self.fig.clear() self._appFilter(draw=False) for _i, tr in enumerate(self._current_st): ax = self.fig.add_subplot(num_plots, 1, _i) ax.plot(tr.data, "k", antialiased=True, rasterized=True, lod=False) ax.axhline(0, color="k", alpha=0.05) ax.set_xlim([0, tr.data.size]) ax.text(0.02, 0.925, self._current_st[_i].id, transform=ax.transAxes, va="top", ha="left", alpha=0.75) ax.channel = tr.stats.channel if _i == 0: ax.set_xlabel("Seconds") # plot picks self._drawPicks(draw=False) self.fig.suptitle( "%s - %s - %s / %.1f Hz / %d samples per chanel" % ( self._current_st[-1].stats.network, self._current_st[-1].stats.station, self._current_st[-1].stats.starttime.isoformat(), 1.0 / self._current_st[-1].stats.delta, self._current_st[-1].stats.npts, ), x=0.2, ) self._updateSB() self._canvasDraw() def _initStations(self): """ Creates a list holding unique station names """ self._stations = [] for _tr in self.st: if _tr.stats.station not in self._stations: self._stations.append(_tr.stats.station) self._stations.sort() def _getPhases(self): """ Creates a list holding unique phase names """ phases = [] for _pick in self._picks: if _pick.phase_hint not in phases: phases.append(_pick.phase_hint) return phases def _streamStation(self, station): """ Copies the current stream object from self.st through obspy.stream.select(station=) """ if station not in self._stations: return self._current_st = self.st.select(station=station).copy() self._current_stname = station self._current_network = self._current_st[0].stats.network # Sort and detrend streams self._current_st.sort(["channel"]) self._current_st.detrend("linear") def _setPick(self, xdata, phase, channel, polarity="undecideable", overwrite_existing=False): """ Write obspy.core.event.Pick into self._picks list """ picktime = self._current_st[0].stats.starttime + (xdata * self._current_st[0].stats.delta) this_pick = event.Pick() overwrite = True # Overwrite existing phase's picktime if overwrite_existing: for _pick in self._getPicks(): if _pick.phase_hint == phase and _pick.waveform_id.channel_code == channel: this_pick = _pick overwrite = False break creation_info = event.CreationInfo(author="ObsPy.StreamPick", creation_time=UTCDateTime()) # Create new event.Pick() this_pick.time = picktime this_pick.phase_hint = phase this_pick.waveform_id = event.WaveformStreamID( network_code=self._current_st[0].stats.network, station_code=self._current_st[0].stats.station, location_code=self._current_st[0].stats.location, channel_code=channel, ) this_pick.evaluation_mode = "manual" this_pick.creation_info = creation_info this_pick.onset = self.onset_types[self.onsetGrp.checkedId()] this_pick.evaluation_status = "preliminary" this_pick.polarity = polarity # if self._current_filter is not None: # this_pick.comments.append(event.Comment( # text=str(self.bpfilter[self.fltrcb.currentIndex()]))) if overwrite: self._picks.append(this_pick) def _delPicks(self, network, station, channel): """ Deletes pick from catalog """ for _i, _pick in enumerate(self._picks): if ( _pick.waveform_id.network_code == network and _pick.waveform_id.station_code == station and _pick.waveform_id.channel_code == channel ): self._picks.remove(_pick) def _getPicks(self): """ Create a list of picks for the current plot """ this_st_picks = [] for _i, pick in enumerate(self._picks): if ( pick.waveform_id.station_code == self._current_stname and self._current_st[0].stats.starttime < pick.time < self._current_st[0].stats.endtime ): this_st_picks.append(_i) return [self._picks[i] for i in this_st_picks] def _getPickXPosition(self, picks): """ Convert picktimes into relative positions along x-axis """ xpicks = [] for _pick in picks: xpicks.append((_pick.time - self._current_st[0].stats.starttime) / self._current_st[0].stats.delta) return np.array(xpicks) def _drawPicks(self, draw=True): """ Draw picklines onto axes """ picks = self._getPicks() xpicks = self._getPickXPosition(picks) for _ax in self.fig.get_axes(): lines = [] labels = [] points = [] transOffset = offset_copy(_ax.transData, fig=self.fig, x=5, y=0, units="points") for _i, _xpick in enumerate(xpicks): if picks[_i].phase_hint == "S": color = "r" elif picks[_i].phase_hint == "P": color = "g" else: color = "b" if _ax.channel != picks[_i].waveform_id.channel_code: alpha = 0.2 else: alpha = 0.8 lines.append( matplotlib.lines.Line2D( [_xpick, _xpick], [_ax.get_ylim()[0] * 0.9, _ax.get_ylim()[1] * 0.8], color=color, alpha=alpha, rasterized=True, ) ) lines[-1].obspy_pick = picks[_i] points.append( matplotlib.lines.Line2D( [_xpick], [_ax.lines[0].get_ydata()[int(_xpick)]], marker="o", mfc=color, mec=color, alpha=alpha, ms=5, ) ) labels.append( matplotlib.text.Text( _xpick, _ax.get_ylim()[0] * 0.8, text=picks[_i].phase_hint, color=color, size=10, alpha=alpha, transform=transOffset, ) ) # delete all artists del _ax.artists[0:] # add updated objects for li, la, po in zip(lines, labels, points): _ax.add_artist(li) _ax.add_artist(la) _ax.add_artist(po) if draw: self._canvasDraw() # Plot Controls def _pltOnScroll(self, event): """ Scrolls/Redraws the plots along x axis """ if event.inaxes is None: return if event.key == "control": axes = [event.inaxes] else: axes = self.fig.get_axes() for _ax in axes: left = _ax.get_xlim()[0] right = _ax.get_xlim()[1] extent = right - left dzoom = 0.2 * extent aspect_left = (event.xdata - _ax.get_xlim()[0]) / extent aspect_right = (_ax.get_xlim()[1] - event.xdata) / extent if event.button == "up": left += dzoom * aspect_left right -= dzoom * aspect_right elif event.button == "down": left -= dzoom * aspect_left right += dzoom * aspect_right else: return _ax.set_xlim([left, right]) self._canvasDraw() def _pltOnDrag(self, event): """ Drags/Redraws the plot upon drag """ if event.inaxes is None: return if event.key == "control": axes = [event.inaxes] else: axes = self.fig.get_axes() if event.button == 2: if self._plt_drag is None: self._plt_drag = event.xdata return for _ax in axes: _ax.set_xlim( [ _ax.get_xlim()[0] + (self._plt_drag - event.xdata), _ax.get_xlim()[1] + (self._plt_drag - event.xdata), ] ) else: return self._canvasDraw() def _pltOnButtonRelease(self, event): """ On Button Release Reset drag variable """ self._plt_drag = None def _pltOnButtonPress(self, event): """ This Function is evoked when the user picks """ print event.key if event.key is not None: event.key = event.key.lower() if event.inaxes is None: return channel = event.inaxes.channel tr_amp = ( event.inaxes.lines[0].get_ydata()[int(event.xdata) + 3] - event.inaxes.lines[0].get_ydata()[int(event.xdata)] ) if tr_amp < 0: polarity = "negative" elif tr_amp > 0: polarity = "positive" else: polarity = "undecideable" if event.key == self._shortcuts["pick_p"] and event.button == 1: self._setPick(event.xdata, phase="P", channel=channel, polarity=polarity) elif event.key == self._shortcuts["pick_s"] and event.button == 1: self._setPick(event.xdata, phase="S", channel=channel, polarity=polarity) elif event.key == self._shortcuts["pick_custom"] and event.button == 1: text, ok = QtGui.QInputDialog.getItem(self, "Custom Phase", "Enter phase name:", self._getPhases()) if ok: self._setPick(event.xdata, phase=text, channel=channel, polarity=polarity) elif event.key == self._shortcuts["pick_remove"]: self._delPicks(network=self._current_network, station=self._current_stname, channel=channel) else: return self._updateSB() self._drawPicks() def _pltNextStation(self): """ Plot next station """ self._streamStation(self._stationCycle.next()) self._drawFig() def _pltPrevStation(self): """ Plot previous station """ for _i in range(len(self._stations) - 1): prevStation = self._stationCycle.next() self._streamStation(prevStation) self._drawFig() def _pltStation(self): """ Plot station from DropDown Menu """ _i = self.stcb.currentIndex() while self._stationCycle.next() != self._stations[_i]: pass self._streamStation(self._stations[_i]) self._drawFig() # Filter functions def _appFilter(self, button=True, draw=True): """ Apply bandpass filter """ _i = self.fltrcb.currentIndex() self._streamStation(self._current_stname) if self.fltrbtn.isChecked() is False: self._current_filter = None else: self._current_st.filter( "bandpass", freqmin=self.bpfilter[_i]["freqmin"], freqmax=self.bpfilter[_i]["freqmax"], corners=self.bpfilter[_i]["corners"], zerophase=True, ) self._current_filter = _i for _i, _ax in enumerate(self.fig.get_axes()): if len(_ax.lines) == 0: continue _ax.lines[0].set_ydata(self._current_st[_i].data) _ax.relim() _ax.autoscale_view() if draw is True: self._drawPicks(draw=False) self._canvasDraw() self._updateSB() def _newFilter(self): """ Create new filter """ newFilter = self.defFilter(self) if newFilter.exec_(): self.bpfilter.append(newFilter.getValues()) self._updateFilterCB() self.fltrcb.setCurrentIndex(len(self.bpfilter) - 1) self._appFilter() def _editFilter(self): """ Edit existing filter """ _i = self.fltrcb.currentIndex() this_filter = self.bpfilter[_i] editFilter = self.defFilter(self, this_filter) if editFilter.exec_(): self.bpfilter[_i] = editFilter.getValues() self._updateFilterCB() self.fltrcb.setCurrentIndex(_i) self._appFilter() def _deleteFilter(self): """ Delete filter """ _i = self.fltrcb.currentIndex() self.fltrbtn.setChecked(False) self.bpfilter.pop(_i) self._updateFilterCB() self._appFilter() def _changeFilter(self, index): """ Evoke this is filter in drop-down is changed """ if index == len(self.bpfilter): return self._newFilter() else: return self._appFilter() def _updateFilterCB(self): """ Update the filter QComboBox """ self.fltrcb.clear() self.fltrcb.setCurrentIndex(-1) for _i, _f in enumerate(self.bpfilter): self.fltrcb.addItem("%s [%.2f - %.2f Hz]" % (_f["name"], _f["freqmin"], _f["freqmax"])) self.fltrcb.addItem("Create new Filter...") # Status bar functions def _createStatusBar(self): """ Creates the status bar """ sb = QtGui.QStatusBar() sb.setFixedHeight(18) self.setStatusBar(sb) self.statusBar().showMessage("Ready") def _updateSB(self, statustext=None): """ Updates the statusbar text """ if statustext is None: self.stcb.setCurrentIndex(self._stations.index(self._current_stname)) msg = "Station %i/%i - %i Picks" % ( self._stations.index(self._current_stname) + 1, len(self._stations), len(self._getPicks()), ) if self._current_filter is not None: msg += " - Bandpass %s [%.2f - %.2f Hz]" % ( self.bpfilter[self._current_filter]["name"], self.bpfilter[self._current_filter]["freqmin"], self.bpfilter[self._current_filter]["freqmax"], ) else: msg += " - Raw Data" self.statusBar().showMessage(msg) def _openCatalogDlg(self): filename = QtGui.QFileDialog.getOpenFileName( self, "Load QuakeML Picks", os.getcwd(), "QuakeML Format (*.xml)", "20" ) if filename: self._openCatalog(str(filename)) self.savefile = str(filename) def _openCatalog(self, filename): """ Open existing QuakeML catalog """ try: print "Opening QuakeML Catalog %s" % filename cat = event.readEvents(filename) self._picks = cat[0].picks self._drawPicks() except: msg = "Could not open QuakeML file %s" % (filename) raise IOError(msg) def _saveCatalogDlg(self): """ Save catalog through QtDialog """ self.savefile = QtGui.QFileDialog.getSaveFileName( self, "Save QuakeML Picks", os.getcwd(), "QuakeML Format (*.xml)" ) if not self.savefile: self.savefile = None return self.savefile = str(self.savefile) if os.path.splitext(self.savefile)[1].lower() != ".xml": self.savefile += ".xml" self._saveCatalog() def _saveCatalog(self, filename=None): """ Saves the catalog to filename """ if self.savefile is None and filename is None: return self._saveCatalogDlg() if filename is not None: savefile = filename else: savefile = self.savefile cat = event.Catalog() cat.events.append(event.Event(picks=self._picks)) cat.write(savefile, format="QUAKEML") print "Picks saved as %s" % savefile def _savePlotDlg(self): """ Save Plot Image Qt Dialog and Matplotlib wrapper """ filename = QtGui.QFileDialog.getSaveFileName( self, "Save Plot", os.getcwd(), "Image Format (*.png *.pdf *.ps *.svg *.eps)" ) if not filename: return filename = str(filename) format = os.path.splitext(filename)[1][1:].lower() if format not in ["png", "pdf", "ps", "svg", "eps"]: format = "png" filename += "." + format self.fig.savefig(filename=filename, format=format, dpi=72) def getPicks(self): return self._picks def _opnWadatiPlot(self): self._wadatiPlt = QtGui.NewWindow() self._wadatiPlt.show() def _infoDlg(self): msg = """ <h3><b>obspy.core.stream-Picker</b></h3> <br><br> <div> StreamPick is a lightweight seismological wave time picker for <code>obspy.core.Stream()</code> objects. It further utilises the <code>obspy.core.event</code> class to store picks in the QuakeML format. </div> <h4>Controls:</h4> <blockquote> <table> <tr> <td width=20><b>%s</b></td><td>Next station</td> </tr> <tr> <td width=20><b>%s</b></td><td>Previous station</td> </tr> <tr> <td width=20><b>%s</b></td><td>Toggle filter</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set P-Phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set S-Phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Set custom phase pick at mouse position</td> </tr> <tr> <td width=20><b>%s</b></td> <td>Remove last pick in trace</td> </tr> </table> </blockquote> <h4>Plot Controls:</h4> <blockquote> Use mouse wheel to zoom in- and out. Middle mouse button moves plot along x-axis.<br> Hit <b>Ctrl</b> to manipulate a single plot. <br> </blockquote> <div> Programm stores filter parameters in <code>.pick_filter</code> and a backup of recent picks in <code>.picks-obspy.xml.bak</code>.<br><br> See <a href=http://www.github.org/miili/StreamPick> http://www.github.org/miili/StreamPick</a> and <a href=http://www.obspy.org>http://www.obspy.org</a> for further documentation. </div> """ % ( self._shortcuts["st_next"], self._shortcuts["st_previous"], self._shortcuts["filter_apply"], self._shortcuts["pick_p"], self._shortcuts["pick_s"], self._shortcuts["pick_custom"], self._shortcuts["pick_remove"], ) QtGui.QMessageBox.about(self, "About", msg) def _canvasDraw(self): """ Redraws the canvas and re-sets mouse focus """ for _i, _ax in enumerate(self.fig.get_axes()): _ax.set_xticklabels(_ax.get_xticks() * self._current_st[_i].stats.delta) self.canvas.draw_idle() self.canvas.flush_events() self.canvas.setFocus() return def closeEvent(self, evnt): """ This function is called upon closing the QtGui """ # Save Picks pickle.dump(self.bpfilter, open(".pick_filters", "w")) # Save Catalog if len(self._picks) > 0: self._saveCatalog(".picks-obspy.xml.bak") if self.savefile is None and len(self._picks) > 0: ask = QtGui.QMessageBox.question( self, "Save Picks?", "Do you want to save your picks?", QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save, ) if ask == QtGui.QMessageBox.Save: self._saveCatalog() elif ask == QtGui.QMessageBox.Cancel: evnt.ignore() print self._picks # Filter Dialog class defFilter(QtGui.QDialog): def __init__(self, parent=None, filtervalues=None): """ Bandpass filter dialog... Qt layout and stuff """ QtGui.QDialog.__init__(self, parent) self.setWindowTitle("Create new Bandpass-Filter") # Frequency QDoubleSpinBoxes self.frqmin = QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=0.1) self.frqmax = QtGui.QDoubleSpinBox(decimals=2, maximum=100, minimum=0.01, singleStep=0.1, value=10.0) # Radio buttons for corners _corners = [2, 4, 8] _radbtn = [] for _c in _corners: _radbtn.append(QtGui.QRadioButton(str(_c))) if _c == 4: _radbtn[-1].setChecked(True) self.corner = QtGui.QButtonGroup() self.corner.setExclusive(True) radiogrp = QtGui.QHBoxLayout() for _i, _r in enumerate(_radbtn): self.corner.addButton(_r, _corners[_i]) radiogrp.addWidget(_radbtn[_i]) # Filter name self.fltname = QtGui.QLineEdit("Filter Name") self.fltname.selectAll() # Make Layout grid = QtGui.QGridLayout() grid.addWidget(QtGui.QLabel("Filter Name"), 0, 0) grid.addWidget(self.fltname, 0, 1) grid.addWidget(QtGui.QLabel("Min. Frequency"), 1, 0) grid.addWidget(self.frqmin, 1, 1) grid.addWidget(QtGui.QLabel("Max. Frequency"), 2, 0) grid.addWidget(self.frqmax, 2, 1) grid.addWidget(QtGui.QLabel("Corners"), 3, 0) grid.addLayout(radiogrp, 3, 1) grid.setVerticalSpacing(10) btnbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) btnbox.accepted.connect(self.accept) btnbox.rejected.connect(self.reject) layout = QtGui.QVBoxLayout() layout.addWidget( QtGui.QLabel( "Define a minimum and maximum" + " frequency\nfor the bandpass filter.\nFunction utilises " + "obspy.signal.filter (zerophase=True).\n" ) ) layout.addLayout(grid) layout.addWidget(btnbox) if filtervalues is not None: self.fltname.setText(filtervalues["name"]) self.frqmin.setValue(filtervalues["freqmin"]) self.frqmax.setValue(filtervalues["freqmax"]) self.corner.button(filtervalues["corners"]).setChecked(True) self.setLayout(layout) self.setSizeGripEnabled(False) def getValues(self): """ Return filter dialogs values as a dictionary """ return dict( name=str(self.fltname.text()), freqmin=float(self.frqmin.cleanText()), freqmax=float(self.frqmax.cleanText()), corners=int(int(self.corner.checkedId())), )
class SecondUiClass(QtGui.QMainWindow): Log_pressure = False Import = False filepath = None import_filepath = None def __init__(self, parent=None): super(SecondUiClass, self).__init__(parent) # Create the window. self.main = QtGui.QWidget() self.setCentralWidget(self.main) self.layout = QtGui.QVBoxLayout(self.main) self.setGeometry(100, 100, 1000, 600) self.setWindowTitle('FHiRE Vacuum Controller - Graphing Window') # Set up the action menu. actionPressure = QtGui.QAction('Graph Pressure', self) actionLog_Pressure = QtGui.QAction('Graph Log Pressure', self) actionPressure.triggered.connect(self.PlotPressure) actionLog_Pressure.triggered.connect(self.PlotLogPressure) mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('&Options') fileMenu.addAction(actionPressure) fileMenu.addAction(actionLog_Pressure) # Set up the figure. self.figure = Figure() self.canvas = FigureCanvas(self.figure) self.layout.addWidget(self.canvas) self.toolbar = NavigationToolbar(self.canvas, self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar) # Main plotting process. def Plot(self, importing): # Set up the graph. self.ax = self.figure.add_subplot(111) self.ax.hold(False) #printInfo("self.filepath: %s" %self.filepath) #printInfo("self.import_filepath: %s" %self.import_filepath) # Check if importing or using live data. self.importing = importing if self.importing == False: open_file = self.filepath else: open_file = self.import_filepath if self.import_filepath == None: printInfo("Please import a pressure log file.") # Graph pressure vs. time. try: date, pressure = np.loadtxt(open_file, unpack=True, skiprows=1) except ValueError: printInfo("Error: Need more values to graph.") return self.ax.plot(date, pressure, 'r-') filename = open_file.split('/')[-1] # Format axes. self.ax.set_title("Graphing: %s" % filename) self.ax.set_xlabel('Time (h:m:s)') self.ax.set_ylabel('Pressure (mbar)') myFmt = mdates.DateFormatter('%H:%M:%S') self.ax.xaxis.set_major_formatter(myFmt) self.ax.xaxis.set_minor_locator(AutoMinorLocator()) self.ax.yaxis.set_minor_locator(AutoMinorLocator()) y_formatter = mtick.ScalarFormatter(useOffset=True) self.ax.yaxis.set_major_formatter(y_formatter) self.ax.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.3e')) self.ax.grid() # Display the graph. self.canvas.draw() self.canvas.flush_events() # Modify the plot to show pressure or log pressure. def PlotPressure(self): self.Log_pressure = False self.updateThread() def PlotLogPressure(self): self.Log_pressure = True self.updateThread() # This thread allows updates to be made to the graph after creation. # Used for updating y axis. def updateThread(self): update_thread = threading.Thread(target=self.UpdatePlot) update_thread.setDaemon(True) update_thread.start() # Update the graph. Used for autoplotting. def UpdatePlot(self): date, pressure = np.loadtxt(self.filepath, unpack=True, skiprows=1) if self.Log_pressure == True: pressure = np.log10(pressure) self.ax.set_ylabel('Log Pressure (mbar)') else: self.ax.set_ylabel('Pressure (mbar)') self.ax.plot(date, pressure, 'r-') filename = self.filepath.split('/')[-1] self.ax.set_title("Graphing: %s" % filename) self.ax.set_xlabel('Time (h:m:s)') myFmt = mdates.DateFormatter('%I:%M:%S') self.ax.xaxis.set_major_formatter(myFmt) self.ax.xaxis.set_minor_locator(AutoMinorLocator()) self.ax.yaxis.set_minor_locator(AutoMinorLocator()) y_formatter = mtick.ScalarFormatter(useOffset=True) self.ax.yaxis.set_major_formatter(y_formatter) self.ax.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.3e')) self.ax.grid() self.ax.relim() self.ax.autoscale_view() self.toolbar.update() self.canvas.draw() self.canvas.flush_events()
class mpl_widget(QWidget): def __init__(self, parent=None, mainWidget=None): self._SELECTEDCELLS = list() # container for instances of selected cells, so we can delete them when we want self._SELECTEDCELLS_IJ = list() # container for coords of selected cells, so we can delete them when we want self._SELECTEDCELLLINES = list() # container for instances of selected cells, so we can delete them when we want self._GRIDLINES = None QWidget.__init__(self, parent) self.mainWidget = mainWidget self.create_main_frame() self.mpl_menu = mpl_menu(self) self.shift_is_held = False #self.connect(self.mpl_menu, QtCore.SIGNAL('mySignal'), self.mySlot) #print 'my parent is:', parent self.clear_selection() self.init_tooltips() def init_tooltips(self): self.canvas.setToolTip('If 2D plot => RMB click toggles menu <br> - RMB click selects cell <br> - selected cells are drawn with black border') self.grid_cb.setToolTip('If 2D plot => show computational grid <br> If 1D plot => show normal gridlines') self.cbar_button.setToolTip('If 2D plot => controls the color range. <br> Note: <br> - pressing UP and DOWN arrows cycles through colormaps <br> - dragging colorbar with RMB scales the color-range <br> - dragging colorbar with LMB shifts the color-range') self.mpl_toolbar.setToolTip('Shows coordinates (i,j, lat,lon) and data-value(z) under the cursor. <br> if you see <i>>>></i> coordinates are not visible. Enlarge the window') def create_main_frame(self): self.fig = Figure(dpi=100) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvas.setFocusPolicy( Qt.ClickFocus ) self.canvas.setFocus() self.mpl_toolbar = myNavigationToolbar(self.canvas, self) self.canvas.mpl_connect('button_press_event', self.on_click) self.canvas.mpl_connect('key_press_event', self.on_key_press) self.canvas.mpl_connect('key_release_event', self.on_key_release) #self.canvas.mpl_connect('button_press_event', self.disable_clicks) self.cbar_button = QPushButton("Color Range") self.cbar_button.setFocusPolicy( Qt.NoFocus ) self.grid_cb = QCheckBox("Show Grid") self.grid_cb.setFocusPolicy( Qt.NoFocus ) self.grid_cb.stateChanged.connect(self.showGrid) vbox = QVBoxLayout() hbox = QHBoxLayout() vbox.addWidget(self.canvas) # the matplotlib canvas hbox.addWidget(self.mpl_toolbar) hbox.addWidget(self.cbar_button) hbox.addWidget(self.grid_cb) vbox.addLayout(hbox) self.setLayout(vbox) def on_click(self, event): if event.inaxes != self.get_axes()[0]: return #if self.get_axes()[0].format_coord(event.x, event.y) == 'outside data area': return if self.allow_menu(): self.allow_popup_menu = True if self.shift_is_held: self.allow_popup_menu = False point = [int(event.xdata + .5), int(event.ydata + .5)] #print '>>>', point, '\t currently {0} selected'.format(len(self._SELECTEDCELLS)) if event.button == 3 : #if RMB is clicked # working with dialog for transect! if self.mainWidget.transect_dlg: if self.mainWidget.transect_dlg.toogle_show_after_selected_cell: realx, realy = self.get_real_xy(event.xdata, event.ydata, self.mainWidget.detect_variable_dimensions()) realpoint = [realy, realx] #print 'real xy:', realpoint if self.mainWidget.transect_dlg.toogle_show_after_selected_cell == 1: # select point 1 self.allow_popup_menu = False self.mainWidget.transect_dlg.data.set_p1(realpoint) elif self.mainWidget.transect_dlg.toogle_show_after_selected_cell == 2: # select point 2 self.allow_popup_menu = False self.mainWidget.transect_dlg.data.set_p2(realpoint) self.mainWidget.transect_dlg.update() self.mainWidget.transect_dlg.show() # working with dialog for flux! if self.mainWidget.flux_dlg: if self.mainWidget.flux_dlg.toogle_show_after_selected_cell: if self.mainWidget.flux_dlg.toogle_show_after_selected_cell == 1: # select point 1 self.allow_popup_menu = False self.mainWidget.flux_dlg.data.set_p1(point) elif self.mainWidget.flux_dlg.toogle_show_after_selected_cell == 2: # select point 2 self.allow_popup_menu = False self.mainWidget.flux_dlg.data.set_p2(point) self.mainWidget.flux_dlg.update() self.mainWidget.flux_dlg.show() if len(self._SELECTEDCELLS) == 0: # if no cell is selected self.add_selected_cell(point) else: # if some cells are already selected if self.mpl_menu.allow_rmb_select_cells() or self.shift_is_held: # check if this point is already selected: already_selected = False for p in self._SELECTEDCELLS_IJ: if (point[0] == p[0]) and (point[1] == p[1]): already_selected = True print 'cell already selected... is not added' if not already_selected: self.add_selected_cell(point) else: pass #self.clear_selection() #self.add_selected_cell(point) def cells_selected(self): if self._SELECTEDCELLS: return len(self._SELECTEDCELLS) else: return False def add_selected_cell(self, point): ''' point = [i, j]''' print 'selected cell:', point[0], point[1] c = self.draw_picked_cell(point) self._SELECTEDCELLS.append(c) self._SELECTEDCELLS_IJ.append(point) def get_selected_cells_ij(self): return self._SELECTEDCELLS_IJ def clear_selection(self): ''' delete all graphical objects of selected cells redraw canvas ''' print 'clearing stuff' if len(self._SELECTEDCELLLINES) > 0: for line in self._SELECTEDCELLLINES: l = line.pop(0) l.remove() del l del self._SELECTEDCELLLINES[:] #print 'cells ---- before:', len(self._SELECTEDCELLS) if len(self._SELECTEDCELLS) > 0: for cell in self._SELECTEDCELLS: for line in cell: l = line.pop(0) l.remove() del l del self._SELECTEDCELLS[:] #print 'cells ---- left:', len(self._SELECTEDCELLS) #print 'cells-coords ----' #print len(self._SELECTEDCELLS_IJ) if self._SELECTEDCELLS_IJ: for cellcoords in self._SELECTEDCELLS_IJ: #cc = cellcoords.pop(0) #cellcoords.remove() del cellcoords del self._SELECTEDCELLS_IJ[:] #print 'cells ---- left,', len(self._SELECTEDCELLS_IJ) if len(self._SELECTEDCELLS) != 0: raise ValueError('List "self._SELECTEDCELLS" was not flushed') if len(self._SELECTEDCELLLINES) != 0: raise ValueError('List "self._SELECTEDCELLLINES" was not flushed') if len(self._SELECTEDCELLS_IJ) != 0: raise ValueError('List "self._SELECTEDCELLLINES" was not flushed') # update plot self.canvas.draw() #print 'finishing clear: cells left', len(self._SELECTEDCELLS) def showGrid(self, state): if self.fig.axes: current_plot = self.mainWidget.get_plotType() current_plot2D = self.mainWidget.get_plotType_for_timeseries() if state == Qt.Checked: if current_plot == '1D' or (current_plot2D =="2DZT"): self.fig.axes[0].grid(True) elif current_plot == '2D' and (not current_plot2D =="2DZT"): self.draw_pixel_grid(True) else: if current_plot == '1D' or (current_plot2D =="2DZT"): self.fig.axes[0].grid(False) elif current_plot == '2D' and (not current_plot2D =="2DZT"): self.draw_pixel_grid(False) self.canvas.draw() def draw_picked_cell(self, point): x = point[0] y = point[1] ''' approach drawing a patch... not working cell_bnd = patches.Rectangle((x-.5, y-.5), 1, 1, fill=False, edgecolor="black", hatch=None, linewidth=1.) cell_instance = self.fig.axes[0].add_patch(cell_bnd) ''' b_line = [(x-.5, x+.5), (y-.5, y-.5)] r_line = [(x+.5, x+.5), (y-.5, y+.5)] t_line = [(x-.5, x+.5), (y+.5, y+.5)] l_line = [(x-.5, x-.5), (y-.5, y+.5)] cell = [b_line, r_line, t_line, l_line] for i, l in enumerate(cell): ll = self.fig.axes[0].plot(l[0], l[1], 'k-', lw=.8) cell[i] = ll # overwriting current Line2D object with object binded to an axes #self._SELECTEDCELLS.append(cell) # collecting reference to this cell to be able to delete it #self._SELECTEDCELLS_IJ.append(point) # collecting reference to this cell to be able to delete it self.canvas.draw() return cell def draw_line(self, point1, point2): line = [(point1[0], point2[0]), (point1[1], point2[1])] l = self.fig.axes[0].plot(line[0], line[1], 'k-', lw=2) return l def draw_pixel_grid(self, enable=True): if enable: dx = 1 dy = 1 x0 = -.5 y0 = -.5 if self.mainWidget.get_plotType_for_timeseries() == '2DXY': nx = self.mainWidget.get_nX() ny = self.mainWidget.get_nY() elif self.mainWidget.get_plotType_for_timeseries() == '2DZY': nx = self.mainWidget.get_nY() ny = self.mainWidget.get_nZ() elif self.mainWidget.get_plotType_for_timeseries() == '2DZX': nx = self.mainWidget.get_nX() ny = self.mainWidget.get_nZ() self._GRIDLINES = list() for n_hline in np.arange(ny+1): hline = [(x0, x0+nx), (y0+n_hline, y0+n_hline)] l = self.fig.axes[0].plot(hline[0], hline[1], 'k-', lw=.2) self._GRIDLINES.append(l) # collecting reference to this line to be able to delete it for n_vline in np.arange(nx+1): vline = [(x0+n_vline, x0+n_vline), (y0, y0+ny)] l = self.fig.axes[0].plot(vline[0], vline[1], 'k-', lw=.2) self._GRIDLINES.append(l) # collecting reference to this line to be able to delete it if not enable: #print 'deleting lines...' if self._GRIDLINES: # if lines were created #print 'lines are here...' for line in self._GRIDLINES: #print line l = line.pop(0) l.remove() del l self.fig.canvas.draw() def on_key_press(self, event): #print 'key pressed:', event.key if event.key == 'shift': self.shift_is_held = True def on_key_release(self, event): #print 'key released:', event.key if event.key == 'shift': self.shift_is_held = False elif event.key == 'escape': self.clear_selection() def change_coordinate_formatter(self, ax, data2d, bruteforce_flag=None, bruteforce_dims=None): ''' see http://stackoverflow.com/questions/14754931/matplotlib-values-under-cursor ''' numrows, numcols = data2d.shape bruteforce_mode_on = False bruteforce_mode_on = (bruteforce_flag == '2DXY' and bruteforce_dims[-1] and bruteforce_dims[-2]) def format_coord(x, y): col = int(x+0.5) row = int(y+0.5) if not bruteforce_mode_on: if col >= 0 and col < numcols and row >= 0 and row < numrows: #z = data2d[row, col] # sice we have artificially reversed y-coordinate axes, now reverse data! # numrows-1, because if nrows=10 => row=[0:9] z = data2d[numrows-1-row, col] #return 'x=%1.1f y=%1.1f z=%1.6f' % (x, y, z) return 'i=%d j=%d z=%.6f' % (col, row, z) else: #return 'x=%1.4f, y=%1.4f' % (x, y) return 'outside data area' elif bruteforce_flag == '2DXY' and bruteforce_dims[-1] and bruteforce_dims[-2]: ''' our extend in X=[-0.5:numcols-0.5], Y=[-0.5:numrows-0.5], because col,row is cell center! ''' if col >= 0 and col < numcols and row >= 0 and row < numrows: #z = data2d[row, col] # sice we have artificially reversed y-coordinate axes, now reverse data! # numrows-1, because if nrows=10 => row=[0:9] z = data2d[numrows-1-row, col] real_x, real_y = self.get_real_xy(x, y, bruteforce_dims) #return 'x=%1.1f y=%1.1f z=%1.6f' % (x, y, z) #return 'i=%d j=%d z=%.3f x=%.4f y=%.4f' % (col, row, z, real_x, real_y) return 'i=%d j=%d z=%.3f, %s=%.2f %s=%.2f' % ( col, row, z, bruteforce_dims[-1], real_x, bruteforce_dims[-2], real_y) else: #return 'x=%1.4f, y=%1.4f' % (x, y) return 'outside data area' else: raise ValueError('bruteforce_flag can be $None$ or $"2DXY"$. Passed %s' % bruteforce_flag) ax.format_coord = format_coord def allow_menu(self): allow = False #print "self.mainWidget.get_plotType():", self.mainWidget.get_plotType() #print "self.mainWidget.get_plotType_for_timeseries():", self.mainWidget.get_plotType_for_timeseries() if self.mainWidget.get_plotType() == "2D" and not self.mainWidget.get_plotType_for_timeseries() == "2DZT": allow = True return allow def get_real_xy(self, i, j, dimension_list): ''' functions returns values of x,y based on passed indexes i, j ''' if any(dimension_list[-2:-1]) is None: print 'Dimensions X,Y of current variable are not specified (variables that have same name as dimensions not found)' raise ValueError('Dimensions X,Y of current variable are not specified (variables that have same name as dimensions not found)') nc = self.mainWidget.get_selected_ncfile_instance() try: x_var = nc.variables[dimension_list[-1]] y_var = nc.variables[dimension_list[-2]] except: print ('Failed to load variables: {0}, {1}'.format(dimension_list[-1], dimension_list[-2])) raise ValueError('Failed to load variables: {0}, {1}'.format(dimension_list[-1], dimension_list[-2])) x_ratio = (x_var[-1]-x_var[0])/(len(x_var)-1) y_ratio = (y_var[-1]-y_var[0])/(len(y_var)-1) #x[i] = x_var[0]+x_ratio*i #y[j] = y_var[0]+y_ratio*j x = x_var[0] + x_ratio*i y = y_var[0] + y_ratio*j nc.close() return (x, y) def get_axes(self): return self.fig.get_axes() def fast_redraw(self, artist): background = [self.canvas.copy_from_bbox(self.get_axes()[0].bbox)] self.get_axes()[0].draw_artist(artist) self.canvas.restore_region(background) self.canvas.blit(self.get_axes()[0].bbox) self.canvas.update() self.canvas.flush_events()