class InitHist(object): #this is the fryplot init - will this work for the histogram? def __init__(self, plotTarget, barTarget, col=0, row=0): # add matplotlib figure to dialog self.plotTarget = plotTarget self.barTarget = barTarget self.col = col self.row = row self.setupFigure() def setupFigure(self): self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self.figure) self.mpltoolbar = NavigationToolbar(self.canvas, self.barTarget) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction(lstActions[7]) self.plotTarget.addWidget(self.canvas, self.row, self.col) self.plotTarget.addWidget(self.mpltoolbar) # and configure matplotlib params rcParams["font.serif"] = "Verdana, Arial, Liberation Serif" rcParams["font.sans-serif"] = "Tahoma, Arial, Liberation Sans" rcParams["font.cursive"] = "Courier New, Arial, Liberation Sans" rcParams["font.fantasy"] = "Comic Sans MS, Arial, Liberation Sans" rcParams["font.monospace"] = "Courier New, Liberation Mono" def histPlotter(self, lenList, title): self.axes.clear() self.axes.set_title(title) x = lenList count, bin, self.bar = self.axes.hist(x) self.figure.canvas.draw() def resetFigure(self): #plt.close(self.figure) #self.setupFigure() try: t = [b.remove() for b in self.bar] except: pass self.figure.canvas.draw()
class Averager(QMainWindow, Ui_Averager): def __init__(self): super(Averager, self).__init__() self.setupUi(self) # state variable self.idle = True # number of samples to show on the plot self.size = 8193 # max size # buffer and offset for the incoming samples self.buffer = bytearray(4 * self.size) self.offset = 0 self.data = np.frombuffer(self.buffer, np.int32) # create figure figure = Figure() figure.set_facecolor('none') self.axes = figure.add_subplot(111) self.canvas = FigureCanvas(figure) self.plotLayout.addWidget(self.canvas) # create navigation toolbar self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False) # remove subplots action actions = self.toolbar.actions() self.toolbar.removeAction(actions[7]) self.plotLayout.addWidget(self.toolbar) # create TCP socket self.socket = QTcpSocket(self) self.socket.connected.connect(self.connected) self.socket.readyRead.connect(self.read_data) self.socket.error.connect(self.display_error) self.cbShowComp.clear() self.cbShowComp.addItems(["Real", "Imaginary", "Absolute", "Phase"]) self.cbShowComp.setCurrentIndex(2); #connections self.btnStart.clicked.connect(self.start) self.txtNOA.valueChanged.connect(self.update_values) self.txtNOS.valueChanged.connect(self.update_values) self.chkFFT.stateChanged.connect(self.update_values) self.chkScale.stateChanged.connect(self.update_values) self.chkLogScale.stateChanged.connect(self.update_values) self.cbShowComp.currentIndexChanged.connect(self.update_values) self.isScaled = True self.isLogScale = False self.isFFT = False self.haveData = False self.showComp = 0 # Real, Imag, Abs, Phase from combo box def update_values(self): self.labNOA.setText(str((1<<int(self.txtNOA.text())))) self.labNOS.setText(str((1<<int(self.txtNOS.text())))) self.isScaled = self.chkScale.isChecked() self.isLogScale = self.chkLogScale.isChecked() self.isFFT = self.chkFFT.isChecked() self.showComp = self.cbShowComp.currentIndex() self.plot() def start(self): if self.idle: print "connecting ..." self.btnStart.setEnabled(False) self.socket.connectToHost(self.txtIPA.text(), 1001) else: self.idle = True self.socket.close() self.offset = 0 self.btnStart.setText('Start') self.btnStart.setEnabled(True) print "Disconnected" def setConfig(self): # Number of Samples self.size = (1<<int(self.txtNOS.text())) self.naverages = (1<<int(self.txtNOA.text())) #print "number of samples = " + str(self.size) if self.idle: return self.socket.write(struct.pack('<I', 1<<28 | int(self.txtTD.text()))) self.socket.write(struct.pack('<I', 2<<28 | int(self.txtNOS.text()))) self.socket.write(struct.pack('<I', 3<<28 | int(self.txtNOA.text()))) #print "Configuration sent" def connected(self): print "Connected" self.idle = False self.btnStart.setText('Stop') self.btnStart.setEnabled(True) self.setConfig() self.fire() def read_data(self): size = self.socket.bytesAvailable() print "got " + str(size) if self.offset + size < 4*self.size: self.buffer[self.offset:self.offset + size] = self.socket.read(size) self.offset += size else: #print "have all data" self.buffer[self.offset:4*self.size] = self.socket.read(4*self.size - self.offset) self.offset = 0 self.haveData = True self.plot() self.idle = True self.socket.close() self.offset = 0 self.btnStart.setText('Start') self.btnStart.setEnabled(True) print "Disconnected" def plot(self): if self.haveData == False: return # reset toolbar self.toolbar.home() self.toolbar._views.clear() self.toolbar._positions.clear() # reset plot self.axes.clear() self.axes.grid() # set data self.time_step = 1./125 # us y_data = np.array(self.data[0:self.size], dtype=float) N = self.size; # number of complex samples # scale y_data = y_data/self.naverages x_data = np.arange(1,N+1) xlab = "Index" ylab = "14-bit ADC output" if self.isScaled == True: self.gnd = 0*-146.6 self.vcc = 1133.7; y_data = 4.96*(y_data - self.gnd)/(self.vcc-self.gnd) x_data = self.time_step*x_data xlab = 'Time (us)' ylab = 'Voltage' if self.isFFT == True: y_data[-1] = (y_data[0]+y_data[-2])/2 y_data = np.fft.fft(y_data)/N x_data = np.fft.fftfreq(y_data.size, self.time_step) x_data = np.fft.fftshift(x_data) y_data = np.fft.fftshift(y_data) xlab = 'Frequency (MHz)' ylab = 'Amplitude' if self.showComp == 0: y_data = y_data.real ylab = "Real " + ylab elif self.showComp == 1: y_data = y_data.imag ylab = "Imag " + ylab elif self.showComp == 2: y_data = np.abs(y_data) ylab = "Abs " + ylab else: y_data = np.angle(y_data) ylab = "Phase " + ylab if self.isLogScale == True: y_data = 20*np.log10(y_data) ylab = ylab + ' (dBV)' else: ylab = ylab + ' (V)' #print str(y_data[N/2-1]) + " " + str(y_data[N/2]) + " " + str(y_data[N/2+1]) self.curve = self.axes.plot(x_data, y_data) #x1, x2, y1, y2 = self.axes.axis() # set y axis limits #self.axes.axis((1, self.size, -1500,500)) self.axes.set_xlim([min(x_data), max(x_data)]) self.axes.set_xlabel(xlab) self.axes.set_ylabel(ylab) self.canvas.draw() def display_error(self, socketError): if socketError == QAbstractSocket.RemoteHostClosedError: pass else: QMessageBox.information(self, 'Averager', 'Error: %s.' % self.socket.errorString()) self.btnStart.setText('Start') self.btnStart.setEnabled(True) def fire(self): if self.idle: return self.socket.write(struct.pack('<I', 0<<28))
class PlotWidget(QWidget): """A wrapper over CanvasWidget to handle additional MOOSE-specific stuff. modelRoot - path to the entire model our plugin is handling dataRoot - path to the container of data tables. pathToLine - map from moose path to Line2D objects in plot. Can one moose table be plotted multiple times? Maybe yes (e.g., when you want multiple other tables to be compared with the same data). lineToDataSource - map from Line2D objects to moose paths """ widgetClosedSignal = pyqtSignal(object) addGraph = pyqtSignal(object) def __init__(self, model, graph, index, parentWidget, *args, **kwargs): super(PlotWidget, self).__init__() self.model = model self.graph = graph self.index = index self.menu = self.getContextMenu() self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.connect( self , SIGNAL("customContextMenuRequested(QPoint)") , self , SLOT("contextMenuRequested(QPoint)") ) self.canvas = CanvasWidget(self.model, self.graph, self.index) self.canvas.setParent(self) self.navToolbar = NavigationToolbar(self.canvas, self) self.hackNavigationToolbar() self.canvas.mpl_connect('pick_event',self.togglePlot) layout = QtGui.QGridLayout() layout.addWidget(self.navToolbar, 0, 0) layout.addWidget(self.canvas, 1, 0) self.setLayout(layout) self.pathToLine = defaultdict(set) self.lineToDataSource = {} self.axesRef = self.canvas.addSubplot(1, 1) self.legend = None desktop = QtGui.QApplication.desktop() self.setMinimumSize(desktop.screenGeometry().width() / 4, desktop.screenGeometry().height() / 3) self.canvas.updateSignal.connect(self.plotAllData) self.plotAllData() def hackNavigationToolbar(self): # ADD Graph Action pixmap = QPixmap( os.path.join( config.MOOSE_ICON_DIR, 'add_graph.png' ) ) icon = QIcon(pixmap) action = QAction(icon, "Add a graph", self.navToolbar) # self.navToolbar.addAction(action) action.triggered.connect( self.addGraph.emit ) self.navToolbar.insertAction(self.navToolbar.actions()[0], action) # Delete Graph Action pixmap = QPixmap( os.path.join( config.MOOSE_ICON_DIR, "delete_graph.png") ) icon = QIcon(pixmap) action = QAction(icon, "Delete this graph", self.navToolbar) action.triggered.connect(self.delete) self.navToolbar.insertAction(self.navToolbar.actions()[1], action) #Toggle Grid Action pixmap = QPixmap( os.path.join( config.MOOSE_ICON_DIR, "grid.png" ) ) icon = QIcon(pixmap) action = QAction(icon, "Toggle Grid", self.navToolbar) action.triggered.connect(self.canvas.toggleGrid) self.navToolbar.insertAction(self.navToolbar.actions()[2], action) self.navToolbar.insertSeparator(self.navToolbar.actions()[3]) @property def plotAll(self): return len(self.pathToLine) == 0 def toggleLegend(self): if self.legend is not None: self.legend.set_visible(not self.legend.get_visible()) self.canvas.draw() def getContextMenu(self): menu = QMenu() # closeAction = menu.addAction("Delete") exportCsvAction = menu.addAction("Export to CSV") exportCsvAction.triggered.connect(self.saveAllCsv) toggleLegendAction = menu.addAction("Toggle legend") toggleLegendAction.triggered.connect(self.toggleLegend) self.removeSubmenu = menu.addMenu("Remove") # configureAction.triggered.connect(self.configure) # self.connect(,SIGNAL("triggered()"), # self,SLOT("slotShow500x500()")) # self.connect(action1,SIGNAL("triggered()"), # self,SLOT("slotShow100x100()")) return menu def deleteGraph(self): """ If there is only one graph in the view, please don't delete it """ print( "Deleting %s " % self.graph.path) moose.delete(self.graph.path) def delete(self, event): """FIXME: The last element should not be deleted """ _logger.info("Deleting PlotWidget " ) self.deleteGraph() self.close() self.widgetClosedSignal.emit(self) def configure(self, event): print("Displaying configure view!") self.plotView.getCentralWidget().show() @pyqtSlot(QtCore.QPoint) def contextMenuRequested(self,point): self.menu.exec_(self.mapToGlobal(point)) def setModelRoot(self, path): self.modelRoot = path def setDataRoot(self, path): self.dataRoot = path #plotAllData() def genColorMap(self,tableObject): species = tableObject+'/info' colormap_file = open(os.path.join(config.settings[config.KEY_COLORMAP_DIR], 'rainbow2.pkl'),'rb') self.colorMap = pickle.load(colormap_file) colormap_file.close() hexchars = "0123456789ABCDEF" color = 'white' #Genesis model exist the path and color will be set but not xml file so bypassing #print "here genColorMap ",moose.exists(species) if moose.exists(species): color = moose.element(species).getField('color') if ((not isinstance(color,(list,tuple)))): if color.isdigit(): tc = int(color) tc = (tc * 2 ) r,g,b = self.colorMap[tc] color = "#"+ hexchars[r / 16] + hexchars[r % 16] + hexchars[g / 16] + hexchars[g % 16] + hexchars[b / 16] + hexchars[b % 16] else: color = 'white' return color def removePlot(self, table): print(("removePlot =>", table)) moose.delete(table) self.plotAllData() def makeRemovePlotAction(self, label, table): action = self.removeSubmenu.addAction(label) action.triggered.connect(lambda: self.removePlot(table)) return action def plotAllData(self): """Plot data from existing tables""" self.axesRef.lines = [] self.pathToLine.clear() self.removeSubmenu.clear() if self.legend is not None: self.legend.set_visible(False) path = self.model.path modelroot = self.model.path time = moose.Clock('/clock').currentTime tabList = [] #for tabId in moose.wildcardFind('%s/##[TYPE=Table]' % (path)): #harsha: policy graphs will be under /model/modelName need to change in kkit #for tabId in moose.wildcardFind('%s/##[TYPE=Table]' % (modelroot)): plotTables = list(moose.wildcardFind(self.graph.path + '/##[TYPE=Table]')) plotTables.extend(moose.wildcardFind(self.graph.path + '/##[TYPE=Table2]')) if len (plotTables) > 0: for tabId in plotTables: tab = moose.Table(tabId) #print("Table =>", tab) line_list=[] tableObject = tab.neighbors['requestOut'] # Not a good way #tableObject.msgOut[0] if len(tableObject) > 0: # This is the default case: we do not plot the same # table twice. But in special cases we want to have # multiple variations of the same table on different # axes. # #Harsha: Adding color to graph for signalling model, check if given path has cubemesh or cylmesh color = '#FFFFFF' if moose.exists(tableObject[0].path + '/info'): color = getColor(tableObject[0].path + '/info') color = str(color[1].name()).upper() lines = self.pathToLine[tab.path] if len(lines) == 0: #Harsha: pass color for plot if exist and not white else random color #print "tab in plotAllData ",tab, tab.path,tab.name field = tab.path.rpartition(".")[-1] if field.endswith("[0]") or field.endswith("_0_"): field = field[:-3] # label = ( tableObject[0].path.partition(self.model.path + "/model[0]/")[-1] # + "." # + field # ) label = ( tableObject[0].path.rpartition("/")[-1] + "." + field ) self.makeRemovePlotAction(label, tab) if (color != '#FFFFFF'): newLines = self.addTimeSeries(tab, label=label,color=color) else: newLines = self.addTimeSeries(tab, label=label) self.pathToLine[tab.path].update(newLines) for line in newLines: self.lineToDataSource[line] = PlotDataSource(x='/clock', y=tab.path, z='') else: for line in lines: dataSrc = self.lineToDataSource[line] xSrc = moose.element(dataSrc.x) ySrc = moose.element(dataSrc.y) if isinstance(xSrc, moose.Clock): ts = np.linspace(0, time, len(tab.vector)) elif isinstance(xSrc, moose.Table): ts = xSrc.vector.copy() line.set_data(ts, tab.vector.copy()) tabList.append(tab) # if len(tabList) > 0: self.legend = self.canvas.callAxesFn( 'legend' , loc='upper right' , prop= {'size' : 10 } # , bbox_to_anchor=(1.0, 0.5) , fancybox = True , shadow=False , ncol=1 ) if self.legend is not None: self.legend.draggable() self.legend.get_frame().set_alpha(0.5) self.legend.set_visible(True) self.canvas.draw() # # leg = self.canvas.callAxesFn( 'legend' # # , loc ='upper right' # # , prop = {'size' : 10 } # # # , bbox_to_anchor = (0.5, -0.03) # # , fancybox = False # # # , shadow = True # # , ncol = 1 # # ) # # leg.draggable(False) # # print(leg.get_window_extent()) # #leg = self.canvas.callAxesFn('legend') # #leg = self.canvas.callAxesFn('legend',loc='upper left', fancybox=True, shadow=True) # #global legend # #legend =leg # for legobj in leg.legendHandles: # legobj.set_linewidth(5.0) # legobj.set_picker(True) # else: # print "returning as len tabId is zero ",tabId, " tableObject ",tableObject, " len ",len(tableObject) def togglePlot(self, event): #print "onclick",event1.artist.get_label() #harsha:To workout with double-event-registered on onclick event #http://stackoverflow.com/questions/16278358/double-event-registered-on-mouse-click-if-legend-is-outside-axes legline = event.artist for line in self.axesRef.lines: if line.get_label() == event.artist.get_label(): vis = not line.get_visible() line.set_visible(vis) if vis: legline.set_alpha(1.0) else: legline.set_alpha(0.2) break self.canvas.draw() def addTimeSeries(self, table, *args, **kwargs): ts = np.linspace(0, moose.Clock('/clock').currentTime, len(table.vector)) return self.canvas.plot(ts, table.vector, *args, **kwargs) def addRasterPlot(self, eventtable, yoffset=0, *args, **kwargs): """Add raster plot of events in eventtable. yoffset - offset along Y-axis. """ y = np.ones(len(eventtable.vector)) * yoffset return self.canvas.plot(eventtable.vector, y, '|') def updatePlots(self): for path, lines in list(self.pathToLine.items()): element = moose.element(path) if isinstance(element, moose.Table2): tab = moose.Table2(path) else: tab = moose.Table(path) data = tab.vector ts = np.linspace(0, moose.Clock('/clock').currentTime, len(data)) for line in lines: line.set_data(ts, data) self.canvas.draw() def extendXAxes(self, xlim): for axes in list(self.canvas.axes.values()): # axes.autoscale(False, axis='x', tight=True) axes.set_xlim(right=xlim) axes.autoscale_view(tight=True, scalex=True, scaley=True) self.canvas.draw() def rescalePlots(self): """This is to rescale plots at the end of simulation. ideally we should set xlim from simtime. """ for axes in list(self.canvas.axes.values()): axes.autoscale(True, tight=True) axes.relim() axes.autoscale_view(tight=True,scalex=True,scaley=True) self.canvas.draw() def saveCsv(self, line, directory): """Save selected plot data in CSV file""" src = self.lineToDataSource[line] xSrc = moose.element(src.x) ySrc = moose.element(src.y) y = ySrc.vector.copy() if isinstance(xSrc, moose.Clock): x = np.linspace(0, xSrc.currentTime, len(y)) elif isinstance(xSrc, moose.Table): x = xSrc.vector.copy() nameVec = ySrc.neighbors['requestOut'] name = moose.element(nameVec[0]).name filename = str(directory)+'/'+'%s.csv' %(name) np.savetxt(filename, np.vstack((x, y)).transpose()) print('Saved data from %s and %s in %s' % (xSrc.path, ySrc.path, filename)) def saveAllCsv(self): """Save data for all currently plotted lines""" #Harsha: Plots were saved in GUI folder instead provided QFileDialog box to save to #user choose fileDialog2 = QtGui.QFileDialog(self) fileDialog2.setFileMode(QtGui.QFileDialog.Directory) fileDialog2.setWindowTitle('Select Directory to save plots') fileDialog2.setOptions(QtGui.QFileDialog.ShowDirsOnly) fileDialog2.setLabelText(QtGui.QFileDialog.Accept, self.tr("Save")) targetPanel = QtGui.QFrame(fileDialog2) targetPanel.setLayout(QtGui.QVBoxLayout()) layout = fileDialog2.layout() layout.addWidget(targetPanel) if fileDialog2.exec_(): directory = fileDialog2.directory().path() for line in list(self.lineToDataSource.keys()): self.saveCsv(line,directory) def getMenus(self): if not hasattr(self, '_menus'): self._menus = [] self.plotAllAction = QtGui.QAction('Plot all data', self) self.plotAllAction.triggered.connect(self.plotAllData) self.plotMenu = QtGui.QMenu('Plot') self.plotMenu.addAction(self.plotAllAction) self.saveAllCsvAction = QtGui.QAction('Save all data in CSV files', self) self.saveAllCsvAction.triggered.connect(self.saveAllCsv) self.plotMenu.addAction(self.saveAllCsvAction) self._menus.append(self.plotMenu) return self._menus
class ProfileFromPointsDialog(QtWidgets.QDialog, FORM_CLASS): proj = QgsProject.instance() def __init__(self, parent=None): """Constructor.""" super(ProfileFromPointsDialog, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) # add matplotlib figure to dialog self.figure = Figure() self.axes = self.figure.add_subplot(111) # self.figure.subplots_adjust(left=.1, bottom=0.15, right=.78, top=.9, wspace=None) self.mplCanvas = FigureCanvas(self.figure) self.mpltoolbar = NavigationToolbar(self.mplCanvas, self.toolbarWidget) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction(lstActions[7]) self.layoutPlot.addWidget(self.mplCanvas) self.layoutPlot.addWidget(self.mpltoolbar) self.figure.patch.set_visible(False) self.layoutPlot.minimumSize() ##connections self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.uPointLayer.currentIndexChanged.connect(self.reloadFields) self.uLineLayer.currentIndexChanged.connect(self.checkSelectedLine) self.uCopytoClip.clicked.connect(self.copyClipboard) self.manageGui() def manageGui(self): # print('manageGui') self.uPointLayer.clear() Lstptos = utils.getPointLayerNames() self.uPointLayer.addItems(Lstptos) #try to find activelayer and select it in the point combobox try: lyrName = qgis.utils.iface.activeLayer().name() if lyrName in Lstptos: self.uPointLayer.setCurrentText(lyrName) except Exception as e: print('Erro:', str(e)) pass self.uLineLayer.clear() self.uLineLayer.addItems(utils.getLineLayerNames()) def reloadFields(self): # print('reload fields') self.uZfield.clear() self.uPointID.clear() self.uOrderField.clear() self.axes.clear() point_layer = self.proj.mapLayersByName( self.uPointLayer.currentText())[0] #processing.getObject(str()) if point_layer.selectedFeatureCount() != 0: self.uSelectedPoints.setCheckState(Qt.Checked) else: self.uSelectedPoints.setCheckState(Qt.Unchecked) self.uZfield.addItems( utils.getFieldNames(point_layer, [QVariant.Int, QVariant.Double])) self.uOrderField.addItems( utils.getFieldNames(point_layer, [QVariant.Int, QVariant.Double])) self.uPointID.addItems( utils.getFieldNames( point_layer, [QVariant.Int, QVariant.Double, 10])) # 10 is for string def checkSelectedLine(self): ###print 'check if line layer selected' line_layer = self.proj.mapLayersByName( self.uLineLayer.currentText())[0] #processing.getObject(str()) if line_layer: if line_layer.selectedFeatureCount() != 0: self.uSelectedLine.setCheckState(Qt.Checked) else: self.uSelectedLine.setCheckState(Qt.Unchecked) def copyClipboard(self): if self.values is None: return else: clipboard = QApplication.clipboard() if self.uNoHeader.isChecked(): clipboard.setText('\n'.join( '%s\t%s' % x for x in zip(self.values[0], self.values[1]))) else: clipboard.setText('distance\televation\tpointID\n' + '\n'.join( '%s\t%s\t%s' % x for x in zip( self.values[0], self.values[1], self.values[2]))) def restoreGui(self): self.buttonBox.rejected.connect(self.reject) self.btnClose.clicked.disconnect(self.stopProcessing) self.btnClose.setText(self.tr("Close")) self.btnOk.setEnabled(True) self.uprogressBar.setMaximum(100) def refreshPlot(self): self.axes.clear() if self.values is None: return self.axes.plot(np.array(self.values[0]), np.array(self.values[1])) ###to draw labels from jorgealmerio if self.uPointIDlabels.isChecked(): for i, linha in enumerate(np.array(self.values[2])): id = self.values[2][i] dist = self.values[0][i] z = self.values[1][i] self.axes.annotate(id, (dist, z)) self.axes.grid() formatter = ScalarFormatter(useOffset=False) self.axes.yaxis.set_major_formatter(formatter) self.axes.set_ylabel(str(self.tr("Elevation, z field units"))) self.axes.set_xlabel(str(self.tr('Station, layer units'))) self.mplCanvas.draw() def buildLine(self, pointSelectFlag): # print('buildLine') pointLayer = self.proj.mapLayersByName( self.uPointLayer.currentText())[0] #processing.getObject(str()) orderField = self.uOrderField.currentText() sortOrder = self.uOrder.currentText() crs = pointLayer.crs().toWkt() pointList = [] if pointSelectFlag: pointFeatureList = pointLayer.selectedFeatures() else: pointFeatureList = pointLayer.getFeatures() for pointFeature in pointFeatureList: pointGeom = pointFeature.geometry() coords = pointGeom.asPoint() sortField = pointFeature[orderField] ##store data pointList.append([coords, sortField]) if not pointFeatureList: QMessageBox.warning(self, 'Error', 'Selected point list is empty') return 'Error' ###sort data by field if sortOrder == 'Ascending': pointList = sorted(pointList, key=itemgetter(1)) else: pointList = sorted(pointList, key=itemgetter(1), reverse=True) ## drop sort field pointList = list(zip(*pointList))[0] #list(zip(*pointList)[0]) ###build line # create a new memory layer newLineLayer = QgsVectorLayer("LineString?crs=" + crs, "profileFromPointsLine", "memory") pr = newLineLayer.dataProvider() feat = QgsFeature() geom = QgsGeometry.fromPolylineXY(pointList) feat.setGeometry(geom) pr.addFeatures([feat]) newLineLayer.updateExtents() QgsProject.instance().addMapLayers([newLineLayer]) return newLineLayer def accept(self): # print('run') pointLayer = self.proj.mapLayersByName( self.uPointLayer.currentText())[0] #processing.getObject(str()) # check for selected features if self.uSelectedPoints.isChecked(): pointSelectFlag = True else: pointSelectFlag = False if self.uSelectedLine.isChecked(): lineSelectFlag = True else: lineSelectFlag = False ## check if need to build line if self.utabWidget.currentIndex() == 0: lineLayer = self.buildLine(pointSelectFlag) if lineLayer == 'Error': return else: lineLayer = self.proj.mapLayersByName( self.uLineLayer.currentText())[0] #processing.getObject(str()) zField = self.uZfield.currentText() pointIdField = self.uPointID.currentText() try: noData = float(self.lineEditNoData.text()) except: QMessageBox.warning(self, 'Error', 'No data value must be numeric') return if self.uBuffer.displayText() != '': buff = float(self.uBuffer.displayText()) else: buff = None # trap for coordinate system if lineLayer.crs() != pointLayer.crs(): QMessageBox.warning( self, 'Error', 'Point layer coordinate system does not match line coordinate system' ) return # trap for more than one line feature counter = 0 if lineSelectFlag: lineFeatureList = lineLayer.selectedFeatures() else: lineFeatureList = lineLayer.getFeatures() for lineFeatures in lineFeatureList: counter = counter + 1 if counter != 1: QMessageBox.warning(self, 'Error', 'More than one line feature in line layer') return if lineSelectFlag: lineFeat = lineLayer.selectedFeatures()[0] else: lineFeat = next(lineLayer.getFeatures()) lineGeom = lineFeat.geometry() if lineGeom.isMultipart: polilinha = lineGeom.asMultiPolyline()[0] #get only first else: polilinha = lineGeom.asPolyline() lineShap = LineString(polilinha) if buff: lineBoundary = lineShap.buffer(buff) if pointSelectFlag: pointFeatureList = pointLayer.selectedFeatures() else: pointFeatureList = pointLayer.getFeatures() pointList = [] for pointFeature in pointFeatureList: pointGeom = pointFeature.geometry() pointShap = Point(pointGeom.asPoint()) if buff: ## check if point is within line buffer if pointShap.within(lineBoundary): z = pointFeature[zField] ### get distance along line dist = lineShap.project(pointShap) pointId = pointFeature[pointIdField] ##store data pointList.append([dist, z, pointId]) else: z = pointFeature[zField] ### get distance along line dist = lineShap.project(pointShap) pointId = pointFeature[pointIdField] ##store data pointList.append([dist, z, pointId]) ###sort data by distance pointList = sorted(pointList, key=itemgetter(0)) ###seperate data back into individual lists zList = [] distList = [] pointIdList = [] for i in pointList: ## only keep data that is not flaged as noData if i[1] != noData: distList.append(i[0]) zList.append(i[1]) pointIdList.append(i[2]) self.values = [distList, zList, pointIdList] self.refreshPlot() self.uCopytoClip.setEnabled(True)
class kmeansDialog(QtGui.QDialog, FORM_CLASS): def __init__(self, parent=None): """Constructor.""" super(kmeansDialog, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) # add matplotlib figure to dialog self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self.figure) self.mpltoolbar = NavigationToolbar(self.canvas, self.widgetPlot) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction(lstActions[7]) self.layoutPlot.addWidget(self.canvas) self.layoutPlot.addWidget(self.mpltoolbar) # and configure matplotlib params rcParams["font.serif"] = "Verdana, Arial, Liberation Serif" rcParams["font.sans-serif"] = "Tahoma, Arial, Liberation Sans" rcParams["font.cursive"] = "Courier New, Arial, Liberation Sans" rcParams["font.fantasy"] = "Comic Sans MS, Arial, Liberation Sans" rcParams["font.monospace"] = "Courier New, Liberation Mono" self.values = None self.outPath = None self.btnOk = self.buttonBox.button(QDialogButtonBox.Ok) self.btnClose = self.buttonBox.button(QDialogButtonBox.Close) self.openBtn.clicked.connect(self.saveFile) self.chkShowGrid.stateChanged.connect(self.refreshPlot) self.chkAsPlot.stateChanged.connect(self.refreshPlot) self.btnRefresh.clicked.connect(self.refreshPlot) self.manageGui() self.axes.set_title(unicode(self.tr(u"Statistic Plot"))) def manageGui(self): self.cmbLayers.clear() self.cmbLayers.addItems(utils.getVectorLayerNames()) self.btnRefresh.setEnabled(False) def accept(self): self.axes.clear() self.spnMinX.setValue(0.0) self.spnMaxX.setValue(0.0) self.lstStatistics.clearContents() self.lstStatistics.setRowCount(0) layer = utils.getVectorLayerByName(self.cmbLayers.currentText()) statData = self.kmeansCluster(layer, self.cmbDis.currentIndex(), self.spnNum.value()) self.processFinished(statData) self.addClassField(layer) self.progressBar.setValue(0) def reject(self): QDialog.reject(self) def setProgressRange(self, maxValue): self.progressBar.setRange(0, maxValue) def updateProgress(self): self.progressBar.setValue(self.progressBar.value() + 1) def processFinished(self, statData): # populate table with results self.tableData = statData[0] self.values = statData[1] rowCount = len(self.tableData) self.lstStatistics.setRowCount(rowCount) for i in xrange(rowCount): item = QTableWidgetItem(self.tr("%d") % (i)) self.lstStatistics.setItem(i, 0, item) tmp = self.tableData[i] item = QTableWidgetItem(self.tr("%f") % (tmp[0])) self.lstStatistics.setItem(i, 1, item) item = QTableWidgetItem(self.tr("%f") % (tmp[1])) self.lstStatistics.setItem(i, 2, item) self.lstStatistics.resizeRowsToContents() self.btnRefresh.setEnabled(True) # create histogram self.refreshPlot() def saveFile(self): self.outPath = QFileDialog.getSaveFileName(self, u'保存文件',u"map","jpg(*.jpg)") self.lineEdit.setText(self.outPath) def refreshPlot(self): self.axes.clear() self.axes.set_title(unicode(self.tr("Statistic Plot"))) interval = None if self.values is None: return if self.spnMinX.value() == self.spnMaxX.value(): pass else: interval = [] if self.spnMinX.value() > self.spnMaxX.value(): interval.append(self.spnMaxX.value()) interval.append(self.spnMinX.value()) else: interval.append(self.spnMinX.value()) interval.append(self.spnMaxX.value()) if not self.chkAsPlot.isChecked(): self.axes.hist(self.values, 18, interval, alpha=0.5, histtype="bar") #self.axes.plot(self.values, "ro-") else: n, bins, pathes = self.axes.hist(self.values, 18, interval, alpha=0.5, histtype="bar") self.axes.clear() c = [] for i in range(len(bins) - 1): s = bins[i + 1] - bins[i] c.append(bins[i] + (s / 2)) self.axes.plot(c, n, "ro-") self.axes.grid(self.chkShowGrid.isChecked()) self.axes.set_ylabel(unicode(self.tr("Count"))) self.axes.set_xlabel(unicode(self.tr("Class"))) self.figure.autofmt_xdate() self.canvas.draw() def kmeansCluster(self, layer, distance, number): import scipy import scipy.cluster.hierarchy as sch from scipy.cluster.vq import vq,kmeans,whiten import numpy as np count = layer.featureCount() self.setProgressRange(count) points = [] for f in layer.getFeatures(): geom = f.geometry() x = geom.asPoint().x() y = geom.asPoint().y() point = [] point.append(x) point.append(y) points.append(point) self.updateProgress() distances = {0:'euclidean', 1:'cityblock', 2:'hamming'} disMat = sch.distance.pdist(points, distances.get(distance))#'euclidean''cityblock''hamming''cosine' Z=sch.linkage(disMat,method='average') P=sch.dendrogram(Z) cluster= sch.fcluster(Z, t=1, criterion='inconsistent') data=whiten(points) centroid=kmeans(data, number)[0] label=vq(data, centroid)[0] return centroid, label def addClassField(self, vectorLayer): vectorLayerDataProvider = vectorLayer.dataProvider() outputFieldName = unicode(self.tr("class")) # Create field of not exist if vectorLayer.fieldNameIndex(outputFieldName) == -1: vectorLayerDataProvider.addAttributes([QgsField(outputFieldName, QVariant.Int)]) vectorLayer.updateFields() vectorLayer.startEditing() attrIdx = vectorLayer.fieldNameIndex(outputFieldName) features = vectorLayer.getFeatures() idx = self.values.tolist() i = 0 for feature in features: vectorLayer.changeAttributeValue(feature.id(), attrIdx, int(idx[i])) i += 1 vectorLayer.updateFields() vectorLayer.commitChanges() self.symbolLayer(vectorLayer) def saveAsMap(self, layer): reg = QgsMapLayerRegistry.instance() i = QImage(QSize(800,800), QImage.Format_ARGB32_Premultiplied) c = QColor("white") i.fill(c.rgb()) p = QPainter() p.begin(i) r = QgsMapRenderer() lyrs = reg.mapLayers().keys() r.setLayerSet(lyrs) rect = QgsRectangle(r.fullExtent()) rect.scale(1.1) r.setExtent(rect) r.setOutputSize(i.size(), i.logicalDpiX()) r.render(p) p.end() i.save(self.outPath,"jpg") # def saveAsMap(self, layer): # i = QImage(QSize(800,800), QImage.Format_ARGB32_Premultiplied) # c = QColor("white") # i.fill(c.rgb()) # p = QPainter() # p.begin(i) # p.setRenderHint(QPainter.Antialiasing) # r = QgsMapRenderer() # lyrs = [layer.getLayerID()] # r.setLayerSet(lyrs) # rect = QgsRect(r.fullExtent()) # rect.scale(1.1) # r.setExtent(rect) # r.setOutputSize(i.size(), i.logicalDpiX()) # r.render(p) # p.end() # i.save(self.outPath,"jpg") def symbolLayer(self, layer): classField = ( ("0",0,0,"red"), ("1",1,1,"orange"), ("2",2,2,"yellow"), ("3",3,3,"green"), ("4",4,4,"cyan"), ("5",5,5,"blue"), ("6",6,6,"purple"), ("7",7,7,"brown"), ("8",8,8,"grey"), ("9",9,9,"black")) ranges = [] for label,lower,upper,color in classField: sym = QgsSymbolV2.defaultSymbol(layer.geometryType()) sym.setColor(QColor(color)) rng = QgsRendererRangeV2(lower, upper, sym, label) ranges.append(rng) field = "class" renderer = QgsGraduatedSymbolRendererV2(field, ranges) layer.setRendererV2(renderer) layer.triggerRepaint() self.saveAsMap(layer)
class InitRose(object): #Create a rose diagram def __init__(self, plotTarget, barTarget, col=0, row=0): # add matplotlib figure to dialog self.plotTarget = plotTarget self.barTarget = barTarget self.col = col self.row = row self.setupFigure() def setupFigure(self): self.rosefigure = Figure() self.axes = self.rosefigure.add_subplot( 111, polar=True) #set up a plot with polar co-ordinates self.axes.set_theta_direction( -1) #change the direction of increasing angle to match compass self.axes.set_theta_zero_location( "N") #change the O theta position to North self.canvas = FigureCanvas(self.rosefigure) self.mpltoolbar = NavigationToolbar(self.canvas, self.barTarget) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction(lstActions[7]) self.plotTarget.addWidget(self.canvas, self.row, self.col) self.plotTarget.addWidget(self.mpltoolbar) # and configure matplotlib params rcParams["font.serif"] = "Verdana, Arial, Liberation Serif" rcParams["font.sans-serif"] = "Tahoma, Arial, Liberation Sans" rcParams["font.cursive"] = "Courier New, Arial, Liberation Sans" rcParams["font.fantasy"] = "Comic Sans MS, Arial, Liberation Sans" rcParams["font.monospace"] = "Courier New, Liberation Mono" def rosePlotter(self, aziList, title): self.axes.set_title(title) angle = 15 #the width of the divisions of the rose diagram. later stage this could be set by value in dialog box ##get data list data = aziList #set up bin parameters nsection = 360 // angle direction = np.linspace(0, 360, nsection, False) / 180 * np.pi #print direction ##set up list for counting frequency frequency = [0] * (nsection) ##count up how many in each bin for i in data: tmp = int( (i - (i % angle)) / angle) ##figure out which bin data belongs frequency[tmp] = frequency[tmp] + 1 awidth = angle / 180.0 * np.pi * np.ones( nsection ) ## makes an array with nection entries all with the same number representing the angular width self.bar = self.axes.bar(direction, frequency, width=awidth, bottom=0.0) self.rosefigure.canvas.draw() def resetFigure(self): #plt.close(self.rosefigure) #self.setupFigure() try: self.bar.remove() except: pass self.rosefigure.canvas.draw()
class InitScatter: """ def __init__(self, plotTarget, barTarget): # add matplotlib figure to dialog self.plotTarget = plotTarget self.barTarget = barTarget self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self.figure) self.mpltoolbar = NavigationToolbar(self.canvas, self.barTarget) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction(lstActions[7]) self.plotTarget.addWidget(self.canvas) self.plotTarget.addWidget(self.mpltoolbar) # and configure matplotlib params rcParams["font.serif"] = "Verdana, Arial, Liberation Serif" rcParams["font.sans-serif"] = "Tahoma, Arial, Liberation Sans" rcParams["font.cursive"] = "Courier New, Arial, Liberation Sans" rcParams["font.fantasy"] = "Comic Sans MS, Arial, Liberation Sans" rcParams["font.monospace"] = "Courier New, Liberation Mono" """ #this is the fryplot init - will this work for the histogram? def __init__(self, plotTarget, barTarget, col=0, row=0): # add matplotlib figure to dialog self.plotTarget = plotTarget self.barTarget = barTarget self.col = col self.row = row self.setupFigure() def setupFigure(self): self.figure = Figure() self.axes = self.figure.add_subplot(111) self.canvas = FigureCanvas(self.figure) self.mpltoolbar = NavigationToolbar(self.canvas, self.barTarget) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction(lstActions[7]) self.plotTarget.addWidget(self.canvas, self.row, self.col) self.plotTarget.addWidget(self.mpltoolbar, self.row + 1, self.col) # and configure matplotlib params rcParams["font.serif"] = "Verdana, Arial, Liberation Serif" rcParams["font.sans-serif"] = "Tahoma, Arial, Liberation Sans" rcParams["font.cursive"] = "Courier New, Arial, Liberation Sans" rcParams["font.fantasy"] = "Comic Sans MS, Arial, Liberation Sans" rcParams["font.monospace"] = "Courier New, Liberation Mono" def scatterPlotter(self, listX, listY, title): self.axes.clear() self.axes.set_title(title, size=9) self.scatter = self.axes.scatter(listX, listY, 2) self.axes.axis('equal') self.axes.grid(b=True) self.axes.tick_params(labelsize=4) self.canvas.draw() def resetFigure(self): #plt.close(self.figure) #self.setupFigure() try: self.scatter.remove() self.setupFigure() except: pass self.figure.canvas.draw()
class calibrlogger(PyQt4.QtGui.QMainWindow, Calibr_Ui_Dialog): # An instance of the class Calibr_Ui_Dialog is created same time as instance of calibrlogger is created def __init__(self, parent, settingsdict1={}, obsid=''): PyQt4.QtGui.QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))#show the user this may take a long time... self.obsid = obsid self.log_pos = None self.y_pos = None self.meas_ts = None self.head_ts = None self.level_masl_ts = None self.loggerpos_masl_or_offset_state = 1 self.settingsdict = settingsdict1 PyQt4.QtGui.QDialog.__init__(self, parent) self.setAttribute(PyQt4.QtCore.Qt.WA_DeleteOnClose) self.setupUi(self) # Required by Qt4 to initialize the UI self.setWindowTitle("Calculate water level from logger") # Set the title for the dialog self.INFO.setText("Select the observation point with logger data to be adjusted.") self.log_calc_manual.setText("<a href=\"https://github.com/jkall/qgis-midvatten-plugin/wiki/4.-Edit-data\">Midvatten manual</a>") # Create a plot window with one single subplot self.calibrplotfigure = plt.figure() self.axes = self.calibrplotfigure.add_subplot( 111 ) self.canvas = FigureCanvas( self.calibrplotfigure ) self.mpltoolbar = NavigationToolbar( self.canvas, self.widgetPlot ) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction( lstActions[ 7 ] ) self.layoutplot.addWidget( self.canvas ) self.layoutplot.addWidget( self.mpltoolbar ) self.calibrplotfigure.tight_layout() self.show() self.cid =[] self.connect(self.pushButtonSet, PyQt4.QtCore.SIGNAL("clicked()"), self.set_logger_pos) self.connect(self.pushButtonAdd, PyQt4.QtCore.SIGNAL("clicked()"), self.add_to_level_masl) self.connect(self.pushButtonFrom, PyQt4.QtCore.SIGNAL("clicked()"), self.set_from_date_from_x) self.connect(self.pushButtonTo, PyQt4.QtCore.SIGNAL("clicked()"), self.set_to_date_from_x) self.connect(self.pushButtonupdateplot, PyQt4.QtCore.SIGNAL("clicked()"), self.update_plot) #self.connect(self.loggerpos_masl_or_offset, PyQt4.QtCore.SIGNAL("clicked()"), self.loggerpos_masl_or_offset_change) #self.connect(self.pushButtonLpos, PyQt4.QtCore.SIGNAL("clicked()"), self.calibrate_from_plot_selection) self.connect(self.pushButtonLpos, PyQt4.QtCore.SIGNAL("clicked()"), self.catch_old_level) self.connect(self.pushButtonMpos, PyQt4.QtCore.SIGNAL("clicked()"), self.catch_new_level) self.pushButtonMpos.setEnabled(False) self.connect(self.pushButtonCalcBestFit, PyQt4.QtCore.SIGNAL("clicked()"), self.logger_pos_best_fit) self.connect(self.pushButtonCalcBestFit2, PyQt4.QtCore.SIGNAL("clicked()"), self.level_masl_best_fit) self.connect(self.pushButton_delete_logger, PyQt4.QtCore.SIGNAL("clicked()"), lambda: self.delete_selected_range(u'w_levels_logger')) self.get_search_radius() # Populate combobox with obsid from table w_levels_logger self.load_obsid_from_db() PyQt4.QtGui.QApplication.restoreOverrideCursor()#now this long process is done and the cursor is back as normal def load_obsid_from_db(self): print ('am here')#debug self.combobox_obsid.clear() myconnection = utils.dbconnection() if myconnection.connect2db() == True: print('connected')#debug # skapa en cursor curs = myconnection.conn.cursor() rs=curs.execute("""select distinct obsid from w_levels_logger order by obsid""") self.combobox_obsid.addItem('') for row in curs: print(row[0])#debug self.combobox_obsid.addItem(row[0]) rs.close() myconnection.closedb() def load_obsid_and_init(self): """ Checks the current obsid and reloads all ts. :return: obsid Info: Before, some time series was only reloaded when the obsid was changed, but this caused a problem if the data was changed in the background in for example spatialite gui. Now all time series are reloaded always. It's rather fast anyway. """ obsid = unicode(self.combobox_obsid.currentText()) if not obsid: utils.pop_up_info("ERROR: no obsid is chosen") return None meas_sql = r"""SELECT date_time, level_masl FROM w_levels WHERE obsid = '""" + obsid + """' ORDER BY date_time""" self.meas_ts = self.sql_into_recarray(meas_sql) head_sql = r"""SELECT date_time as 'date [datetime]', head_cm / 100 FROM w_levels_logger WHERE obsid = '""" + obsid + """' ORDER BY date_time""" self.head_ts = self.sql_into_recarray(head_sql) self.obsid = obsid level_masl_ts_sql = r"""SELECT date_time as 'date [datetime]', level_masl FROM w_levels_logger WHERE obsid = '""" + self.obsid + """' ORDER BY date_time""" self.level_masl_ts = self.sql_into_recarray(level_masl_ts_sql) return obsid def getlastcalibration(self): obsid = self.load_obsid_and_init() if not obsid=='': sql = """SELECT MAX(date_time), loggerpos FROM (SELECT date_time, (level_masl - (head_cm/100)) as loggerpos FROM w_levels_logger WHERE level_masl > -990 AND obsid = '""" sql += obsid sql += """')""" self.lastcalibr = utils.sql_load_fr_db(sql)[1] if self.lastcalibr[0][1] and self.lastcalibr[0][0]: text = """Last pos. for logger in """ text += obsid text += """ was """ + str(self.lastcalibr[0][1]) + """ masl at """ + str(self.lastcalibr[0][0]) else: text = """There is no earlier known position for the logger in """ + unicode(self.combobox_obsid.currentText())#self.obsid[0] self.INFO.setText(text) def set_logger_pos(self): self.loggerpos_masl_or_offset_state = 1 obsid = self.load_obsid_and_init() if not self.LoggerPos.text() == '': self.calibrate() self.update_plot() def add_to_level_masl(self): self.loggerpos_masl_or_offset_state = 0 obsid = self.load_obsid_and_init() if not self.Add2Levelmasl.text() == '': self.calibrate() self.update_plot() def calibrate(self): self.calib_help.setText("Calibrating") PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) obsid = self.load_obsid_and_init() if not obsid=='': sanity1sql = """select count(obsid) from w_levels_logger where obsid = '""" + obsid[0] + """'""" sanity2sql = """select count(obsid) from w_levels_logger where head_cm not null and head_cm !='' and obsid = '""" + obsid[0] + """'""" if utils.sql_load_fr_db(sanity1sql)[1] == utils.sql_load_fr_db(sanity2sql)[1]: # This must only be done if head_cm exists for all data fr_d_t = self.FromDateTime.dateTime().toPyDateTime() to_d_t = self.ToDateTime.dateTime().toPyDateTime() if self.loggerpos_masl_or_offset_state == 1: self.update_level_masl_from_head(obsid, fr_d_t, to_d_t, self.LoggerPos.text()) else: self.update_level_masl_from_level_masl(obsid, fr_d_t, to_d_t, self.Add2Levelmasl.text()) self.getlastcalibration() else: utils.pop_up_info("Calibration aborted!!\nThere must not be empty cells or\nnull values in the 'head_cm' column!") else: self.INFO.setText("Select the observation point with logger data to be calibrated.") self.calib_help.setText("") PyQt4.QtGui.QApplication.restoreOverrideCursor() def update_level_masl_from_level_masl(self, obsid, fr_d_t, to_d_t, newzref): """ Updates the level masl using newzref :param obsid: (str) The obsid :param fr_d_t: (datetime) start of calibration :param to_d_t: (datetime) end of calibration :param newzref: (int/float/str [m]) The correction that should be made against the head [m] :return: None """ sql =r"""UPDATE w_levels_logger SET level_masl = """ sql += str(newzref) sql += """ + level_masl WHERE obsid = '""" sql += obsid # Sqlite seems to have problems with date comparison date_time >= a_date, so they have to be converted into total seconds first. sql += """' AND CAST(strftime('%s', date_time) AS NUMERIC) > """ sql += str((fr_d_t - datetime.datetime(1970,1,1)).total_seconds()) sql += """ AND CAST(strftime('%s', date_time) AS NUMERIC) < """ sql += str((to_d_t - datetime.datetime(1970,1,1)).total_seconds()) sql += """ """ dummy = utils.sql_alter_db(sql) def update_level_masl_from_head(self, obsid, fr_d_t, to_d_t, newzref): """ Updates the level masl using newzref :param obsid: (str) The obsid :param fr_d_t: (datetime) start of calibration :param to_d_t: (datetime) end of calibration :param newzref: (int/float/str [m]) The correction that should be made against the head [m] :return: None """ sql =r"""UPDATE w_levels_logger SET level_masl = """ sql += str(newzref) sql += """ + head_cm / 100 WHERE obsid = '""" sql += obsid # Sqlite seems to have problems with date comparison date_time >= a_date, so they have to be converted into total seconds first (but now we changed to > but kept .total_seconds()) sql += """' AND CAST(strftime('%s', date_time) AS NUMERIC) > """ sql += str((fr_d_t - datetime.datetime(1970,1,1)).total_seconds()) sql += """ AND CAST(strftime('%s', date_time) AS NUMERIC) < """ sql += str((to_d_t - datetime.datetime(1970,1,1)).total_seconds()) sql += """ """ dummy = utils.sql_alter_db(sql) def sql_into_recarray(self, sql): """ Converts and runs an sql-string and turns the answer into an np.recarray and returns it""" my_format = [('date_time', datetime.datetime), ('values', float)] #Define (with help from function datetime) a good format for numpy array recs = utils.sql_load_fr_db(sql)[1] table = np.array(recs, dtype=my_format) #NDARRAY table2=table.view(np.recarray) # RECARRAY Makes the two columns inte callable objects, i.e. write table2.values return table2 def update_plot(self): """ Plots self.level_masl_ts, self.meas_ts and maybe self.head_ts """ self.reset_plot_selects_and_calib_help() self.calib_help.setText("Updating plot") PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) obsid = self.load_obsid_and_init() if obsid == None: PyQt4.QtGui.QApplication.restoreOverrideCursor() self.calib_help.setText("") return self.axes.clear() p=[None]*2 # List for plot objects # Load manual reading (full time series) for the obsid self.plot_recarray(self.axes, self.meas_ts, obsid, 'o-', 10) # Load Loggerlevels (full time series) for the obsid if self.loggerLineNodes.isChecked(): logger_line_style = '.-' else: logger_line_style = '-' self.plot_recarray(self.axes, self.level_masl_ts, obsid + unicode(' logger', 'utf-8'), logger_line_style, 10) #Plot the original head_cm if self.plot_logger_head.isChecked(): self.plot_recarray(self.axes, self.head_ts, obsid + unicode(' original logger head', 'utf-8'), logger_line_style, 10) """ Finish plot """ self.axes.grid(True) self.axes.yaxis.set_major_formatter(tick.ScalarFormatter(useOffset=False, useMathText=False)) self.calibrplotfigure.autofmt_xdate() self.axes.set_ylabel(unicode('Level (masl)', 'utf-8')) #This is the method that accepts even national characters ('åäö') in matplotlib axes labels self.axes.set_title(unicode('Plot for ', 'utf-8') + str(obsid)) #This is the method that accepts even national characters ('åäö') in matplotlib axes labels for label in self.axes.xaxis.get_ticklabels(): label.set_fontsize(10) for label in self.axes.yaxis.get_ticklabels(): label.set_fontsize(10) #plt.show() self.calibrplotfigure.tight_layout() self.canvas.draw() plt.close(self.calibrplotfigure)#this closes reference to self.calibrplotfigure PyQt4.QtGui.QApplication.restoreOverrideCursor() self.calib_help.setText("") self.getlastcalibration() def plot_recarray(self, axes, a_recarray, lable, line_style, picker=10): """ Plots a recarray to the supplied axes object """ # Get help from function datestr2num to get date and time into float myTimestring = [a_recarray.date_time[idx] for idx in xrange(len(a_recarray))] numtime=datestr2num(myTimestring) #conv list of strings to numpy.ndarray of floats axes.plot_date(numtime, a_recarray.values, line_style, label=lable, picker=picker) def set_from_date_from_x(self): """ Used to set the self.FromDateTime by clicking on a line node in the plot self.canvas """ self.reset_plot_selects_and_calib_help() self.calib_help.setText("Select a node to use as \"from\"") self.deactivate_pan_zoom() self.canvas.setFocusPolicy(Qt.ClickFocus) self.canvas.setFocus() self.cid.append(self.canvas.mpl_connect('pick_event', lambda event: self.set_date_from_x_onclick(event, self.FromDateTime))) def set_to_date_from_x(self): """ Used to set the self.ToDateTime by clicking on a line node in the plot self.canvas """ self.reset_plot_selects_and_calib_help() self.calib_help.setText("Select a node to use as \"to\"") self.deactivate_pan_zoom() self.canvas.setFocusPolicy(Qt.ClickFocus) self.canvas.setFocus() self.cid.append(self.canvas.mpl_connect('pick_event', lambda event: self.set_date_from_x_onclick(event, self.ToDateTime))) def set_date_from_x_onclick(self, event, date_holder): """ Sets the date_holder to a date from a line node closest to the pick event date_holder: a QDateTimeEdit object. """ found_date = utils.find_nearest_date_from_event(event) date_holder.setDateTime(found_date) self.reset_plot_selects_and_calib_help() def reset_plot_selects_and_calib_help(self): """ Reset self.cid and self.calib_help """ self.reset_cid() self.log_pos = None self.y_pos = None self.calib_help.setText("") def reset_cid(self): """ Resets self.cid to an empty list and disconnects unused events """ for x in self.cid: self.canvas.mpl_disconnect(x) self.cid = [] def catch_old_level(self): """Part of adjustment method 3. adjust level_masl by clicking in plot. this part selects a line node and a y-position on the plot""" #Run init to make sure self.meas_ts and self.head_ts is updated for the current obsid. self.load_obsid_and_init() self.deactivate_pan_zoom() self.canvas.setFocusPolicy(Qt.ClickFocus) self.canvas.setFocus() self.calib_help.setText("Select a logger node.") self.cid.append(self.canvas.mpl_connect('pick_event', self.set_log_pos_from_node_date_click)) def catch_new_level(self): """ Part of adjustment method 3. adjust level_masl by clicking in plot. this part selects a y-position from the plot (normally user would select a manual measurement).""" if self.log_pos is not None: self.calib_help.setText("Select a y position to move to.") self.cid.append(self.canvas.mpl_connect('button_press_event', self.set_y_pos_from_y_click)) self.calib_help.setText("") else: self.calib_help.setText("Something wrong, click \"Current\" and try again.") def calculate_offset(self): """ Part of adjustment method 3. adjust level_masl by clicking in plot. this method extracts the head from head_ts with the same date as the line node. 4. Calculating y-position - head (or level_masl) and setting self.LoggerPos. 5. Run calibration. """ if self.log_pos is not None and self.y_pos is not None: PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) logger_ts = self.level_masl_ts y_pos = self.y_pos log_pos = self.log_pos self.y_pos = None self.log_pos = None log_pos_date = datestring_to_date(log_pos).replace(tzinfo=None) logger_value = None #Get the value for the selected node for raw_date, logger_value in logger_ts: date = datestring_to_date(raw_date).replace(tzinfo=None) if date == log_pos_date: break if logger_value is None: utils.pop_up_info("No connection between level_masl dates and logger date could be made!\nTry again or choose a new logger line node!") else: self.Add2Levelmasl.setText(str(float(y_pos) - float(logger_value))) PyQt4.QtGui.QApplication.restoreOverrideCursor() self.pushButtonMpos.setEnabled(False) def set_log_pos_from_node_date_click(self, event): """ Sets self.log_pos variable to the date (x-axis) from the node nearest the pick event """ found_date = utils.find_nearest_date_from_event(event) #self.calib_help.setText("Logger node " + str(found_date) + " selected, click button \"Calibrate by selection in plot\" again.") self.calib_help.setText("Logger node " + str(found_date) + " selected, click \"new\" and select new level.") self.log_pos = found_date self.reset_cid() self.pushButtonMpos.setEnabled(True) def set_y_pos_from_y_click(self, event): """ Sets the self.y_pos variable to the y value of the click event """ self.y_pos = event.ydata #self.calib_help.setText("Y position set, click button \"Calibrate by selection in plot\" again for calibration.") self.calculate_offset() self.calib_help.setText("Offset is calculated, now click \"add\".") self.reset_cid() def logger_pos_best_fit(self): self.loggerpos_masl_or_offset_state = 1 self.calc_best_fit() def level_masl_best_fit(self): self.loggerpos_masl_or_offset_state = 0 self.calc_best_fit() def calc_best_fit(self): """ Calculates the self.LoggerPos from self.meas_ts and self.head_ts First matches measurements from self.meas_ts to logger values from self.head_ts. This is done by making a mean of all logger values inside self.meas_ts date - search_radius and self.meas_ts date + search_radius. (this could probably be change to get only the closest logger value inside the search_radius instead) (search_radius is gotten from self.get_search_radius()) Then calculates the mean of all matches and set to self.LoggerPos. """ obsid = self.load_obsid_and_init() self.reset_plot_selects_and_calib_help() search_radius = self.get_search_radius() if self.loggerpos_masl_or_offset_state == 1:# UPDATE TO RELEVANT TEXT logger_ts = self.head_ts text_field = self.LoggerPos calib_func = self.set_logger_pos really_calibrate_question = utils.askuser("YesNo", """This will calibrate all values inside the chosen period\nusing the mean difference between head_cm and w_levels measurements.\n\nSearch radius for matching logger and measurement nodes set to '""" + ' '.join(search_radius) + """'\n\nContinue?""") else:# UPDATE TO RELEVANT TEXT logger_ts = self.level_masl_ts text_field = self.Add2Levelmasl calib_func = self.add_to_level_masl really_calibrate_question = utils.askuser("YesNo", """This will calibrate all values inside the chosen period\nusing the mean difference between level_masl and w_levels measurements.\n\nSearch radius for matching logger and measurement nodes set to '""" + ' '.join(search_radius) + """'\n\nContinue?""") if really_calibrate_question.result == 0: # if the user wants to abort return PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor) coupled_vals = self.match_ts_values(self.meas_ts, logger_ts, search_radius) if not coupled_vals: utils.pop_up_info("There was no matched measurements or logger values inside the chosen period.\n Try to increase the search radius!") else: text_field.setText(str(utils.calc_mean_diff(coupled_vals))) calib_func() PyQt4.QtGui.QApplication.restoreOverrideCursor() def match_ts_values(self, meas_ts, logger_ts, search_radius_tuple): """ Matches two timeseries values for shared timesteps For every measurement point, a mean of logger values inside measurementpoint + x minutes to measurementpoint - x minutes is coupled together. At the first used measurement, only logger values greater than the set start date is used. At the last measurement, only logger values lesser than the set end date is used. This is done so that values from another logger reposition is not mixed with the chosen logger positioning. (Hard to explain). """ coupled_vals = [] #Get the search radius, default to 10 minutes search_radius = int(search_radius_tuple[0]) search_radius_period = search_radius_tuple[1] logger_gen = utils.ts_gen(logger_ts) try: l = next(logger_gen) except StopIteration: return None log_vals = [] all_done = False #The .replace(tzinfo=None) is used to remove info about timezone. Needed for the comparisons. This should not be a problem though as the date scale in the plot is based on the dates from the database. outer_begin = self.FromDateTime.dateTime().toPyDateTime().replace(tzinfo=None) outer_end = self.ToDateTime.dateTime().toPyDateTime().replace(tzinfo=None) logger_step = datestring_to_date(l[0]).replace(tzinfo=None) for m in meas_ts: if logger_step is None: break meas_step = datestring_to_date(m[0]).replace(tzinfo=None) step_begin = dateshift(meas_step, -search_radius, search_radius_period) step_end = dateshift(meas_step, search_radius, search_radius_period) if step_end < outer_begin: continue if step_begin > outer_end: break #Skip logger steps that are earlier than the chosen begin date or are not inside the measurement period. while logger_step < step_begin or logger_step < outer_begin: try: l = next(logger_gen) except StopIteration: all_done = True break logger_step = datestring_to_date(l[0]).replace(tzinfo=None) log_vals = [] while logger_step is not None and step_begin <= logger_step <= step_end and outer_begin <= logger_step <= outer_end: if not math.isnan(float(l[1])) or l[1] in ('nan', 'NULL'): log_vals.append(float(l[1])) try: l = next(logger_gen) except StopIteration: all_done = True break logger_step = datestring_to_date(l[0]).replace(tzinfo=None) if log_vals: mean = np.mean(log_vals) if not math.isnan(mean): coupled_vals.append((m[1], mean)) if all_done: break return coupled_vals def get_search_radius(self): """ Get the period search radius, default to 10 minutes """ if not self.bestFitSearchRadius.text(): search_radius = '10 minutes' self.bestFitSearchRadius.setText(search_radius) else: search_radius = self.bestFitSearchRadius.text() search_radius_splitted = search_radius.split() if len(search_radius_splitted) != 2: utils.pop_up_info("Must write time resolution also, ex. 10 minutes") return tuple(search_radius_splitted) def deactivate_pan_zoom(self): """ Deactivates the NavigationToolbar pan or zoom feature if they are currently active """ if self.mpltoolbar._active == "PAN": self.mpltoolbar.pan() elif self.mpltoolbar._active == "ZOOM": self.mpltoolbar.zoom() def delete_selected_range(self, table_name): """ Deletes the current selected range from the database from w_levels_logger :return: De """ current_loaded_obsid = self.obsid selected_obsid = self.load_obsid_and_init() if current_loaded_obsid != selected_obsid: utils.pop_up_info("Error!\n The obsid selection has been changed but the plot has not been updated. No deletion done.\nUpdating plot.") self.update_plot() return elif selected_obsid is None: utils.pop_up_info("Error!\n No obsid was selected. No deletion done.\nUpdating plot.") self.update_plot() return fr_d_t = str((self.FromDateTime.dateTime().toPyDateTime() - datetime.datetime(1970,1,1)).total_seconds()) to_d_t = str((self.ToDateTime.dateTime().toPyDateTime() - datetime.datetime(1970,1,1)).total_seconds()) sql_list = [] sql_list.append(r"""delete from "%s" """%table_name) sql_list.append(r"""where obsid = '%s' """%selected_obsid) sql_list.append(r"""AND CAST(strftime('%s', date_time) AS NUMERIC) """) sql_list.append(r""" > '%s' """%fr_d_t) sql_list.append(r"""AND CAST(strftime('%s', date_time) AS NUMERIC) """) sql_list.append(r""" < '%s' """%to_d_t) sql = ''.join(sql_list) really_delete = utils.askuser("YesNo", "Do you want to delete the period " + str(self.FromDateTime.dateTime().toPyDateTime()) + " to " + str(self.ToDateTime.dateTime().toPyDateTime()) + " for obsid " + selected_obsid + " from table " + table_name + "?").result if really_delete: utils.sql_alter_db(sql) self.update_plot()
class plotsqlitewindow(QtGui.QMainWindow, customplot_ui_class): def __init__(self, parent, msettings):#, parent as second arg? self.ms = msettings self.ms.loadSettings() QtGui.QDialog.__init__(self, parent) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setupUi( self )#due to initialisation of Ui_MainWindow instance self.initUI() self.LoadTablesFromDB() self.LastSelections()#fill comboboxes etc with last selected values #on close: #del self.axes.collections[:]#this should delete all plot objects related to axes and hence not intefere with following tsplots self.drawn = False def initUI(self): self.table_ComboBox_1.clear() self.table_ComboBox_2.clear() self.table_ComboBox_3.clear() for i in range (1,3): self.clearthings(1) # function partial due to problems with currentindexChanged and Combobox #self.connect(self.table_ComboBox_1, QtCore.SIGNAL("currentIndexChanged(int)"), partial(self.Table1Changed))#currentIndexChanged caused unnecessary signals when scrolling in combobox self.connect(self.table_ComboBox_1, QtCore.SIGNAL("activated(int)"), partial(self.Table1Changed)) self.connect(self.Filter1_ComboBox_1, QtCore.SIGNAL("activated(int)"), partial(self.Filter1_1Changed)) #self.connect(self.Filter1_ComboBox_1, QtCore.SIGNAL("activated(int)"), partial(self.FilterChanged(1,1))) self.connect(self.Filter2_ComboBox_1, QtCore.SIGNAL("activated(int)"), partial(self.Filter2_1Changed)) self.connect(self.table_ComboBox_2, QtCore.SIGNAL("activated(int)"), partial(self.Table2Changed)) self.connect(self.Filter1_ComboBox_2, QtCore.SIGNAL("activated(int)"), partial(self.Filter1_2Changed)) self.connect(self.Filter2_ComboBox_2, QtCore.SIGNAL("activated(int)"), partial(self.Filter2_2Changed)) self.connect(self.table_ComboBox_3, QtCore.SIGNAL("activated(int)"), partial(self.Table3Changed)) self.connect(self.Filter1_ComboBox_3, QtCore.SIGNAL("activated(int)"), partial(self.Filter1_3Changed)) self.connect(self.Filter2_ComboBox_3, QtCore.SIGNAL("activated(int)"), partial(self.Filter2_3Changed)) self.PlotChart_QPushButton.clicked.connect(self.drawPlot) self.Redraw_pushButton.clicked.connect( self.refreshPlot ) # Create a plot window with one single subplot self.custplotfigure = plt.figure() self.axes = self.custplotfigure.add_subplot( 111 ) self.canvas = FigureCanvas( self.custplotfigure ) self.mpltoolbar = NavigationToolbar( self.canvas, self.widgetPlot) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction( lstActions[ 7 ] ) self.layoutplot.addWidget( self.canvas ) self.layoutplot.addWidget( self.mpltoolbar ) #Validator for QlineEdit that should contain only floats, any number of decimals with either point(.) or comma(,) as a decimal separater regexp = QtCore.QRegExp('[+-]?\\d*[\\.,]?\\d+') validator = QtGui.QRegExpValidator(regexp) self.LineEditFactor1.setValidator(validator) self.LineEditFactor2.setValidator(validator) self.LineEditFactor3.setValidator(validator) self.LineEditOffset1.setValidator(validator) self.LineEditOffset2.setValidator(validator) self.LineEditOffset3.setValidator(validator) self.show() def calc_frequency(self,table2): freqs = np.zeros(len(table2.values),dtype=float) for j, row in enumerate(table2): if j>0:#we can not calculate frequency for first row try: diff = (table2.values[j] - table2.values[j-1]) """ Get help from function datestr2num to get date and time into float""" delta_time = 24*3600*(datestr2num(table2.date_time[j]) - datestr2num(table2.date_time[j-1]))#convert to seconds since numtime is days except: pass #just skip inaccurate data values and use previous frequency freqs[j] = diff/delta_time freqs[0]=freqs[1]#assuming start frequency to get a nicer plot return freqs def drawPlot(self): QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))#show the user this may take a long time... self.axes.clear() self.axes.legend_ = None My_format = [('date_time', datetime.datetime), ('values', float)] #Define (with help from function datetime) a good format for numpy array myconnection = utils.dbconnection() myconnection.connect2db() curs = myconnection.conn.cursor() i = 0 nop=0# nop=number of plots self.p=[] self.plabels=[] if not (self.table_ComboBox_1.currentText() == '' or self.table_ComboBox_1.currentText()==' ') and not (self.xcol_ComboBox_1.currentText()== '' or self.xcol_ComboBox_1.currentText()==' ') and not (self.ycol_ComboBox_1.currentText()== '' or self.ycol_ComboBox_1.currentText()==' '): #if anything is to be plotted from tab 1 self.ms.settingsdict['custplot_maxtstep'] = self.spnmaxtstep.value() # if user selected a time step bigger than zero than thre may be discontinuous plots plottable1='y' filter1 = unicode(self.Filter1_ComboBox_1.currentText()) filter1list = [] filter2list = [] filter1list = self.Filter1_QListWidget_1.selectedItems() filter2 = unicode(self.Filter2_ComboBox_1.currentText()) filter2list= self.Filter2_QListWidget_1.selectedItems() nop += max(len(filter1list),1)*max(len(filter2list),1) #self.p= [None]*nop#list for plot objects self.p.extend([None]*nop)#list for plot objects self.plabels.extend([None]*nop)# List for plot labels try: factor1 = float(self.LineEditFactor1.text().replace(',','.')) except ValueError: factor1 = 1.0 try: offset1 = float(self.LineEditOffset1.text().replace(',','.')) except ValueError: offset1 = 0.0 remove_mean1 = self.checkBox_remove_mean1.isChecked() while i < len(self.p): if not (filter1 == '' or filter1==' ' or filter1list==[]) and not (filter2== '' or filter2==' ' or filter2list==[]): for item1 in filter1list: for item2 in filter2list: sql = r""" select """ + unicode(self.xcol_ComboBox_1.currentText()) + """, """ + unicode(self.ycol_ComboBox_1.currentText()) + """ from """ + unicode(self.table_ComboBox_1.currentText()) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' and """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol_ComboBox_1.currentText()) self.plabels[i] = unicode(item1.text()) + """, """ + unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_1.currentText(), factor1, offset1, remove_mean1) i += 1 elif not (filter1 == '' or filter1==' ' or filter1list==[]): for item1 in filter1list: sql = r""" select """ + unicode(self.xcol_ComboBox_1.currentText()) + """, """ + unicode(self.ycol_ComboBox_1.currentText()) + """ from """ + unicode(self.table_ComboBox_1.currentText()) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' order by """ + unicode(self.xcol_ComboBox_1.currentText()) self.plabels[i] = unicode(item1.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_1.currentText(), factor1, offset1, remove_mean1) i += 1 elif not (filter2 == '' or filter2==' ' or filter2list==[]): for item2 in filter2list: sql = r""" select """ + unicode(self.xcol_ComboBox_1.currentText()) + """, """ + unicode(self.ycol_ComboBox_1.currentText()) + """ from """ + unicode(self.table_ComboBox_1.currentText()) + """ where """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol_ComboBox_1.currentText()) self.plabels[i] = unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_1.currentText(), factor1, offset1, remove_mean1) i += 1 else: sql = r""" select """ + unicode(self.xcol_ComboBox_1.currentText()) + """, """ + unicode(self.ycol_ComboBox_1.currentText()) + """ from """ + unicode(self.table_ComboBox_1.currentText()) + """ order by """ + unicode(self.xcol_ComboBox_1.currentText()) self.plabels[i] = unicode(self.ycol_ComboBox_1.currentText())+""", """+unicode(self.table_ComboBox_1.currentText()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_1.currentText(), factor1, offset1, remove_mean1) i += 1 if not (self.table_ComboBox_2.currentText() == '' or self.table_ComboBox_2.currentText()==' ') and not (self.xcol_ComboBox_2.currentText()== '' or self.xcol_ComboBox_2.currentText()==' ') and not (self.ycol_ComboBox_2.currentText()== '' or self.ycol_ComboBox_2.currentText()==' '):#if anything is to be plotted from tab 2 self.ms.settingsdict['custplot_maxtstep'] = self.spnmaxtstep.value() # if user selected a time step bigger than zero than thre may be discontinuous plots plottable2='y' filter1 = unicode(self.Filter1_ComboBox_2.currentText()) filter1list = [] filter2list = [] filter1list = self.Filter1_QListWidget_2.selectedItems() filter2 = unicode(self.Filter2_ComboBox_2.currentText()) filter2list= self.Filter2_QListWidget_2.selectedItems() nop =+ max(len(filter1list),1)*max(len(filter2list),1) self.p.extend([None]*nop)#list for plot objects self.plabels.extend([None]*nop)# List for plot labels try: factor2 = float(self.LineEditFactor2.text().replace(',','.')) except ValueError: factor2 = 1.0 try: offset2 = float(self.LineEditOffset2.text().replace(',','.')) except ValueError: offset2 = 0.0 remove_mean2 = self.checkBox_remove_mean2.isChecked() while i < len(self.p): if not (filter1 == '' or filter1==' ' or filter1list==[]) and not (filter2== '' or filter2==' ' or filter2list==[]): for item1 in filter1list: for item2 in filter2list: sql = r""" select """ + unicode(self.xcol_ComboBox_2.currentText()) + """, """ + unicode(self.ycol_ComboBox_2.currentText()) + """ from """ + unicode(self.table_ComboBox_2.currentText()) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' and """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol_ComboBox_2.currentText()) self.plabels[i] = unicode(item1.text()) + """, """ + unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText(), factor2, offset2, remove_mean2) i += 1 elif not (filter1 == '' or filter1==' ' or filter1list==[]): for item1 in filter1list: sql = r""" select """ + unicode(self.xcol_ComboBox_2.currentText()) + """, """ + unicode(self.ycol_ComboBox_2.currentText()) + """ from """ + unicode(self.table_ComboBox_2.currentText()) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' order by """ + unicode(self.xcol_ComboBox_2.currentText()) self.plabels[i] = unicode(item1.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText(), factor2, offset2, remove_mean2) i += 1 elif not (filter2 == '' or filter2==' ' or filter2list==[]): for item2 in filter2list: sql = r""" select """ + unicode(self.xcol_ComboBox_2.currentText()) + """, """ + unicode(self.ycol_ComboBox_2.currentText()) + """ from """ + unicode(self.table_ComboBox_2.currentText()) + """ where """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol_ComboBox_2.currentText()) self.plabels[i] = unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText(), factor2, offset2, remove_mean2) i += 1 else: sql = r""" select """ + unicode(self.xcol_ComboBox_2.currentText()) + """, """ + unicode(self.ycol_ComboBox_2.currentText()) + """ from """ + unicode(self.table_ComboBox_2.currentText()) + """ order by """ + unicode(self.xcol_ComboBox_2.currentText()) self.plabels[i] = unicode(self.ycol2)+""", """+unicode(self.table_ComboBox_2.currentText()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText(), factor2, offset2, remove_mean2) i += 1 if not (self.table_ComboBox_3.currentText() == '' or self.table_ComboBox_3.currentText()==' ') and not (self.xcol_ComboBox_3.currentText()== '' or self.xcol_ComboBox_3.currentText()==' ') and not (self.ycol_ComboBox_3.currentText()== '' or self.ycol_ComboBox_3.currentText()==' '):#if anything is to be plotted from tab 3 self.ms.settingsdict['custplot_maxtstep'] = self.spnmaxtstep.value() # if user selected a time step bigger than zero than thre may be discontinuous plots plottable3='y' filter1 = unicode(self.Filter1_ComboBox_3.currentText()) filter1list = [] filter2list = [] filter1list = self.Filter1_QListWidget_3.selectedItems() filter2 = unicode(self.Filter2_ComboBox_3.currentText()) filter2list= self.Filter2_QListWidget_3.selectedItems() nop =+ max(len(filter1list),1)*max(len(filter2list),1) self.p.extend([None]*nop)#list for plot objects self.plabels.extend([None]*nop)# List for plot labels try: factor3 = float(self.LineEditFactor3.text().replace(',','.')) except ValueError: factor3 = 1.0 try: offset3 = float(self.LineEditOffset3.text().replace(',','.')) except ValueError: offset3 = 0.0 remove_mean3 = self.checkBox_remove_mean3.isChecked() while i < len(self.p): if not (filter1 == '' or filter1==' ' or filter1list==[]) and not (filter2== '' or filter2==' ' or filter2list==[]): for item1 in filter1list: for item2 in filter2list: sql = r""" select """ + unicode(self.xcol_ComboBox_3.currentText()) + """, """ + unicode(self.ycol_ComboBox_3.currentText()) + """ from """ + unicode(self.table_ComboBox_3.currentText()) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' and """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol_ComboBox_3.currentText()) self.plabels[i] = unicode(item1.text()) + """, """ + unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText(), factor3, offset3, remove_mean3) i += 1 elif not (filter1 == '' or filter1==' ' or filter1list==[]): for item1 in filter1list: sql = r""" select """ + unicode(self.xcol_ComboBox_3.currentText()) + """, """ + unicode(self.ycol_ComboBox_3.currentText()) + """ from """ + unicode(self.table_ComboBox_3.currentText()) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' order by """ + unicode(self.xcol_ComboBox_3.currentText()) self.plabels[i] = unicode(item1.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText(), factor3, offset3, remove_mean3) i += 1 elif not (filter2 == '' or filter2==' ' or filter2list==[]): for item2 in filter2list: sql = r""" select """ + unicode(self.xcol_ComboBox_3.currentText()) + """, """ + unicode(self.ycol_ComboBox_3.currentText()) + """ from """ + unicode(self.table_ComboBox_3.currentText()) + """ where """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol_ComboBox_3.currentText()) self.plabels[i] = unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText(), factor3, offset3, remove_mean3) i += 1 else: sql = r""" select """ + unicode(self.xcol_ComboBox_3.currentText()) + """, """ + unicode(self.ycol_ComboBox_3.currentText()) + """ from """ + unicode(self.table_ComboBox_3.currentText()) + """ order by """ + unicode(self.xcol_ComboBox_3.currentText()) self.plabels[i] = unicode(self.ycol_ComboBox_3.currentText())+""", """+unicode(self.table_ComboBox_3.currentText()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText(), factor3, offset3, remove_mean3) i += 1 #rs.close() # close the cursor myconnection.closedb() # close the database self.xaxis_formatters = (self.axes.xaxis.get_major_formatter(), self.axes.xaxis.get_major_locator()) self.axes.set_title(self.ms.settingsdict['custplot_title']) self.axes.set_xlabel(self.ms.settingsdict['custplot_xtitle']) self.axes.set_ylabel(self.ms.settingsdict['custplot_ytitle']) self.drawn = True self.refreshPlot() QtGui.QApplication.restoreOverrideCursor()#now this long process is done and the cursor is back as normal def createsingleplotobject(self,sql,i,My_format,curs,plottype='line', factor=1.0, offset=0.0, remove_mean=False): rs = curs.execute(sql) #Send SQL-syntax to cursor recs = rs.fetchall() # All data are stored in recs # late fix for xy-plots #Transform data to a numpy.recarray try: table = np.array(recs, dtype=My_format) #NDARRAY table2=table.view(np.recarray) # RECARRAY transform the 2 cols into callable objects FlagTimeXY = 'time' myTimestring = list(table2.date_time) numtime=datestr2num(myTimestring) #conv list of strings to numpy.ndarray of floats except Exception, e: utils.MessagebarAndLog.info(log_msg=u"Customplot, transforming to recarray with date_time as x-axis failed, msg: " + utils.returnunicode(str(e))) table = np.array(recs, dtype=[('numx', float), ('values', float)]) #NDARRAY #define a format for xy-plot (to use if not datetime on x-axis) table2=table.view(np.recarray) # RECARRAY transform the 2 cols into callable objects FlagTimeXY = 'XY' numtime = list(table2.numx) # from version 0.2 there is a possibility to make discontinuous plot if timestep bigger than maxtstep if self.spnmaxtstep.value() > 0: # if user selected a time step bigger than zero than thre may be discontinuous plots pos = np.where(np.abs(np.diff(numtime)) >= self.spnmaxtstep.value())[0] numtime[pos] = np.nan table2.values[pos] = np.nan if plottype == "marker": MarkVar = 'o' elif plottype in ("line","frequency"): MarkVar = '-' elif plottype == "line and cross": MarkVar = '+-' else: MarkVar = 'o-' if FlagTimeXY == "time" and plottype == "frequency": table2.values[:] = self.calc_frequency(table2)[:] if remove_mean: table2.values[:] = utils.remove_mean_from_nparray(table2.values)[:] table2.values[:] = utils.scale_nparray(table2.values, factor, offset)[:] if FlagTimeXY == "time" and plottype == "step-pre": self.p[i], = self.axes.plot_date(numtime, table2.values, drawstyle='steps-pre', linestyle='-', marker='None',c=np.random.rand(3,1),label=self.plabels[i])# 'steps-pre' best for precipitation and flowmeters, optional types are 'steps', 'steps-mid', 'steps-post' elif FlagTimeXY == "time" and plottype == "step-post": self.p[i], = self.axes.plot_date(numtime, table2.values, drawstyle='steps-post', linestyle='-', marker='None',c=np.random.rand(3,1),label=self.plabels[i]) elif FlagTimeXY == "time" and plottype == "line and cross": self.p[i], = self.axes.plot_date(numtime, table2.values, MarkVar,markersize = 6, label=self.plabels[i]) elif FlagTimeXY == "time" and plottype == "frequency": try: self.p[i], = self.axes.plot_date(numtime, table2.values, MarkVar,markersize = 6, label='frequency '+str(self.plabels[i])) self.plabels[i]='frequency '+str(self.plabels[i]) except: self.p[i], = self.axes.plot_date(np.array([]),np.array([]), MarkVar,markersize = 6, label='frequency '+str(self.plabels[i])) self.plabels[i]='frequency '+str(self.plabels[i]) elif FlagTimeXY == "time": self.p[i], = self.axes.plot_date(numtime, table2.values, MarkVar,label=self.plabels[i]) elif FlagTimeXY == "XY" and plottype == "step-pre": self.p[i], = self.axes.plot(numtime, table2.values, drawstyle='steps-pre', linestyle='-', marker='None',c=np.random.rand(3,1),label=self.plabels[i]) elif FlagTimeXY == "XY" and plottype == "step-post": self.p[i], = self.axes.plot(numtime, table2.values, drawstyle='steps-post', linestyle='-', marker='None',c=np.random.rand(3,1),label=self.plabels[i]) elif FlagTimeXY == "XY" and plottype == "line and cross": self.p[i], = self.axes.plot(numtime, table2.values, MarkVar,markersize = 6, label=self.plabels[i]) else: self.p[i], = self.axes.plot(numtime, table2.values, MarkVar,label=self.plabels[i])
class MainWindow(QtGui.QMainWindow, Ui_MainWindow): def __init__(self, parent = None): #QtGui.QMainWindow.__init__(self, parent)#the line below is for some reason preferred super(MainWindow, self).__init__(parent)#for some reason this is supposed to be better than line above #QDialog.__init__( self ) #if not working with an application with mainwindow #self.iface = iface #self=Ui_MainWindow()#new self.setupUi( self )#due to initialisation of Ui_MainWindow instance self.initUI() self.maxtstep = 0 #self.database = '' #self.table1 = '' #self.database_pyqt4provider = QtSql.QSqlDatabase.addDatabase("QSQLITE","db1") def initUI(self): self.table_ComboBox_1.clear() self.table_ComboBox_2.clear() self.table_ComboBox_3.clear() for i in range (1,3): self.clearthings(1) self.quit_Qaction.triggered.connect(self.quit_app) self.actionAbout.triggered.connect(self.about) self.selectDB_QAction.triggered.connect(self.selectFile) self.selectDB_QPushButton.clicked.connect(self.selectFile) # whenever Time Series Table is changed, the column-combobox must be updated and TableCheck must be performed (function partial due to problems with currentindexChanged and Combobox) #self.connect(self.table_ComboBox_1, QtCore.SIGNAL("currentIndexChanged(int)"), partial(self.Table1Changed))#currentIndexChanged caused unnecessary signals when scrolling in combobox self.connect(self.table_ComboBox_1, QtCore.SIGNAL("activated(int)"), partial(self.Table1Changed)) self.connect(self.Filter1_ComboBox_1, QtCore.SIGNAL("activated(int)"), partial(self.Filter1_1Changed)) self.connect(self.Filter2_ComboBox_1, QtCore.SIGNAL("activated(int)"), partial(self.Filter2_1Changed)) self.connect(self.table_ComboBox_2, QtCore.SIGNAL("activated(int)"), partial(self.Table2Changed)) self.connect(self.Filter1_ComboBox_2, QtCore.SIGNAL("activated(int)"), partial(self.Filter1_2Changed)) self.connect(self.Filter2_ComboBox_2, QtCore.SIGNAL("activated(int)"), partial(self.Filter2_2Changed)) self.connect(self.table_ComboBox_3, QtCore.SIGNAL("activated(int)"), partial(self.Table3Changed)) self.connect(self.Filter1_ComboBox_3, QtCore.SIGNAL("activated(int)"), partial(self.Filter1_3Changed)) self.connect(self.Filter2_ComboBox_3, QtCore.SIGNAL("activated(int)"), partial(self.Filter2_3Changed)) self.PlotChart_QPushButton.clicked.connect(self.drawPlot) self.Redraw_pushButton.clicked.connect( self.refreshPlot ) # Create a plot window with one single subplot self.figure = plt.figure() self.axes = self.figure.add_subplot( 111 ) self.canvas = FigureCanvas( self.figure ) self.mpltoolbar = NavigationToolbar( self.canvas, self.widgetPlot ) lstActions = self.mpltoolbar.actions() self.mpltoolbar.removeAction( lstActions[ 7 ] ) self.layoutplot.addWidget( self.canvas ) self.layoutplot.addWidget( self.mpltoolbar ) # Search for saved settings and load as preset values self.settings = QtCore.QSettings('foo','foo') self.readsettings() self.show() def quit_app(self): self.close() #QtSql.QSqlDatabase.removeDatabase("db1") QtCore.QCoreApplication.instance().quit() def drawPlot(self): QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))#show the user this may take a long time... self.storesettings() #db, table, x-col and y-col are saved as default values when user clicks 'plot chart' self.axes.clear() My_format = [('date_time', datetime.datetime), ('values', float)] #Define (with help from function datetime) a good format for numpy array conn = sqlite.connect(np.unicode(self.selected_database_QLineEdit.text()),detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)#should be cross-platform # skapa en cursor curs = conn.cursor() i = 0 nop=0# nop=number of plots self.p=[] self.plabels=[] if not (self.table1 == '' or self.table1==' ') and not (self.xcol1== '' or self.xcol1==' ') and not (self.ycol1== '' or self.ycol1==' '): #if anything is to be plotted from tab 1 self.maxtstep = self.spnmaxtstep.value() # if user selected a time step bigger than zero than thre may be discontinuous plots plottable1='y' filter1 = np.unicode(self.Filter1_ComboBox_1.currentText()) filter1list = self.Filter1_QListWidget_1.selectedItems() filter2 = np.unicode(self.Filter2_ComboBox_1.currentText()) filter2list= self.Filter2_QListWidget_1.selectedItems() nop += max(len(filter1list),1)*max(len(filter2list),1) #self.p= [None]*nop#list for plot objects self.p.extend([None]*nop)#list for plot objects self.plabels.extend([None]*nop)# List for plot labels while i < len(self.p): if not (filter1 == '' or filter1==' ') and not (filter2== '' or filter2==' '): for item1 in filter1list: for item2 in filter2list: sql = r""" select """ + np.unicode(self.xcol_ComboBox_1.currentText()) + """, """ + np.unicode(self.ycol_ComboBox_1.currentText()) + """ from """ + np.unicode(self.table_ComboBox_1.currentText()) + """ where """ + filter1 + """='""" + np.unicode(item1.text())+ """' and """ + filter2 + """='""" + np.unicode(item2.text())+ """' order by """ + np.unicode(self.xcol_ComboBox_1.currentText()) self.plabels[i] = np.unicode(item1.text()) + """, """ + np.unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_1.currentText()) i += 1 elif not (filter1 == '' or filter1==' '): for item1 in filter1list: sql = r""" select """ + np.unicode(self.xcol_ComboBox_1.currentText()) + """, """ + np.unicode(self.ycol_ComboBox_1.currentText()) + """ from """ + np.unicode(self.table_ComboBox_1.currentText()) + """ where """ + filter1 + """='""" + np.unicode(item1.text())+ """' order by """ + np.unicode(self.xcol_ComboBox_1.currentText()) self.plabels[i] = np.unicode(item1.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_1.currentText()) i += 1 elif not (filter2 == '' or filter2==' '): for item2 in filter2list: sql = r""" select """ + np.unicode(self.xcol_ComboBox_1.currentText()) + """, """ + np.unicode(self.ycol_ComboBox_1.currentText()) + """ from """ + np.unicode(self.table_ComboBox_1.currentText()) + """ where """ + filter2 + """='""" + np.unicode(item2.text())+ """' order by """ + np.unicode(self.xcol_ComboBox_1.currentText()) self.plabels[i] = np.unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_1.currentText()) i += 1 else: sql = r""" select """ + np.unicode(self.xcol_ComboBox_1.currentText()) + """, """ + np.unicode(self.ycol_ComboBox_1.currentText()) + """ from """ + np.unicode(self.table_ComboBox_1.currentText()) + """ order by """ + np.unicode(self.xcol_ComboBox_1.currentText()) self.plabels[i] = np.unicode(self.ycol_ComboBox_1.currentText())+""", """+np.unicode(self.table_ComboBox_1.currentText()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_1.currentText()) i += 1 if not (self.table2 == '' or self.table2==' ') and not (self.xcol2== '' or self.xcol2==' ') and not (self.ycol2== '' or self.ycol2==' '):#if anything is to be plotted from tab 2 self.maxtstep = self.spnmaxtstep.value() # if user selected a time step bigger than zero than thre may be discontinuous plots plottable2='y' filter1 = np.unicode(self.Filter1_ComboBox_2.currentText()) filter1list = self.Filter1_QListWidget_2.selectedItems() filter2 = np.unicode(self.Filter2_ComboBox_2.currentText()) filter2list= self.Filter2_QListWidget_2.selectedItems() nop =+ max(len(filter1list),1)*max(len(filter2list),1) self.p.extend([None]*nop)#list for plot objects self.plabels.extend([None]*nop)# List for plot labels while i < len(self.p): if not (filter1 == '' or filter1==' ') and not (filter2== '' or filter2==' '): for item1 in filter1list: for item2 in filter2list: sql = r""" select """ + np.unicode(self.xcol2) + """, """ + np.unicode(self.ycol2) + """ from """ + np.unicode(self.table2) + """ where """ + filter1 + """='""" + np.unicode(item1.text())+ """' and """ + filter2 + """='""" + np.unicode(item2.text())+ """' order by """ + np.unicode(self.xcol2) self.plabels[i] = np.unicode(item1.text()) + """, """ + np.unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText()) i += 1 elif not (filter1 == '' or filter1==' '): for item1 in filter1list: sql = r""" select """ + np.unicode(self.xcol2) + """, """ + np.unicode(self.ycol2) + """ from """ + np.unicode(self.table2) + """ where """ + filter1 + """='""" + np.unicode(item1.text())+ """' order by """ + np.unicode(self.xcol2) self.plabels[i] = np.unicode(item1.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText()) i += 1 elif not (filter2 == '' or filter2==' '): for item2 in filter2list: sql = r""" select """ + np.unicode(self.xcol2) + """, """ + np.unicode(self.ycol2) + """ from """ + np.unicode(self.table2) + """ where """ + filter2 + """='""" + np.unicode(item2.text())+ """' order by """ + np.unicode(self.xcol2) self.plabels[i] = np.unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText()) i += 1 else: sql = r""" select """ + np.unicode(self.xcol2) + """, """ + np.unicode(self.ycol2) + """ from """ + np.unicode(self.table2) + """ order by """ + np.unicode(self.xcol2) self.plabels[i] = np.unicode(self.ycol2)+""", """+np.unicode(self.table2) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText()) i += 1 if not (self.table3 == '' or self.table3==' ') and not (self.xcol3== '' or self.xcol3==' ') and not (self.ycol3== '' or self.ycol3==' '):#if anything is to be plotted from tab 3 self.maxtstep = self.spnmaxtstep.value() # if user selected a time step bigger than zero than thre may be discontinuous plots plottable3='y' filter1 = np.unicode(self.Filter1_ComboBox_3.currentText()) filter1list = self.Filter1_QListWidget_3.selectedItems() filter2 = np.unicode(self.Filter2_ComboBox_3.currentText()) filter2list= self.Filter2_QListWidget_3.selectedItems() nop =+ max(len(filter1list),1)*max(len(filter2list),1) self.p.extend([None]*nop)#list for plot objects self.plabels.extend([None]*nop)# List for plot labels while i < len(self.p): if not (filter1 == '' or filter1==' ') and not (filter2== '' or filter2==' '): for item1 in filter1list: for item2 in filter2list: sql = r""" select """ + np.unicode(self.xcol3) + """, """ + np.unicode(self.ycol3) + """ from """ + np.unicode(self.table3) + """ where """ + filter1 + """='""" + np.unicode(item1.text())+ """' and """ + filter2 + """='""" + np.unicode(item2.text())+ """' order by """ + np.unicode(self.xcol3) self.plabels[i] = np.unicode(item1.text()) + """, """ + np.unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText()) i += 1 elif not (filter1 == '' or filter1==' '): for item1 in filter1list: sql = r""" select """ + np.unicode(self.xcol3) + """, """ + np.unicode(self.ycol3) + """ from """ + np.unicode(self.table3) + """ where """ + filter1 + """='""" + np.unicode(item1.text())+ """' order by """ + np.unicode(self.xcol3) self.plabels[i] = np.unicode(item1.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText()) i += 1 elif not (filter2 == '' or filter2==' '): for item2 in filter2list: sql = r""" select """ + np.unicode(self.xcol3) + """, """ + np.unicode(self.ycol3) + """ from """ + np.unicode(self.table3) + """ where """ + filter2 + """='""" + np.unicode(item2.text())+ """' order by """ + np.unicode(self.xcol3) self.plabels[i] = np.unicode(item2.text()) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText()) i += 1 else: sql = r""" select """ + np.unicode(self.xcol3) + """, """ + np.unicode(self.ycol3) + """ from """ + np.unicode(self.table3) + """ order by """ + np.unicode(self.xcol3) self.plabels[i] = np.unicode(self.ycol3)+""", """+np.unicode(self.table3) self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText()) i += 1 #rs.close() # close the cursor conn.close() # close the database self.refreshPlot() QtGui.QApplication.restoreOverrideCursor()#now this long process is done and the cursor is back as normal def createsingleplotobject(self,sql,i,My_format,curs,plottype='line'): rs = curs.execute(sql) #Send SQL-syntax to cursor recs = rs.fetchall() # All data are stored in recs # late fix for xy-plots My_format2 = [('numx', float), ('values', float)]#define a format for xy-plot (to use if not datetime on x-axis) #Transform data to a numpy.recarray try: table = np.array(recs, dtype=My_format) #NDARRAY table2=table.view(np.recarray) # RECARRAY transform the 2 cols into callable objects myTimestring = [] #LIST FlagTimeXY = 'time' j = 0 for row in table2: myTimestring.append(table2.date_time[j]) j = j + 1 numtime=datestr2num(myTimestring) #conv list of strings to numpy.ndarray of floats except: table = np.array(recs, dtype=My_format2) #NDARRAY table2=table.view(np.recarray) # RECARRAY transform the 2 cols into callable objects myXYstring = [] #LIST FlagTimeXY = 'XY' j = 0 for row in table2: # myXYstring.append(table2.numx[j]) j = j + 1 numtime = myXYstring # from version 0.2 there is a possibility to make discontinuous plot if timestep bigger than maxtstep if self.maxtstep > 0: # if user selected a time step bigger than zero than thre may be discontinuous plots pos = np.where(np.abs(np.diff(numtime)) >= self.maxtstep)[0] numtime[pos] = np.nan table2.values[pos] = np.nan if plottype == "marker": MarkVar = 'o' elif plottype == "line": MarkVar = '-' elif plottype == "line and cross": MarkVar = '+-' else: MarkVar = 'o-' if FlagTimeXY == "time" and plottype == "step-pre": self.p[i], = self.axes.plot_date(numtime, table2.values, drawstyle='steps-pre', linestyle='-', marker='None',c=np.random.rand(3,1),label=self.plabels[i])# 'steps-pre' best for precipitation and flowmeters, optional types are 'steps', 'steps-mid', 'steps-post' elif FlagTimeXY == "time" and plottype == "step-post": self.p[i], = self.axes.plot_date(numtime, table2.values, drawstyle='steps-post', linestyle='-', marker='None',c=np.random.rand(3,1),label=self.plabels[i]) elif FlagTimeXY == "time" and plottype == "line and cross": self.p[i], = self.axes.plot_date(numtime, table2.values, MarkVar,markersize = 6, label=self.plabels[i]) elif FlagTimeXY == "time": self.p[i], = self.axes.plot_date(numtime, table2.values, MarkVar,label=self.plabels[i]) elif FlagTimeXY == "XY" and plottype == "step-pre": self.p[i], = self.axes.plot(numtime, table2.values, drawstyle='steps-pre', linestyle='-', marker='None',c=np.random.rand(3,1),label=self.plabels[i]) elif FlagTimeXY == "XY" and plottype == "step-post": self.p[i], = self.axes.plot(numtime, table2.values, drawstyle='steps-post', linestyle='-', marker='None',c=np.random.rand(3,1),abel=self.plabels[i]) elif FlagTimeXY == "XY" and plottype == "line and cross": self.p[i], = self.axes.plot(numtime, table2.values, MarkVar,markersize = 6, label=self.plabels[i]) else: self.p[i], = self.axes.plot(numtime, table2.values, MarkVar,label=self.plabels[i]) def refreshPlot( self ): self.axes.legend_=None #self.axes.clear() #self.plabels = ('Rb1103','Rb1104')#debugging #print self.plabels #debug datemin = self.spnMinX.dateTime().toPyDateTime() datemax = self.spnMaxX.dateTime().toPyDateTime() if datemin == datemax: #xaxis-limits pass else: self.axes.set_xlim(min(datemin, datemax),max(datemin, datemax)) if self.spnMinY.value() == self.spnMaxY.value(): #yaxis-limits pass else: self.axes.set_ylim(min(self.spnMaxY.value(), self.spnMinY.value()),max(self.spnMaxY.value(), self.spnMinY.value())) self.axes.yaxis.set_major_formatter(tick.ScalarFormatter(useOffset=False, useMathText=False))#yaxis-format self.figure.autofmt_xdate()#xaxis-format self.axes.grid(self.Grid_checkBox.isChecked() )#grid if not self.title_QLineEdit.text()=='':#title self.axes.set_title(self.title_QLineEdit.text()) if not self.xtitle_QLineEdit.text()=='':#xaxis label self.axes.set_xlabel(self.xtitle_QLineEdit.text()) if not self.ytitle_QLineEdit.text()=='':#yaxis label self.axes.set_ylabel(self.ytitle_QLineEdit.text()) for label in self.axes.xaxis.get_ticklabels(): label.set_fontsize(10) for label in self.axes.yaxis.get_ticklabels(): label.set_fontsize(10) # finally, the legend if self.Legend_checkBox.isChecked(): if (self.spnLegX.value() ==0 ) and (self.spnLegY.value() ==0): leg = self.axes.legend(self.p, self.plabels) else: leg = self.axes.legend(self.p, self.plabels, bbox_to_anchor=(self.spnLegX.value(),self.spnLegY.value()),loc=10) leg.draggable(state=True) frame = leg.get_frame() # the matplotlib.patches.Rectangle instance surrounding the legend frame.set_facecolor('1') # set the frame face color to white frame.set_fill(False) # set the frame face color to white for t in leg.get_texts(): t.set_fontsize(10) # the legend text fontsize else: self.axes.legend_=None self.figure.autofmt_xdate() self.canvas.draw() def selectFile(self): #Open a dialog to locate the sqlite file and some more... try: from PyQt4.QtCore import QString message=QtCore.QString.fromLocal8Bit("Select database:") except ImportError: message = str("Select database:") path = QtGui.QFileDialog.getOpenFileName(None,message,"*.sqlite") if path: self.database = path # To make possible cancel the FileDialog and continue loading a predefined db self.openDBFile() def openDBFile( self ): # Open the SpatiaLite file to extract info about tables if os.path.isfile( np.unicode( self.database ) ): self.selected_database_QLineEdit.setText(self.database) self.table_ComboBox_1.clear() self.table_ComboBox_2.clear() self.table_ComboBox_3.clear() for i in range (1,3): self.clearthings(1) conn = sqlite.connect( np.unicode(self.database) ) cursor = conn.cursor() rs=cursor.execute(r"""SELECT tbl_name FROM sqlite_master WHERE (type='table' or type='view') and not (name in('geom_cols_ref_sys', 'geometry_columns', 'geometry_columns_time', 'spatial_ref_sys', 'spatialite_history', 'vector_layers', 'views_geometry_columns', 'virts_geometry_columns', 'geometry_columns_auth', 'geometry_columns_fields_infos', 'geometry_columns_statistics', 'sql_statements_log', 'layer_statistics', 'sqlite_sequence', 'sqlite_stat1' , 'views_layer_statistics', 'virts_layer_statistics', 'vector_layers_auth', 'vector_layers_field_infos', 'vector_layers_statistics', 'views_geometry_columns_auth', 'views_geometry_columns_field_infos', 'views_geometry_columns_statistics', 'virts_geometry_columns_auth', 'virts_geometry_columns_field_infos', 'virts_geometry_columns_statistics' , 'geometry_columns', 'spatialindex', 'SpatialIndex')) ORDER BY tbl_name""" ) #SQL statement to get the relevant tables in the spatialite database #self.dbTables = {} self.table_ComboBox_1.addItem('') self.table_ComboBox_2.addItem('') self.table_ComboBox_3.addItem('') for row in cursor: self.table_ComboBox_1.addItem(row[0]) self.table_ComboBox_2.addItem(row[0]) self.table_ComboBox_3.addItem(row[0]) rs.close() conn.close() def clearthings(self,tabno=1): #clear xcol,ycol,fukter1,filter2 xcolcombobox = 'xcol_ComboBox_' + str(tabno) ycolcombobox = 'ycol_ComboBox_' + str(tabno) filter1combobox = 'Filter1_ComboBox_' + str(tabno) filter2combobox = 'Filter2_ComboBox_' + str(tabno) filter1qlistwidget = 'Filter1_QListWidget_' + str(tabno) filter2qlistwidget = 'Filter2_QListWidget_' + str(tabno) getattr(self,xcolcombobox).clear() getattr(self,ycolcombobox).clear() getattr(self,filter1combobox).clear() getattr(self,filter2combobox).clear() getattr(self,filter1qlistwidget).clear() getattr(self,filter2qlistwidget).clear() def Table1Changed(self): #This method is called whenever table1 is changed # First, update combobox with columns self.clearthings(1) self.table1 = np.unicode(self.table_ComboBox_1.currentText()) self.PopulateComboBox('xcol_ComboBox_1', self.table_ComboBox_1.currentText()) # GeneralNote: For some reason it is not possible to send currentText with the SIGNAL-trigger self.PopulateComboBox('ycol_ComboBox_1', self.table_ComboBox_1.currentText()) # See GeneralNote self.PopulateComboBox('Filter1_ComboBox_1', self.table_ComboBox_1.currentText()) # See GeneralNote self.PopulateComboBox('Filter2_ComboBox_1', self.table_ComboBox_1.currentText()) # See GeneralNote def Table2Changed(self): #This method is called whenever table2 is changed # First, update combobox with columns self.clearthings(2) self.table2 = np.unicode(self.table_ComboBox_2.currentText()) self.PopulateComboBox('xcol_ComboBox_2', self.table_ComboBox_2.currentText()) # GeneralNote: For some reason it is not possible to send currentText with the SIGNAL-trigger self.PopulateComboBox('ycol_ComboBox_2', self.table_ComboBox_2.currentText()) # See GeneralNote self.PopulateComboBox('Filter1_ComboBox_2', self.table_ComboBox_2.currentText()) # See GeneralNote self.PopulateComboBox('Filter2_ComboBox_2', self.table_ComboBox_2.currentText()) # See GeneralNote def Table3Changed(self): #This method is called whenever table3 is changed # First, update combobox with columns self.clearthings(3) self.table3 = np.unicode(self.table_ComboBox_3.currentText()) self.PopulateComboBox('xcol_ComboBox_3', self.table_ComboBox_3.currentText()) # GeneralNote: For some reason it is not possible to send currentText with the SIGNAL-trigger self.PopulateComboBox('ycol_ComboBox_3', self.table_ComboBox_3.currentText()) # See GeneralNote self.PopulateComboBox('Filter1_ComboBox_3', self.table_ComboBox_3.currentText()) # See GeneralNote self.PopulateComboBox('Filter2_ComboBox_3', self.table_ComboBox_3.currentText()) # See GeneralNote def PopulateComboBox(self, comboboxname='', table=None): """This method fills comboboxes with columns for selected tool and table""" columns = self.LoadColumnsFromTable(table) # Load all columns into a list 'columns' if len(columns)>0: # Transfer information from list 'columns' to the combobox getattr(self, comboboxname).addItem('') for columnName in columns: getattr(self, comboboxname).addItem(columnName) # getattr is to combine a function and a string to a combined function def LoadColumnsFromTable(self, table=''): """ This method returns a list with all the columns in the table""" if len(table)>0 and len(self.database)>0: # Should not be needed since the function never should be called without existing table... conn = sqlite.connect(np.unicode(self.database)) curs = conn.cursor() sql = r"""SELECT * FROM '""" sql += np.unicode(table) sql += """'""" rs = curs.execute(sql) #Send the SQL statement to get the columns in the table columns = {} columns = [tuple[0] for tuple in curs.description] rs.close() conn.close() else: #QMessageBox.information(None,"info","no table is loaded") # DEBUGGING columns = {} return columns # This method returns a list with all the columns in the table def Filter1_1Changed(self): self.Filter1_QListWidget_1.clear() if not self.Filter1_ComboBox_1.currentText()=='': self.PopulateFilterList(self.table1,'Filter1_QListWidget_1', self.Filter1_ComboBox_1.currentText()) # For some reason it is not possible to send currentText with the SIGNAL-trigger def Filter2_1Changed(self): self.Filter2_QListWidget_1.clear() if not self.Filter2_ComboBox_1.currentText()=='': self.PopulateFilterList(self.table1,'Filter2_QListWidget_1', self.Filter2_ComboBox_1.currentText()) # For some reason it is not possible to send currentText with the SIGNAL-trigger def Filter1_2Changed(self): self.Filter1_QListWidget_2.clear() if not self.Filter1_ComboBox_2.currentText()=='': self.PopulateFilterList(self.table2,'Filter1_QListWidget_2', self.Filter1_ComboBox_2.currentText()) def Filter2_2Changed(self): self.Filter2_QListWidget_2.clear() if not self.Filter2_ComboBox_2.currentText()=='': self.PopulateFilterList(self.table2,'Filter2_QListWidget_2', self.Filter2_ComboBox_2.currentText()) def Filter1_3Changed(self): self.Filter1_QListWidget_3.clear() if not self.Filter1_ComboBox_3.currentText()=='': self.PopulateFilterList(self.table3,'Filter1_QListWidget_3', self.Filter1_ComboBox_3.currentText()) def Filter2_3Changed(self): self.Filter2_QListWidget_3.clear() if not self.Filter2_ComboBox_3.currentText()=='': self.PopulateFilterList(self.table3,'Filter2_QListWidget_3', self.Filter2_ComboBox_3.currentText()) def PopulateFilterList(self, table, QListWidgetname='', filtercolumn=None): sql = "select distinct " + np.unicode(filtercolumn) + " from " + table + " order by " + np.unicode(filtercolumn) list_data=sql_load_fr_db(self.database, sql) for post in list_data: item = QtGui.QListWidgetItem(np.unicode(post[0])) getattr(self, QListWidgetname).addItem(item) def storesettings(self): self.settings.setValue('db',self.database) self.settings.setValue('table1', self.table_ComboBox_1.currentText()) self.settings.setValue('xcol1', self.xcol_ComboBox_1.currentText()) self.settings.setValue('ycol1', self.ycol_ComboBox_1.currentText()) self.table1=self.table_ComboBox_1.currentText() self.xcol1=self.xcol_ComboBox_1.currentText() self.ycol1=self.ycol_ComboBox_1.currentText() self.settings.setValue('table2', self.table_ComboBox_2.currentText()) self.settings.setValue('xcol2', self.xcol_ComboBox_2.currentText()) self.settings.setValue('ycol2', self.ycol_ComboBox_2.currentText()) self.table2=self.table_ComboBox_2.currentText() self.xcol2=self.xcol_ComboBox_2.currentText() self.ycol2=self.ycol_ComboBox_2.currentText() self.settings.setValue('table3', self.table_ComboBox_3.currentText()) self.settings.setValue('xcol3', self.xcol_ComboBox_3.currentText()) self.settings.setValue('ycol3', self.ycol_ComboBox_3.currentText()) self.table3=self.table_ComboBox_3.currentText() self.xcol3=self.xcol_ComboBox_3.currentText() self.ycol3=self.ycol_ComboBox_3.currentText() def readsettings(self): #only used when application starts, to load default values from last run try: l1 = len((self.settings.value('db')).toString()) except: l1 = len(str(self.settings.value('db'))) if l1>0: self.database = self.settings.value('db',type='QString') #print self.database self.openDBFile() try:#table1 self.table1 = self.settings.value('table1').toString() notfound=0 i=0 while notfound==0: # Loop until the last selected table1 is found self.table_ComboBox_1.setCurrentIndex(i) if self.table_ComboBox_1.currentText() == self.table1: #The index count stops when last selected table is found notfound=1 self.Table1Changed() # Fill xcol,ycol,filter1,filter2 comboboxes with info from selected table try:#xcol1 self.xcol1 = self.settings.value('xcol1').toString() notfound2=0 j=0 while notfound2==0: # loop until the last selected tscolumn is found self.xcol_ComboBox_1.setCurrentIndex(j) if self.xcol_ComboBox_1.currentText() == self.xcol1: # index count stops when column found notfound2=1 elif j> len(self.xcol_ComboBox_1): notfound2=1 j = j + 1 except: print('no stored data for xcolumn') try:#ycol1 self.ycol1 = self.settings.value('ycol1').toString() notfound2=0 j=0 while notfound2==0: # loop until the last selected tscolumn is found self.ycol_ComboBox_1.setCurrentIndex(j) if self.ycol_ComboBox_1.currentText() == self.ycol1: # index count stops when column found notfound2=1 elif j> len(self.ycol_ComboBox_1): notfound2=1 j = j + 1 except: print('no stored data for ycolumn') elif i> len(self.table_ComboBox_1): notfound=1 i = i + 1 except: print('nothing to be done for table1') try:#table2 self.table2 = self.settings.value('table2').toString() notfound=0 i=0 while notfound==0: # Loop until the last selected table2 is found self.table_ComboBox_2.setCurrentIndex(i) if self.table_ComboBox_2.currentText() == self.table2: #The index count stops when last selected table is found notfound=1 self.Table2Changed() # Fill xcol,ycol,filter1,filter2 comboboxes with info from selected table try:#xcol2 self.xcol2 = self.settings.value('xcol2').toString() notfound2=0 j=0 while notfound2==0: # loop until the last selected tscolumn is found self.xcol_ComboBox_2.setCurrentIndex(j) if self.xcol_ComboBox_2.currentText() == self.xcol2: # index count stops when column found notfound2=1 elif j> len(self.xcol_ComboBox_2): notfound2=1 j = j + 1 except: print('no stored data for xcolumn') try:#ycol2 self.ycol2 = self.settings.value('ycol2').toString() notfound2=0 j=0 while notfound2==0: # loop until the last selected tscolumn is found self.ycol_ComboBox_2.setCurrentIndex(j) if self.ycol_ComboBox_2.currentText() == self.ycol2: # index count stops when column found notfound2=1 elif j> len(self.ycol_ComboBox_2): notfound2=1 j = j + 1 except: print('no stored data for ycolumn') elif i> len(self.table_ComboBox_2): notfound=1 i = i + 1 except: print('nothing to be done for table2') try:#table3 self.table3 = self.settings.value('table3').toString() notfound=0 i=0 while notfound==0: # Loop until the last selected table2 is found self.table_ComboBox_3.setCurrentIndex(i) if self.table_ComboBox_3.currentText() == self.table3: #The index count stops when last selected table is found notfound=1 self.Table3Changed() # Fill xcol,ycol,filter1,filter2 comboboxes with info from selected table try:#xcol3 self.xcol3 = self.settings.value('xcol3').toString() notfound2=0 j=0 while notfound2==0: # loop until the last selected tscolumn is found self.xcol_ComboBox_3.setCurrentIndex(j) if self.xcol_ComboBox_3.currentText() == self.xcol3: # index count stops when column found notfound2=1 elif j> len(self.xcol_ComboBox_3): notfound2=1 j = j + 1 except: print('no stored data for xcolumn') try:#ycol3 self.ycol3 = self.settings.value('ycol3').toString() notfound2=0 j=0 while notfound2==0: # loop until the last selected tscolumn is found self.ycol_ComboBox_3.setCurrentIndex(j) if self.ycol_ComboBox_3.currentText() == self.ycol3: # index count stops when column found notfound2=1 elif j> len(self.ycol_ComboBox_3): notfound2=1 j = j + 1 except: print('no stored data for ycolumn') elif i> len(self.table_ComboBox_3): notfound=1 i = i + 1 except: print('nothing to be done for table3') def about(self): version = u'0.2.4' contact = u'*****@*****.**' web = u'http://sourceforge.net/projects/plotsqlite' TEXT = 'This is PlotSQLite - the Midvatten plot generator.\n\nVersion: ' + version + '\nContact: ' + contact + '\nMore info: ' + web QtGui.QMessageBox.information(None, "info", TEXT)