class PicoPlotter(QtGui.QDialog): def set_class_vars(self): self.script = ones self.n_show = 30 self.live_data = np.full(self.n_show, None) def __init__(self, parent): super(PicoPlotter, self).__init__() self.parent = parent self.set_class_vars() self.populate() def populate(self): self.setWindowTitle('Live plotter') self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) '''Changed nav toolbar''' self.nav.addAction('Reset optimizer', self.reset_opt) self.layout = QtGui.QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.nav) self.layout.addWidget(self.canvas) self.setLayout(self.layout) self.canvas.ax.set_ylim((0, 5e-5)) self.canvas.ax.set_xlim((0, .04)) width = self.canvas.width() height = self.nav.height() + self.canvas.height() + 20 self.setFixedSize(width, height) def reset_opt(self): self.live_data = np.full(self.n_show, None) def live_plot(self): try: this_shot = self.script(self.parent.data) empty_data = np.where(self.live_data == None) if len(empty_data[0]) == 0: self.live_data[0:self.n_show - 1] = self.live_data[1:self.n_show] self.live_data[-1] = this_shot else: self.live_data[empty_data[0][0]] = this_shot except AttributeError: print('Not loaded') '''def ones(self): return 1 ''' def show_window(self): self.live_plot() self.canvas.ax.clear() self.canvas.ax.plot(self.live_data) # self.canvas.ax.title(np.std(self.live_data)) self.canvas.draw()
class Plot(object): def __init__(self, figure, identifier, filepath): loader = UiLoader() self.ui = loader.load('plot_window.ui', PlotWindow()) # Tell Windows how to handle our windows in the the taskbar, making pinning work properly and stuff: if os.name == 'nt': self.ui.newWindow.connect(set_win_appusermodel) self.set_window_title(identifier, filepath) # figure.tight_layout() self.figure = figure self.canvas = FigureCanvas(figure) self.navigation_toolbar = NavigationToolbar(self.canvas, self.ui) self.lock_action = self.navigation_toolbar.addAction( QtGui.QIcon(':qtutils/fugue/lock-unlock'), 'Lock axes', self.on_lock_axes_triggered) self.lock_action.setCheckable(True) self.lock_action.setToolTip('Lock axes') self.copy_to_clipboard_action = self.navigation_toolbar.addAction( QtGui.QIcon(':qtutils/fugue/clipboard--arrow'), 'Copy to clipboard', self.on_copy_to_clipboard_triggered) self.copy_to_clipboard_action.setToolTip('Copy to clipboard') self.copy_to_clipboard_action.setShortcut(QtGui.QKeySequence.Copy) self.ui.verticalLayout_canvas.addWidget(self.canvas) self.ui.verticalLayout_navigation_toolbar.addWidget(self.navigation_toolbar) self.lock_axes = False self.axis_limits = None self.update_window_size() self.ui.show() def on_lock_axes_triggered(self): if self.lock_action.isChecked(): self.lock_axes = True self.lock_action.setIcon(QtGui.QIcon(':qtutils/fugue/lock')) else: self.lock_axes = False self.lock_action.setIcon(QtGui.QIcon(':qtutils/fugue/lock-unlock')) def on_copy_to_clipboard_triggered(self): lyse.figure_to_clipboard(self.figure) @inmain_decorator() def save_axis_limits(self): axis_limits = {} for i, ax in enumerate(self.figure.axes): # Save the limits of the axes to restore them afterward: axis_limits[i] = ax.get_xlim(), ax.get_ylim() self.axis_limits = axis_limits @inmain_decorator() def clear(self): self.figure.clear() @inmain_decorator() def restore_axis_limits(self): for i, ax in enumerate(self.figure.axes): try: xlim, ylim = self.axis_limits[i] ax.set_xlim(xlim) ax.set_ylim(ylim) except KeyError: continue @inmain_decorator() def set_window_title(self, identifier, filepath): self.ui.setWindowTitle(str(identifier) + ' - ' + os.path.basename(filepath)) @inmain_decorator() def update_window_size(self): l, w = self.figure.get_size_inches() dpi = self.figure.get_dpi() self.canvas.resize(int(l*dpi),int(w*dpi)) self.ui.adjustSize() @inmain_decorator() def draw(self): self.canvas.draw() def show(self): self.ui.show() @property def is_shown(self): return self.ui.isVisible()
class AppForm(QWidget): # class AppForm(QDialog): def __init__(self, inFile, cfg, index, xAxis=None, D1_flag=False, parent=None): QWidget.__init__(self, parent) try: # 20170814 通过pic.cfg的第二行,控制点标注的浮点数显示位数 f = open('pic.cfg') x = f.readlines()[-1] x = eval(x) if x > 10: x = 10 elif x < 2: x = 2 self.annoteLen = '%%.%de' % (x) except: self.annoteLen = '%.4e' if D1_flag == False: # 画二维图 self.pic2D(inFile, cfg, xAxis, index) elif D1_flag == True: # 画一维图 self.pic1D(inFile, cfg, index) # self.data = self.get_data2() self.create_main_frame() # print "Heap at the end of the functionn", hp.heap() # self.on_draw() # QObject.connect(self, SIGNAL("_signalexit"), self.testslot) def create_main_frame(self): # self.main_frame = QWidget() self.canvas = self.fig.canvas self.mpl_toolbar = NavigationToolbar(self.canvas, self, coordinates=False) self.mpl_toolbar.addSeparator() # self.mpl_toolbar.addAction(self.mpl_toolbar._icon("style.png"),'Customize',self.get_data2) self.anoteAction = self.mpl_toolbar.addAction( QIcon("img\\location.png"), 'Point Note', self.anoteset) # self.exitAction=self.mpl_toolbar.addAction(QIcon("style.png"),'Point Note',self.exitslot) self.anoteAction.setCheckable(True) # self.mpl_toolbar.addSeparator() # action=self.mpl_toolbar.addAction(self.mpl_toolbar._icon("qt.png"), # 'Customize', self.get_data2) # action.setCheckable(True) # self.canvas.mpl_connect('key_press_event', self.on_key_press) # vbox = QVBoxLayout() # vbox.addWidget(self.mpl_toolbar) # vbox.addWidget(self.canvas) # the matplotlib canvas # self.setLayout(vbox) # self.main_frame.setLayout(vbox) # self.setCentralWidget(self.main_frame) # print self.mpl_toolbar self.chklist = [] self.listwid = QListWidget(self) for x in range(len(self.lnamelist)): item = QListWidgetItem() checkbox = QCheckBox() checkbox.setCheckState(2) # checkbox.checkState() font = QFont() font.setPointSize(12) checkbox.setFont(font) checkbox.setText(' %s' % (self.lnamelist[x])) checkbox.stateChanged.connect(self.chklistSlot) self.chklist.append(checkbox) self.listwid.addItem(item) self.listwid.setItemWidget(item, checkbox) gridLayout = QGridLayout() # gridLayout.addWidget(self.mpl_toolbar,0,0,1,4) # gridLayout.addWidget(self.canvas,1,0,3,3) # gridLayout.addWidget(self.listwid,1,3,3,1) gridLayout.addWidget(self.mpl_toolbar, 0, 0) gridLayout.addWidget(self.canvas, 1, 0) gridLayout.addWidget(self.listwid, 1, 1) gridLayout.setColumnStretch(0, 2) gridLayout.setColumnStretch(0, 1) self.setLayout(gridLayout) # self.dispDock=QDockWidget(self.tr("显示选择"),self) # wig=QWidget(self.dispDock) # # wig.setSizeIncrement(180,350) # self.listWid = QListWidget(wig) # self.gridLayout=QGridLayout(wig) # self.gridLayout.addWidget(self.listWid, 0, 0, 1, 2) # wig.setLayout(self.gridLayout) # self.dispDock.setWidget(wig) # self.dispDock.setFeatures(QDockWidget.AllDockWidgetFeatures) # self.addDockWidget(Qt.RightDockWidgetArea,self.dispDock) def get_data2(self): # print 'asda' return np.arange(20).reshape([4, 5]).copy() def on_draw(self): self.canvas.draw() # plt.show() def on_key_press(self, event): print('you pressed', event.key) # implement the default mpl key press events described at # http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts # key_press_handler(event, self.canvas, self.mpl_toolbar) def pic1D(self, inFilelist, cfglist, colslist): self.fig, self.ax = plt.subplots(1, 1) self.datalist = [] self.linelist = [] self.lnamelist = [] self.fmtlist = [] zh_font = font_manager.FontProperties( fname=r'c:\windows\fonts\simsun.ttc', size=10) if len(inFilelist) == 0: return # print inFilelist for ind in range(len(inFilelist)): inFile = inFilelist[ind] fmt = readType(cfglist[ind], inFilelist[ind]) # print fmt # xAxis=xAxislist[ind] index = colslist[ind] cols = [] # cols.append(xAxis) cols.extend(index) datalist = np.loadtxt(inFile, unpack=True, usecols=cols) # datalist=np.loadtxt(inFile,unpack=True, usecols=cols,dtype=[fmt[col][1] for col in cols]) str1 = '%d\n' if len(cols) > 1: x = np.array([i for i in range(1, len(datalist[0]) + 1)]) else: x = np.array([i for i in range(1, len(datalist) + 1)]) # print type(dlist[0]) # dlist.insert(0,x) dlist = [] for i in range(len(cols)): # print fmt[index[i]] if len(cols) > 1: dlist.append(datalist[i]) else: dlist.append(datalist) pic_scale = fmt[index[i]][3] if pic_scale != 1.0: line, = self.ax.plot( x, dlist[i] * pic_scale, picker=5, label=fmt[index[i]][0], linewidth=1) # ,LineStyle=':',MarkerSymbol='o') self.datalist.extend([x, dlist[i] * pic_scale]) else: line, = self.ax.plot(x, dlist[i], picker=5, label=fmt[index[i]][0], linewidth=1) self.datalist.extend([x, dlist[i]]) # line.set_antialiased(False) self.linelist.append(line) self.lnamelist.append(fmt[index[i]][0]) # self.datalist.extend([x,dlist[i]]) if fmt[index[i]][1] not in (np.dtype('float32'), np.dtype('float64')): if fmt[index[i]][2] == 1: str2 = str1 + '0x%x' else: str2 = str1 + '%d' else: str2 = str1 + self.annoteLen self.fmtlist.append(str2) # handles, labels = self.ax.get_legend_handles_labels() # print self.fmtlist self.browser = PointBrowser(self.fig, self.ax, self.datalist, self.linelist, self.fmtlist) plt.grid(True) plt.legend(loc=2, prop=zh_font) def pic2D(self, inFilelist, cfglist, xAxislist, colslist): self.fig, self.ax = plt.subplots(1, 1) # print type(self.fig),type(self.ax) self.datalist = [] self.linelist = [] self.lnamelist = [] self.fmtlist = [] zh_font = font_manager.FontProperties( fname=r'c:\windows\fonts\simsun.ttc', size=10) if len(inFilelist) == 0: return # print inFilelist for ind in range(len(inFilelist)): inFile = inFilelist[ind] fmt = readType(cfglist[ind], inFilelist[ind]) # print fmt xAxis = xAxislist[ind] index = colslist[ind] cols = [] cols.append(xAxis) cols.extend(index) dlist = np.loadtxt(inFile, unpack=True, usecols=cols) # dlist2=np.loadtxt(inFile,unpack=True)#, usecols=(0,index[0],index[1])) # self.ax.set_title('click on point to plot time series') # line,line2 = ax.plot(xs, ys, xs, zs, picker=5) # picker参数必须设置,鼠标的pick_event事件才能激活,数值大小为选取的范围大小 x = dlist[0] if fmt[xAxis][1] not in (np.dtype('float32'), np.dtype('float64')): str1 = '%d\n' else: # str1='%.4e\n' str1 = self.annoteLen + '\n' for i in range(len(cols) - 1): pic_scale = fmt[index[i]][3] # 20170507 i修改为index[i],修复bug # print pic_scale if pic_scale != 1.0: line, = self.ax.plot( x, dlist[i + 1] * pic_scale, picker=5, label=fmt[index[i]][0], linewidth=1) # ,LineStyle=':',MarkerSymbol='o') self.datalist.extend([ x, dlist[i + 1] * pic_scale ]) # 20170507 此处必须将刻度值乘到数据中,否则点标注将显示原有点的值 else: line, = self.ax.plot(x, dlist[i + 1], picker=5, label=fmt[index[i]][0], linewidth=1) self.datalist.extend([x, dlist[i + 1]]) # line.set_antialiased(False) self.linelist.append(line) self.lnamelist.append(fmt[index[i]][0]) # self.datalist.extend([x,dlist[i+1]]) # 20170507 注释 if fmt[index[i]][1] not in (np.dtype('float32'), np.dtype('float64')): if fmt[index[i]][2] == 1: str2 = str1 + '0x%x' else: str2 = str1 + '%d' else: # str2=str1+'%.4e' str2 = str1 + self.annoteLen self.fmtlist.append(str2) # handles, labels = self.ax.get_legend_handles_labels() # print self.fmtlist self.browser = PointBrowser(self.fig, self.ax, self.datalist, self.linelist, self.fmtlist) plt.grid(True) plt.legend(loc=2, prop=zh_font) def anoteset(self): if self.anoteAction.isChecked(): self.pickCid = self.fig.canvas.mpl_connect('pick_event', self.browser.onpick) self.keyCid = self.fig.canvas.mpl_connect('key_press_event', self.browser.onpress) self.browser.setDraggable(True) # QAction().isChecked() else: self.browser.setDraggable(False) self.fig.canvas.mpl_disconnect(self.pickCid) self.fig.canvas.mpl_disconnect(self.keyCid) def chklistSlot(self): self.browser.hideline = [] for index in range(len(self.chklist)): # x=QCheckBox() if self.chklist[index].checkState() == 0: # print self.linelist[index].get_visible() # self.anotBackup[index]=[] self.linelist[index].set_visible(False) self.browser.hideline.append( index) # 隐藏的线段添加到browser对象中的hideline,不再对其进行标注 for point in self.browser.datapick[index]: # text=self.browser.datapick[index][point][0]._text # self.anotBackup[index].append(text) self.browser.datapick[index][point][0].set_visible(False) self.browser.datapick[index][point][1].set_visible(False) else: self.linelist[index].set_visible(True) if index in self.browser.hideline: # 被隐藏的线段恢复可标注 self.browser.hideline.remove(index) for point in self.browser.datapick[index]: # text=self.browser.datapick[index][point][0]._text # self.anotBackup[index].append(text) self.browser.datapick[index][point][0].set_visible(True) self.browser.datapick[index][point][1].set_visible(True) # print self.browser.hideline self.on_draw() # def __del__(self): # # self.fig,self.ax,self.datalist,self.linelist,self.fmtlist # self.browser.dataset=None # self.browser.lineset=None # self.browser.fmt=None # self.datalist=None # self.linelist=None # self.fmtlist=None # gc.collect() def exitslot(self): # self.browser.dataset=None # self.browser.lineset=None # self.browser.fmt=None # self.datalist=None # self.linelist=None # self.fmtlist=None del self.browser.dataset del self.browser.lineset del self.browser.fmt del self.datalist del self.linelist del self.fmtlist self.fig.clf(True) del self.fig del self.ax del self.canvas gc.collect() # self.emit(SIGNAL('_signalexit')) # self.close() def testslot(self): print('slot trigger!')
class Plot(object): def __init__(self, figure, identifier, filepath): loader = UiLoader() self.ui = loader.load('plot_window.ui', PlotWindow()) # Tell Windows how to handle our windows in the the taskbar, making pinning work properly and stuff: if os.name == 'nt': self.ui.newWindow.connect(set_win_appusermodel) self.set_window_title(identifier, filepath) # figure.tight_layout() self.figure = figure self.canvas = FigureCanvas(figure) self.navigation_toolbar = NavigationToolbar(self.canvas, self.ui) self.lock_action = self.navigation_toolbar.addAction( QtGui.QIcon(':qtutils/fugue/lock-unlock'), 'Lock axes', self.on_lock_axes_triggered) self.lock_action.setCheckable(True) self.lock_action.setToolTip('Lock axes') self.ui.verticalLayout_canvas.addWidget(self.canvas) self.ui.verticalLayout_navigation_toolbar.addWidget(self.navigation_toolbar) self.lock_axes = False self.axis_limits = None self.update_window_size() self.ui.show() def on_lock_axes_triggered(self): if self.lock_action.isChecked(): self.lock_axes = True self.lock_action.setIcon(QtGui.QIcon(':qtutils/fugue/lock')) else: self.lock_axes = False self.lock_action.setIcon(QtGui.QIcon(':qtutils/fugue/lock-unlock')) @inmain_decorator() def save_axis_limits(self): axis_limits = {} for i, ax in enumerate(self.figure.axes): # Save the limits of the axes to restore them afterward: axis_limits[i] = ax.get_xlim(), ax.get_ylim() self.axis_limits = axis_limits @inmain_decorator() def clear(self): self.figure.clear() @inmain_decorator() def restore_axis_limits(self): for i, ax in enumerate(self.figure.axes): try: xlim, ylim = self.axis_limits[i] ax.set_xlim(xlim) ax.set_ylim(ylim) except KeyError: continue @inmain_decorator() def set_window_title(self, identifier, filepath): self.ui.setWindowTitle(str(identifier) + ' - ' + os.path.basename(filepath)) @inmain_decorator() def update_window_size(self): l, w = self.figure.get_size_inches() dpi = self.figure.get_dpi() self.canvas.resize(int(l*dpi),int(w*dpi)) self.ui.adjustSize() @inmain_decorator() def draw(self): self.canvas.draw() def show(self): self.ui.show() @property def is_shown(self): return self.ui.isVisible()
class BaseGui(QtGui.QMainWindow): def __init__(self): # define the inheritance, nothing to QMainWindow super(BaseGui, self).__init__() # call the GUI init function and show self.initGUI() self.show() # initialize the GUI layout def initGUI(self, width = 600, height = 400): # resize, center, set window title and icon self.resize(width, height) self.center() self.setWindowTitle('Base QT GUI') self.setWindowIcon(QtGui.QIcon('pngs/wolf.png')) # set up status bar at bottom of application self.statusBar().showMessage('Ready') # initialize statusbar # set up central widget self.cw = QtGui.QWidget() self.setCentralWidget(self.cw) # set up grid on central widget, a 10x10 grid is implied for now self.grid = QtGui.QGridLayout(self.cw) self.grid.setSpacing(6) # create a figure, canvas, and toolbar self.figure = plt.figure() self.canvas = FigureCanvas(self.figure) self.toolbar = NavigationToolbar(self.canvas, self) # add the figure and toolbar to the central widget grid self.grid.addWidget(self.toolbar, 0, 0, 1, 9) self.grid.addWidget(self.canvas, 1, 0, 3, 9) # create a slider and LCD display, add to central widget, wire together self.slider = QtGui.QSlider(QtCore.Qt.Horizontal) self.lcd = QtGui.QLCDNumber() self.sLabel = QtGui.QLabel('Select\nFrequency') self.grid.addWidget(self.slider, 8, 1, 2, 8) self.grid.addWidget(self.lcd, 3, 9) self.grid.addWidget(self.sLabel, 8, 0) self.slider.valueChanged.connect(self.lcd.display) self.slider.valueChanged.connect(self.updatePlot) self.slider.setMaximum(30) # create quit pushbutton with tooltip self.quitButton = QtGui.QPushButton('Quit') self.quitButton.resize(self.quitButton.sizeHint()) self.quitButton.setToolTip('Close This Application') self.quitButton.clicked.connect(QtGui.qApp.quit) self.grid.addWidget(self.quitButton, 9, 9) # add label and combo-box for type of plot for top subplot self.pLabelTop = QtGui.QLabel('Select Top Subplot Type') self.grid.addWidget(self.pLabelTop, 4, 0) self.pSelectTop = QtGui.QComboBox() self.pSelectTop.addItems(['', 'sin', 'cos', 'sin squared', 'cos squared']) self.grid.addWidget(self.pSelectTop, 4, 2, 1, 8) self.pSelectTop.activated[str].connect(self.updatePlot) # add label and combo-box for type of plot for bottom subplot self.pLabelBottom = QtGui.QLabel('Select Bottom Subplot Type') self.grid.addWidget(self.pLabelBottom, 5, 0) self.pSelectBottom = QtGui.QComboBox() self.pSelectBottom.addItems(['', 'sin', 'cos', 'sin squared', 'cos squared']) self.grid.addWidget(self.pSelectBottom, 5, 2, 1, 8) self.pSelectBottom.activated[str].connect(self.updatePlot) # add text edit box for number of data points in plot self.NpointsEdit = QtGui.QLineEdit('50') self.NpointsLabel = QtGui.QLabel('Set Number of Data Points in Plot') self.grid.addWidget(self.NpointsLabel, 0, 9) self.grid.addWidget(self.NpointsEdit, 1, 9) self.NpointsEdit.textChanged[str].connect(self.updatePlot) # create toolbar, add quit action to it self.toolbar = self.addToolBar('MainToolbar') exitAction = QtGui.QAction(QtGui.QIcon('pngs/quit.png'), 'Close Application', self) exitAction.triggered.connect(QtGui.qApp.quit) self.toolbar.addAction(exitAction) def updatePlot(self, text): # create axes in right place based on sender if self.sender() == self.pSelectTop: axes = [self.figure.add_subplot(2,1,1)] elif self.sender() == self.pSelectBottom: axes = [self.figure.add_subplot(2,1,2)] elif (self.sender() == self.slider) or (self.sender() == self.NpointsEdit): text = int() axes = [] axes.append(self.figure.add_subplot(2,1,1)) axes.append(self.figure.add_subplot(2,1,2)) else: return # get frequency from slider value freq = self.slider.value() # define x-data for plot Npoints = int(self.NpointsEdit.text()) x = np.linspace(0, 2*np.pi, Npoints) # make right type of plot on each axes plotType = text for (i, ax) in enumerate(axes): # clear axes ax.hold(False) # for case of slider selection, get the value in the combobox if type(text) is int: if i == 0: plotType = self.pSelectTop.currentText() elif i == 1: plotType = self.pSelectBottom.currentText() # update plots linesty = '.' if plotType == 'sin': ax.plot(x, np.sin(freq*x), linesty) elif plotType == 'cos': ax.plot(x, np.cos(freq*x), linesty) elif plotType == 'sin squared': ax.plot(x, np.sin(freq*x)**2, linesty) elif plotType == 'cos squared': ax.plot(x, np.cos(freq*x)**2, linesty) else: return ax.set_xlim((0, 2*np.pi)) ax.set_ylim((-1.01, 1.01)) ax.grid(True) # clean up and show self.figure.subplots_adjust(hspace = 0.4) self.canvas.draw() # center widget method def center(self): qr = self.frameGeometry() cp = QtGui.QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def closeEvent(self, event): reply = QtGui.QMessageBox.question(self, 'Message', 'Sure you want to quit', \ QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, \ QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: event.accept() else: event.ignore()
class MatplotlibWidget(QtGui.QWidget): """ MatplotlibWidget is a plotting widget based on matplotlib. While the FigureCanvasQTAgg widget provided by matplotlib itself is intended for easy matplotlib integration in Qt applications, this widget focuses on hiding matplotlib internals from the user and adding new features. As the widget is designed to be used within applications, MatplotlibWidget provides methods for updating the data of graphs without clearing the figure and setting it up from scratch. This optimizes performance when the data is changed frequently. After creating a MatplotlibWidget, you add a new plots to the figure by calling :func:`addGroupedPlot`. A new feature is the use of so called `plot groups`. When calling :func:`newPlotGroup`, all subsequent calls to :func:`addGroupedPlot` will add new plots to a different group, which will change the appearance of the plots. The plot will be updated when calling :func:`draw`. All plots within a group will have the same color but different line styles. Each group however will differ in color. You can choose a split presentation, where each group will be displayed in its own graph. You can use :func:`updateGroupedPlot` for changing the plot-data, or :func:`clearPlots` for clearing the whole figure and setting it up from scratch. :param parent: Parent parameter of QWidget, usually None. :param autoscaleBn: (bool) Add autoscale button to panel. Example: .. literalinclude:: ../src/qao/gui/MatplotlibWidget.py :pyobject: testMatplotlibWidget """ colors = 'bgrkcm' markers = 'os^vd' linestyles = ['-', '--', '-.', ':'] def __init__(self, parent=None, autoscaleBn = False): QtGui.QWidget.__init__(self, parent) # canvas font = self.font() windowColor = str(self.palette().window().color().name()) matplotlib.rc('font', family=str(font.family()), size=.9*font.pointSize(), weight="normal") matplotlib.rc('figure', facecolor=windowColor, edgecolor=windowColor) self.fig = Figure(dpi=self.logicalDpiX()) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) # navigation self.navigation = NavigationToolbar(self.canvas, self, coordinates=False) self.actionGroupPlotStyle = self.navigation.addAction("Split", self.toggleGroupPlotStyle) self.actionGroupPlotStyle.setCheckable(True) self.actionAutoscale = self.navigation.addAction("Auto", self.toggleAutoscale) self.actionAutoscale.setCheckable(True) self.actionAutoscale.setChecked(True) layout = QtGui.QVBoxLayout(self) layout.addWidget(self.canvas) layout.addWidget(self.navigation) # init other stuff self.xlabel = "" self._needSetupFigure = True self._needSetupLines = True self._needRescale = True self.clearPlots() self.setGropPlotStyle("combined") def clearPlots(self): """ Removes all plots from the figure and deletes all plot groups. """ self.plotPointGroups = [] self.plotLineGroups = [] self._needSetupFigure = True def resizeEvent(self, event): if self.isMinimized() or self.isHidden(): return w, h = event.size().width(), event.size().height() self.fig.subplots_adjust(left = 30./w, right = 1-5./w, top = 1-5./h, bottom = 50./h, hspace = 70./h) def newPlotGroup(self): """ Creates a new group for further plots added to the figure. Plots within a group have different line styles. Plots of different groups will receive different colors. In the split presentation, each plot group will be displayed in its own graph. :returns: (int) Group id assigned for updating plots later on. """ assert len(self.plotPointGroups) < len(self.colors), "maximum number of plot groups reached" self.plotPointGroups.append([]) self.plotLineGroups.append([]) self._needSetupFigure = True return len(self.plotLineGroups) - 1 def addGroupedPlot(self, label, x, y): """ Creates a new plot within the last created plot group. Generally, this function creates two plots for a given dataset. The first plot is a scatter plot, showing all x and y values. The second plot is a line plot, averaging over y values if there are multiple occurrences of x values. The plot data can be updated by calling :func:`updateGroupedPlot`. :param label: (str) Label to be displayed in the figure legend. :param x: (ndarray) Array or list of x values. :param y: (ndarray) Array or list of y values. :returns: (int) Plot id assigned for updating plots later on. """ if not self.plotPointGroups: self.newPlotGroup() assert len(self.plotPointGroups[-1]) < len(self.linestyles), "maximum number of plot group elements reached" pointGroup = self.plotPointGroups[-1] lineGroup = self.plotLineGroups[-1] if len(x) != 0: xu, yu = unique_mean(x, y) else: xu, yu = [], [] points = matplotlib.lines.Line2D(x, y, color = self.colors[len(self.plotPointGroups)-1], marker = "o", ls = "") line = matplotlib.lines.Line2D(xu, yu, label = label, color = self.colors[len(self.plotLineGroups)-1], ls = self.linestyles[len(lineGroup)]) pointGroup.append(points) lineGroup.append(line) self._needSetupLines = True return len(lineGroup) - 1 def updateGroupedPlot(self, group, plot, x, y): """ Update the data for a single plot. The plot you want to update is defined by the group and plot id. Both numbers are starting at zero and simply increment when new groups/plots are added by the user, so the second plot within the first group is (group=0, plot=1). :param group: (int) Group id of the plot. :param plot: (int) Plot id of the plot. :param x: (ndarray) New x values for plotting. :param y: (ndarray) New y values for plotting. """ line = self.plotLineGroups[group][plot] points = self.plotPointGroups[group][plot] if len(x) != 0: xu, yu = unique_mean(x, y) else: xu, yu = [], [] line.set_xdata(xu) line.set_ydata(yu) points.set_xdata(x) points.set_ydata(y) self._needRescale = True def setGropPlotStyle(self, style = "combined"): """ Change the presentation style regarding the plot groups. The default behavior is a combined presentation, where all plots are displayed in the same graph. The split view assignes one graph for each plot group. :param style: (str) Plot style, may be 'combined' or 'individual'. """ if style == "combined": self.actionGroupPlotStyle.setChecked(False) self.groupPlotStyle = "combined" elif style == "individual": self.actionGroupPlotStyle.setChecked(True) self.groupPlotStyle = "individual" else: raise Exception("invalid group plot style") # update figure layout self._needSetupFigure = True def toggleGroupPlotStyle(self): """ Convenience function for changing the plot style. If the currently active style is 'combined', the style will chance to 'individual' and vice versa. .. seealso:: :func:`setGropPlotStyle` """ if self.groupPlotStyle == "combined": self.setGropPlotStyle("individual") else: self.setGropPlotStyle("combined") self.draw() def toggleAutoscale(self): self.draw() def setXLabel(self, label): """ Change the label for the x-axis. :param label: (str) Text displayed under x-axis. """ self.xlabel = label def draw(self): """ Redraw the current figure. Changes to the plot data, labels etc. will be visible after calling this method. """ if self._needSetupFigure: self._setupFigure() if self._needSetupLines: self._setupLines() if self._needRescale: self._setupScale() self.canvas.draw() def _setupFigure(self): self._needSetupFigure = False # clear figure and setup axes for plot groups self.fig.clf() nGroups = len(self.plotLineGroups) if not nGroups: return if self.groupPlotStyle == "combined": self.axes = [self.fig.add_subplot(1,1,1)] * nGroups elif self.groupPlotStyle == "individual": self.axes = [self.fig.add_subplot(nGroups,1,1)] self.axes += [self.fig.add_subplot(nGroups,1,i, sharex=self.axes[0]) for i in range(2, nGroups+1)] self.axes[-1].set_xlabel(self.xlabel) # axes prepared, add lines to axes self._setupLines() def _setupLines(self): if not len(self.plotLineGroups): return self._needSetupLines = False self._needRescale = False # clear lines from axes for ax in self.axes: ax.lines = [] # every group of lines is plotted to one axes for ax, pointlines, lines in zip(self.axes, self.plotPointGroups, self.plotLineGroups): for line in lines: ax.add_line(line) line.set_transform(ax.transData) for points in pointlines: ax.add_line(points) points.set_transform(ax.transData) ax.autoscale_view() ax.legend(loc=0) def _setupScale(self): self._needRescale = False if not self.actionAutoscale.isChecked(): return if not len(self.plotLineGroups): return for ax in self.axes: ax.relim() ax.autoscale()
class PicoViewer(QtGui.QDialog): name = None data_dir = None data_fxn = None def __init__(self, reactor, cxn=None, ylim = 2e-9): super(PicoViewer, self).__init__(None) self.reactor = reactor self.cxn = cxn print 'Directory:' print self.data_dir self.update_id = np.random.randint(0, 2**31 - 1) self.loading = False self.connect() self.Plotter = PicoPlotter(self) @inlineCallbacks def connect(self): if self.cxn is None: self.cxn = connection() cname = 'pico - {} - client'.format(self.name) yield self.cxn.connect(name=cname) self.populate() yield self.connect_signals() def show_fft(self): self.mouse_listener = self.canvas.mpl_connect('button_press_event', self.process_click) def process_click(self, event): t_click = event.xdata self.canvas.mpl_disconnect(self.mouse_listener) self.FFTPlot = FFTPlotter(self.data, self.ts, t_click) self.FFTPlot.show() def launch_plotter(self): self.Plotter.show() def populate(self): self.setWindowTitle(self.name) self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) self.nav.addAction('Select analysis method') self.nav.addAction('Launch live plotter', self.launch_plotter) self.nav.addAction('Show fft on click', self.show_fft) self.layout = QtGui.QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.nav) self.layout.addWidget(self.canvas) self.setLayout(self.layout) self.canvas.ax.set_ylim(self.ylim) self.canvas.ax.set_xlim((-.005, .045)) width = self.canvas.width() height = self.nav.height() + self.canvas.height() + 20 self.setFixedSize(width, height) self.setWindowTitle('pico_viewer') @inlineCallbacks def connect_signals(self): pico_server = yield self.cxn.get_server('cavity_probe_pico') yield pico_server.signal__update(self.update_id) yield pico_server.addListener(listener=self.receive_update, source=None, ID=self.update_id) def receive_update(self, c, signal_json): signal = json.loads(signal_json) for message_type, message in signal.items(): print message_type, message device_message = message.get(self.name) if (message_type == 'record') and (device_message is not None): #Will only look at file specified by device message self.get_data(device_message) self.replot() self.Plotter.show_window() def get_data(self, abs_data_path): with h5py.File(abs_data_path) as h5f: self.data = np.array(h5f['gnd']) #self.test = np.array(h5f['test_new_trig']) #print(self.test) self.ts = np.array(h5f['time']) def replot(self): #Apply function as specified in child class print('called') x, y = (self.data_fxn)(self.data, self.ts)#, self.ts) #keep zoomed in view on repaint xlim = self.canvas.ax.get_xlim() ylim = self.canvas.ax.get_ylim() self.canvas.ax.clear() self.canvas.ax.plot(x, y, label='Time domain') self.canvas.ax.set_xlim(xlim) self.canvas.ax.set_ylim(ylim) self.canvas.ax.legend() self.canvas.draw() print('redrawn') def closeEvent(self, x): self.reactor.stop()
class plotting(QtGui.QWidget): #for every 1D graph made , __init__, initUI , and graphRes is called. def __init__(self): #creation of the variables #initialized for all plotting instances #print('Plotting : init') super(plotting, self).__init__() self.initUI() def initUI(self): #initialized along with __init__ #print('Plotting: initUI') self.figure=plt.figure() self.ax=self.figure.add_subplot(111) self.main_frame = QtGui.QTabWidget() self.canvas=FigureCanvas(self.figure) self.toolbar=NavigationToolbar(self.canvas,self.main_frame) #self.canvas self.canvas.setParent(self.main_frame) ########## #FigureCanvas.setPa vbox = QtGui.QVBoxLayout() vbox.addWidget(self.toolbar) vbox.addWidget(self.canvas) # the matplotlib canvas self.main_frame.setLayout(vbox) def graphRes(self, data, calib=None): #print('Plotting: graphRes') #ax = figure.add_subplot(111) self.ax.hold(True) #plot with the same axis parameters if calib==None: #object warning, still works, ignore for now #FutureWarning: comparison to `None` will result in an elementwise object comparison in the future. x= np.arange(0.,len(data)) self.ax.plot(x,data) #regular plot if no calibration data exists else: self.ax.plot(calib, data[:len(calib)]) #if calibration exists, use calibrated x axis data (calib), and y axis as regular procssed counts (data) #self.dc1=datacursor(formatter="Energy:{x:.4f}\nCounts:{y:.4f}".format,bbox=None) #interactive cursor , SLOW find alternative or fix #self.ax.imshow(data, interpolation='nearest') ##ADDED self.ax.xaxis.set_minor_locator(AutoMinorLocator()) #auto set minor ticks plt.tick_params(which='both', width=1) plt.tick_params(which='major', length=7) plt.tick_params(which='minor', length=4, color='r') self.ax.grid(True) self.canvas.draw() #draw in pyQT gui canvas rather than seperate window def graph2DRes(self, data): #3d plot print('Plotting: graph2DRes..Please wait...') #print('data from graph2dres is: ', data) ############################################# #np.savetxt('2Dcoin.csv',data ,delimiter=",")#save 2D Data as CSV for later use ############################################# self.ax=self.figure.add_subplot(111) #, axisbg='slategray' self.ax.hold(False) #dont use same axis as before gridsizes=int(max(np.amax(data[:,0]),np.amax(data[:,1]))) + 100 #set grid size to max of each channel total energy print('2D plot gridsize is: ', gridsizes) #########Gridsize not working for HEXBIN graph option below, fix############ #make 2D total counts external message module here (factoring in min count=2) totalgraphicalcounts = sum(data[:,2]) print('the total (after 2count threshold) 2D coincidence counts are: ', totalgraphicalcounts) ###### print('the maximum count at a point on the 2D coincidence graph is: ', np.amax(data[:,2])) #debugging purposes tdcm=self.ax.hexbin(data[:,0],data[:,1],C=(data[:,2]), gridsize=gridsizes, #tdcm= two dimensional color map cmap= cm.nipy_spectral, bins=None) #cmap = cm.viridis -> linear color scale self.figure.colorbar(tdcm) #gradient color bar , related to above tdcm parameters self.ax.grid(True) #self.dc1=datacursor(formatter="Energy:{x:.4f}\nCounts:{y:.4f}".format,bbox=None) #data cursor seems to be broken for 2d Graph self.canvas.draw() #draw 2D color map canvas #============================================================================== #triple coincidence 3D plotting work in progress # def graph3DRes(self, data): # self.ax =self.figure.add_subplot(111, projection='3d') # self.ax.hold(False) # gridsize=int(max(np.amax(data[:,0]),np.amax(data[:,1]))) # # tdcm=self.ax.scatter(data[:,0],data[:,1],C=(data[:,2]), gridsize=gridsize, cmap= plt.cm.nipy_spectral_r, bins=None) # self.figure.colorbar(tdcm) # # self.canvas.draw() #============================================================================== def newButton(self, newAction): print('Plotting: newButton') self.toolbar.addAction(newAction)