def __init__(self): super(DataViewer, self).__init__() self.comboList = ComboList.ComboList() self.settings = SettingsWidget() self.calcPlot = CalculatorPlot(parent=self) self.setupGUI() # default plots will be drawn with multiple y and single x self.mainAxis = 'x' self.sliderParam = self.settings.config()['Main parameters']['slider'] self.timeParam = self.settings.config()['Main parameters']['time'] # no legend at first (there is no data) self.legend = None self.currentDataSetName = None # cursors are movable items to point the failure points self.cursors = [] self.dataSetButtons = {} # list of items in the dataset section of the menu bar ''' Note: indices = piece of all data indices, corresponding to the values interval, contrained by the slider THE VIEWER PLOTTS DATA using indices!!!! ''' self.data = None # dictionary with full current data set self.indices = None # array with indices for the current interval self.comments = {} self.allComments = {} self.allData = {} # here we keep data for different datasets self.allCursors = {} # cursors for different dataset self.allIndices = {} # contains all truncated indices self.allSampleLengths = {} self.allUnits = {} # self.settings.okButton.pressed.connect(self.settings.hide) self.exitButton.triggered.connect(sys.exit) self.settingsButton.triggered.connect(self.settings.show) self.loadButton.triggered.connect(self.requestLoad) self.addSceneButton.triggered.connect(self.addSceneToCombo) self.showComboDataButton.triggered.connect(self.comboList.show) self.calcPlotButton.triggered.connect(self.runCalcPlot) self.calcPlotButton.setDisabled(True) #### # connect cursors self.plt.sigRangeChanged.connect(self.scaleCursors) self.addPointButton.triggered.connect(self.addCursor) self.removePointButton.triggered.connect(self.removeCursor) self.drawCirclesButton.triggered.connect(self.plotMohrCircles) # Finally enable the save button self.saveButton.triggered.connect(self.save) self.setStatus('Ready')
class DataViewer(QtGui.QWidget): def __init__(self): super(DataViewer, self).__init__() self.comboList = ComboList.ComboList() self.settings = SettingsWidget() self.calcPlot = CalculatorPlot(parent=self) self.setupGUI() # default plots will be drawn with multiple y and single x self.mainAxis = 'x' self.sliderParam = self.settings.config()['Main parameters']['slider'] self.timeParam = self.settings.config()['Main parameters']['time'] # no legend at first (there is no data) self.legend = None self.currentDataSetName = None # cursors are movable items to point the failure points self.cursors = [] self.dataSetButtons = {} # list of items in the dataset section of the menu bar ''' Note: indices = piece of all data indices, corresponding to the values interval, contrained by the slider THE VIEWER PLOTTS DATA using indices!!!! ''' self.data = None # dictionary with full current data set self.indices = None # array with indices for the current interval self.comments = {} self.allComments = {} self.allData = {} # here we keep data for different datasets self.allCursors = {} # cursors for different dataset self.allIndices = {} # contains all truncated indices self.allSampleLengths = {} self.allUnits = {} # self.settings.okButton.pressed.connect(self.settings.hide) self.exitButton.triggered.connect(sys.exit) self.settingsButton.triggered.connect(self.settings.show) self.loadButton.triggered.connect(self.requestLoad) self.addSceneButton.triggered.connect(self.addSceneToCombo) self.showComboDataButton.triggered.connect(self.comboList.show) self.calcPlotButton.triggered.connect(self.runCalcPlot) self.calcPlotButton.setDisabled(True) #### # connect cursors self.plt.sigRangeChanged.connect(self.scaleCursors) self.addPointButton.triggered.connect(self.addCursor) self.removePointButton.triggered.connect(self.removeCursor) self.drawCirclesButton.triggered.connect(self.plotMohrCircles) # Finally enable the save button self.saveButton.triggered.connect(self.save) self.setStatus('Ready') def showComboList(self): self.comboList.show() self.comboList.activateWindow() def checkForLastDir(self): ''' tries to open file 'lastdir' if it exists, returns the contents, else returns none ''' try: with open('lastdir','r') as f: return f.read() except IOError: return '' def makeLastDir(self,filename): ''' gets directory name from file absolute path create file 'lastdir' and writes ''' with open('lastdir','w') as f: f.write(os.path.dirname(filename)) def requestLoad(self): ''' opens file manager, gets filename, calls load ''' self.lastdir = self.checkForLastDir() # second par - name of file dialog window # third parameter - default file name # forth parameter - file filter. types separated by ';;' filename = QtGui.QFileDialog.getOpenFileName(self, "", "%s"%(self.lastdir), "*.clf;;MAT files (*.mat)") self.load(filename) def load(self,filename): ''' opens file manager, reads data from file, calls generateList to put into GUI ''' headerexpr = self.settings.msWidget.getHeaderExpr() slengthexpr = self.settings.msWidget.getSampleLengthExpr() if filename[0] == '': return if filename[1] == 'MAT files (*.mat)': self.data = pymat.load(filename[0]) elif filename[1] == u'*.clf': tup = readclf.readclf(filename[0], headerexpr=headerexpr, lengthexpr=slengthexpr) if tup==None: reply = QtGui.QMessageBox.warning(self, 'Wrong header', BadHeaderMessage, QtGui.QMessageBox.Ok ) IOError('Cannot read this file.') data,comments,length = tup else: raise IOError('Cannot read this file format.') # this is to remember this name when we wanna save file self.makeLastDir(filename[0]) # extract filename from absolute path self.filename = os.path.basename(filename[0]) # remove extension from name self.filename = os.path.splitext(self.filename)[0] # Separate all digital data and units units = data['Units'] del data['Units'] self.data = data # self.setParameters() # self.connectParameters() isNew = True if self.filename in self.allData.keys(): isNew = False self.allData[self.filename] = data # get one name from array to get length of the data key = data.keys()[0] l = self.data[key].shape[0] self.allSampleLengths[self.filename] = length self.allIndices[self.filename] = np.arange(l) self.allComments[self.filename] = comments self.allUnits[self.filename] = units self.addDataSet(self.filename,isNew) def addDataSet(self,name,isNew=True): print 'Modifying GUI: adding data set button' if isNew: dataSetButton = QtGui.QAction(name,self,checkable=True) dataSetButton.setActionGroup(self.dataSetGroup) dataSetButton.setChecked(True) self.dataSetMenu.addAction(dataSetButton) self.dataSetButtons[name] = dataSetButton dataSetButton.triggered.connect(lambda: self.setCurrentDataSet(name)) self.allCursors[name] = [] self.setCurrentDataSet(name) def setCurrentDataSet(self,name): print 'New data set is chosen' # if we switch to a different data set (if it's not the first), # remember cursors for the old one if self.currentDataSetName: print 'Saving old data' self.allIndices[self.currentDataSetName] = self.indices self.allCursors[self.currentDataSetName] = self.cursors self.allComments[self.currentDataSetName] = self.comments print 'Setting new data' # set current data dictionaries to new values self.currentDataSetName = name self.data = self.allData[name] self.units = self.allUnits[name] self.sampleLength = self.allSampleLengths[name] self.indices = self.allIndices[name] self.dataSetMenu.setDefaultAction(self.dataSetButtons[name]) self.cursors = self.allCursors[name] self.comments = self.allComments[name] self.setParameters() self.connectParameters() # self.mcSettings.setAvailableVariables(self.data.keys()) self.settings.mcWidget.setAvailableVariables(self.data.keys()) self.calcPlotButton.setDisabled(False) if self.calcPlot.active: print 'Calculator active' self.calcPlot.setData(self.data) self.updatePlot() def save(self): self.lastdir = self.checkForLastDir() # second par - name of file dialog window # third parameter - default file name # forth parameter - file filter. types separated by ';;' filename = pg.QtGui.QFileDialog.getSaveFileName(self, "Save to MATLAB format", "%s%s"%(self.lastdir,self.currentDataSetName), "MAT files (*.mat)") if filename[0] == '': return pymat.save(filename[0],self.data) def connectParameters(self): ''' Makes new connection of list entries with plot after loading a new dataset. 'Parameter' with name Time is default if it's in the list Default Interval variable is set to Time ''' # set default values for modifying parameters self.modparams.param('Parameter').setValue(self.timeParam) # self.modparams.param('Interval').setValue('Time') # connect signals to updating functions self.tree.sigStateChanged.connect(self.bindCursors) self.tree.sigStateChanged.connect(self.updatePlot) self.slider.sigRangeChanged.connect(self.truncate) # self.modparams.param('Interval').sigValueChanged.connect(self.updatePlot) self.modparams.param('min').sigValueChanged.connect(self.setTicks) self.modparams.param('max').sigValueChanged.connect(self.setTicks) self.modparams.param('Parameter').sigValueChanged.connect(self.updatePlot) self.modparams.param('Plot vs.').sigValueChanged.connect(self.setMainAxis) # connection with trend computations self.tree.sigStateChanged.connect(self.setTrendParameter) self.modparams.param('Parameter').sigValueChanged.connect(self.checkTrendUpdates) self.modparams.param('Plot vs.').sigValueChanged.connect(self.setTrendParameter) self.computeTrendFlag.sigValueChanged.connect(self.checkTrendUpdates) self.trendParameter.sigValueChanged.connect(self.setTrendParameter) # connect Null parameter self.nullFlag.sigValueChanged.connect(self.updatePlot) ### enable cursors buttons self.addPointButton.setEnabled(True) self.removePointButton.setEnabled(True) self.drawCirclesButton.setEnabled(True) def addCursor(self): print 'adding a Cursor' viewrange = self.plt.viewRange() # print viewrange rangeX = [viewrange[0][0],viewrange[0][1]] rangeY = [viewrange[1][0],viewrange[1][1]] pos = [(rangeX[0] + rangeX[1])/2,(rangeY[0] + rangeY[1])/2] xSize = float(rangeX[1]-rangeX[0])/50*800/self.plt.width() ySize = float(rangeY[1]-rangeY[0])/50*800/self.plt.height() Cursor = CursorItem.CursorItem(pos,[xSize,ySize],pen=(4,9)) self.cursors.append(Cursor) self.allCursors[self.currentDataSetName] = self.cursors # bind cursor if there is something to plot plotlist = self.activeEntries() if len(plotlist)>0: self.bindCursors() self.updatePlot() def removeCursor(self): if len(self.cursors)>0: self.cursors.pop(-1) self.updatePlot() def plotMohrCircles(self): global CirclesWidget CirclesWidget = MohrCircles.MohrCircles() params = self.settings.mcWidget.parameters() b = params[3] # biot coef names = [] PorePressure = [] AxialStress = [] ConfiningStress = [] ncircles = 0 for DataSet in self.allCursors.keys(): cursors = self.allCursors[DataSet] data = self.allData[DataSet] if cursors == []: continue else: indices = [] for cursor in cursors: indices.append(cursor.index) ncircles += 1 Sig1 = data[params[0]][cursor.index] #axial stress if params[1]=='0': Pc = 0 else: Pc = data[params[1]][cursor.index] # confining press if params[2]=='0': Pu = 0 else: Pu = data[params[2]][cursor.index] # pore pressure sigma1 = Sig1 - b*Pu sigma3 = Pc - b*Pu CirclesWidget.addData(max(sigma1,sigma3),min(sigma1,sigma3),name=DataSet +'_'+ str(ncircles)) if ncircles == 0: return 0 CirclesWidget.start() CirclesWidget.show() CirclesWidget.activateWindow() def scaleCursors(self): ''' make cursors circles of an appropriate size when scaling plot ''' viewrange = self.plt.viewRange() rangeX = [viewrange[0][0],viewrange[0][1]] rangeY = [viewrange[1][0],viewrange[1][1]] xSize = float(rangeX[1]-rangeX[0])/50*800/self.plt.width() ySize = float(rangeY[1]-rangeY[0])/50*800/self.plt.height() size = np.array([xSize,ySize]) for cursor in self.cursors: oldSize = cursor.getSize() # workaround to force the cursor stay on the same place cursor.translate(oldSize/2,snap=None) cursor.setSize(size) cursor.translate(-size/2,snap=None) def drawCursors(self): ''' add cursors again after clearing the plot window ''' for cursor in self.cursors: self.plt.addItem(cursor) def bindCursors(self): ''' make cursor slide along data ''' # print self.sender() try: plotlist = self.activeEntries() if self.mainAxis == 'y': xlabel = plotlist[-1] ylabel = self.modparams.param('Parameter').value() elif self.mainAxis == 'x': ylabel = plotlist[-1] xlabel = self.modparams.param('Parameter').value() x = self.data[xlabel][self.indices] y = self.data[ylabel][self.indices] for cursor in self.cursors: cursor.setData(x,y) except: pass def checkTrendUpdates(self): if self.computeTrendFlag.value(): self.computeTrend() self.updatePlot() def setTrendParameter(self): entries = self.activeEntries() for i in entries: pass if entries != []: self.trendParameter.setValue(i) self.checkTrendUpdates() def truncate(self): interval = self.slider.interval() arr = self.data[self.sliderParam] self.indices = (arr>=interval[0]) & (arr <= interval[1]) self.checkTrendUpdates() self.updatePlot() def setMainAxis(self): self.mainAxis = self.modparams.param('Plot vs.').value() self.updatePlot() def updateLimits(self): interval = self.slider.interval() self.modparams.param('min').sigValueChanged.disconnect(self.setTicks) self.modparams.param('max').sigValueChanged.disconnect(self.setTicks) self.modparams.param('min').setValue(interval[0]) self.modparams.param('max').setValue(interval[1]) self.modparams.param('min').sigValueChanged.connect(self.setTicks) self.modparams.param('max').sigValueChanged.connect(self.setTicks) def setTicks(self): ''' sets ticks to state coressponding to Interval min/max values, when they are manually changed ''' scale = self.data[self.sliderParam].max() values = [float(self.modparams.param('min').value())/scale, float(self.modparams.param('max').value())/scale ] self.slider.setInterval(values) self.updatePlot() def updatePlot(self): ''' updates plot ''' self.setAxisScale() self.updateLimits() ### Ready to update # self.setAutoFillBackground(True) self.clearPlotWindow() self.drawCursors() self.plt.showGrid(x=True, y=True) if self.mainAxis == 'x': self.plotVersusX() if self.mainAxis == 'y': self.plotVersusY() if self.computeTrendFlag.value(): self.plotTrend() if self.calcPlot.active: self.calcPlot.indices = self.indices self.calcPlot.plot() def plotVersusX(self): ''' plot when we have sevaral y's versus of x. ''' # Get variables to plot data = self.data plotlist = self.activeEntries() xlabel = self.modparams.param('Parameter').value() null = self.nullFlag.value() for i in range(len(plotlist)): ylabel = plotlist[i] color = self.tree.colors[ylabel].getColor() linestyle = pg.mkPen(color=color, width=3) yunits = self.units[ylabel] xdata = data[xlabel][self.indices] ydata = data[ylabel][self.indices] if null: ydata -= ydata[0] self.plt.plot(xdata, ydata, pen=linestyle, name=plotlist[i]) self.plt.setLabel('left', plotlist[i],units=yunits, **AxisLabelStyle) xunits = self.units[xlabel] self.plt.setLabel('bottom', xlabel,units=xunits,**AxisLabelStyle) # if len(plotlist)>0: self.bindCursors(data[xlabel],data[ylabel]) def plotVersusY(self): ''' plot when we have sevaral y's versus of x. ''' # Get variables to plot data = self.data plotlist = self.activeEntries() ylabel = self.modparams.param('Parameter').value() yunits = self.units[ylabel] null = self.nullFlag.value() for i in range(len(plotlist)): xlabel = plotlist[i] color = self.tree.colors[xlabel].getColor() linestyle = pg.mkPen(color=color, width=3) xunits = self.units[xlabel] xdata = data[xlabel][self.indices] ydata = data[ylabel][self.indices] if null: xdata -= xdata[0] self.plt.plot(xdata, ydata, pen=linestyle, name=plotlist[i]) self.plt.setLabel('bottom', xlabel,units=xunits,**AxisLabelStyle) self.plt.setLabel('left', ylabel,units=yunits,**AxisLabelStyle) def plotTrend(self): ''' plots linear trend ''' if self.mainAxis == 'x': xpar = self.modparams.param('Parameter').value() ypar = self.trendParameter.value() self.plt.setLabel('bottom', xpar) if self.mainAxis == 'y': xpar = self.trendParameter.value() ypar = self.modparams.param('Parameter').value() x = self.data[xpar][self.indices] y = self.slope*x + self.intersection self.plt.plot(x,y,pen=TrendPen, name='%s Trend'%(self.trendParameter.value())) self.plt.setLabel('bottom', xpar) self.plt.setLabel('left', ypar) def clearPlotWindow(self): ''' clears plot from data. clears legend. if there is no legend creates it ''' # default legend position position = [30,30] # clear plot area self.plt.clear() # remove old legend if self.legend: position = self.legend.pos() self.legend.scene().removeItem(self.legend) # creadte new legend self.plt.addLegend([90,20],offset=position) self.legend = self.plt.legend def setAxisScale(self): ''' sets scale to the interval axis. if time, sets minimum value to 0, because it could have been cleared ''' # interval_parameter = self.modparams.param('Interval').value() interval_parameter = self.sliderParam if interval_parameter == self.timeParam: self.slider.setRange(0,max(self.data[self.timeParam])) else: self.slider.setRange(min(self.data[interval_parameter]),max(self.data[interval_parameter])) def activeEntries(self): ''' returns a list of active entries in the data bar ''' plotlist = [] # for i in self.data.keys(): # if self.params.param(i).value() == True: for item in self.data.keys(): if self.tree.boxes[item].value() == True: plotlist.append(item) return plotlist def setParameters(self): print 'Modifying GUI: adding parameters to plot' # set modifying parameters self.modparamlist = ModifyingParameters self.modparamlist[1]['values'] = self.data.keys() # Parameter # self.modparamlist[2]['values'] = self.data.keys() # Interval self.modparamlist[5]['children'][1]['values'] = self.data.keys() # Trend parameter # create parameter class instances() # self.params = Parameter.create(name='Data', type='group',children=self.paramlist) self.modparams = Parameter.create(name='Options', type='group',children=self.modparamlist) self.tree.clear() self.tree.addItems(self.data.keys(),DataViewerTreeColors) # self.tree.setParameters(self.params, showTop=True) self.modtree.setParameters(self.modparams, showTop=True) self.assignAttributes() # to get shorter names def assignAttributes(self): ''' assign parameters from modparams tree to class DataViewer attributes to shorten code ''' self.nullFlag = self.modparams.param('Null') # assign chilren of 'Linear Trend' group to class attributes self.computeTrendFlag = self.modparams.param('Linear Trend').children()[0] self.trendParameter = self.modparams.param('Linear Trend').children()[1] self.trendSlope = self.modparams.param('Linear Trend').children()[2] self.trendIntersection = self.modparams.param('Linear Trend').children()[3] def setupGUI(self): pg.setConfigOption('background', (255,255,255)) pg.setConfigOption('foreground',(0,0,0)) self.setWindowIcon(QtGui.QIcon('images/Logo.png')) # Global widget where we place our layout self.layout = QtGui.QVBoxLayout() self.layout.setContentsMargins(0,0,0,0) self.layout.setSpacing(0) self.setLayout(self.layout) # Create and add menu bar self.menuBar = QtGui.QMenuBar() self.fileMenu = self.menuBar.addMenu('File') self.viewMenu = self.menuBar.addMenu('View') self.dataSetMenu = self.menuBar.addMenu('Dataset') self.mohrMenu = self.menuBar.addMenu('Mohr\' Circles') self.comboPlotMenu = self.menuBar.addMenu('Combo plot') self.prefMenu = self.menuBar.addMenu('Preferences') self.dataSetGroup = QtGui.QActionGroup(self) # create status bar self.layout.addWidget(self.menuBar,0) self.layout.setMenuBar(self.menuBar) # create submenu items self.loadButton = QtGui.QAction('Load',self) self.saveButton = QtGui.QAction('Save',self) self.exitButton = QtGui.QAction('Exit',self,shortcut="Alt+F4") self.calcPlotButton = QtGui.QAction('Calculator',self) self.autoScaleButton = QtGui.QAction('Auto scale',self) self.addPointButton = QtGui.QAction('Add point',self,shortcut='Ctrl+Q') self.removePointButton = QtGui.QAction('Remove point',self,shortcut='Ctrl+R') self.drawCirclesButton = QtGui.QAction('Draw Mohr\'s Circles',self,shortcut='Alt+M') self.showComboDataButton = QtGui.QAction('Show',self,shortcut='Ctrl+Shift+C') self.addSceneButton = QtGui.QAction('Add scene',self,shortcut='Ctrl+C') self.settingsButton = QtGui.QAction('Settings',self) self.addPointButton.setEnabled(False) self.removePointButton.setEnabled(False) self.drawCirclesButton.setEnabled(False) # Add buttons to submenus self.fileMenu.addAction(self.loadButton) self.fileMenu.addAction(self.saveButton) self.fileMenu.addAction(self.exitButton) self.mohrMenu.addAction(self.addPointButton) self.mohrMenu.addAction(self.removePointButton) self.mohrMenu.addAction(self.drawCirclesButton) self.viewMenu.addAction(self.calcPlotButton) self.viewMenu.addAction(self.autoScaleButton) self.comboPlotMenu.addAction(self.showComboDataButton) self.comboPlotMenu.addAction(self.addSceneButton) self.prefMenu.addAction(self.settingsButton) # splitter is a widget, which handles the layout # it splits the main window into parameter window # and the plotting area self.splitter = QtGui.QSplitter() self.splitter.setOrientation(QtCore.Qt.Horizontal) self.layout.addWidget(self.splitter) # tree is a list of parameters to plot self.tree = CParameterTree.CParameterTree(name='Data') # modtree is a list of governing parameters to modify plot self.modtree = ParameterTree(showHeader=False) # sublayout is were we place our plot and slider self.sublayout = pg.GraphicsLayoutWidget() # treesplitter splits parameter window into 2 halfs self.treesplitter = QtGui.QSplitter() self.buttonsplitter = QtGui.QSplitter() self.treesplitter.setOrientation(QtCore.Qt.Vertical) self.treesplitter.addWidget(self.tree) self.treesplitter.addWidget(self.modtree) self.treesplitter.setSizes([int(self.height()*0.7), int(self.height()*0.3), 20]) self.treesplitter.setStretchFactor(0, 0) self.treesplitter.setStretchFactor(1, 0.9) self.splitter.addWidget(self.treesplitter) self.splitter.addWidget(self.sublayout) self.splitter.setSizes([int(self.width()*0.4), int(self.width()*0.6)]) self.splitter.setStretchFactor(0, 0) self.splitter.setStretchFactor(1, 1) self.plt = self.sublayout.addPlot() setup_plot(self.plt) self.plt.setLabel('bottom', 'X Axis',**AxisLabelStyle) self.plt.setLabel('left', 'Y Axis',**AxisLabelStyle) self.plt.enableAutoRange(enable=True) self.autoScaleButton.triggered.connect(self.plt.enableAutoRange) # self.slider = self.createSlider() self.slider = SliderWidget() self.sublayout.nextRow() self.sublayout.addItem(self.slider) self.sublayout.nextRow() self.statusBar = QtGui.QStatusBar() self.treesplitter.addWidget(self.statusBar) self.setGeometry(80, 50, 800, 600) self.treesplitter.setStretchFactor(2, 0) self.treesplitter.setCollapsible(2, 0) self.statusBar.setSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Fixed) self.setGeometry(80, 30, 1000, 700) def setStatus(self,message): self.statusBar.showMessage(message) print message def computeTrend(self): ''' computer linear trend a and b and from truncated data. ''' if self.mainAxis == 'x': # if multiple plots vs x xpar = self.modparams.param('Parameter').value() ypar = self.trendParameter.value() if self.mainAxis == 'y': # if multiple plots vs y ypar = self.modparams.param('Parameter').value() xpar = self.trendParameter.value() x = self.data[xpar][self.indices] y = self.data[ypar][self.indices] A = np.array([x, np.ones(len(y))]).T ## Solves the equation a x = b by computing a vector x that ## minimizes the Euclidean 2-norm || b - a x ||^2. self.slope,self.intersection = np.linalg.lstsq(A,y)[0] self.trendSlope.setValue(self.slope) self.trendIntersection.setValue(self.intersection) def createSlider(self): slider = pg.GradientEditorItem(orientation='top', allowAdd=False) # print slider.__dict__ # slider.tickPen = pg.mkPen(color=(255,255,255)) slider.tickSize = 0 # print slider.gradRect slider.rectSize = 0 for i in slider.ticks: slider.setTickColor(i, QtGui.QColor(150,150,150)) return slider def closeEvent(self,event): ''' When pressing X button, show quit dialog. if yes, closes the window and ends the process ''' # reply = QtGui.QMessageBox.question(self, 'Quit Dataviewer', # "Are you sure to quit?", QtGui.QMessageBox.Yes | # QtGui.QMessageBox.No, QtGui.QMessageBox.No) # if reply == QtGui.QMessageBox.Yes: # sys.exit() # event.accept() # else: # event.ignore() sys.exit() def addSceneToCombo(self): print 'adding scene to Combo plot' rootname = self.currentDataSetName for item in self.plt.listDataItems(): name = rootname+'_'+item.name() x = item.xData y = item.yData self.comboList.addItem(name,x,y) def runCalcPlot(self): self.calcPlot.active = True self.calcPlot.setData(self.data) self.calcPlot.show() self.calcPlot.activateWindow()