Exemple #1
0
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(
            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 = unicode(self.Filter1_ComboBox_1.currentText())
            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
            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 """ + 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())
                            i += 1
                elif not (filter1 == '' or filter1 == ' '):
                    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())
                        i += 1
                elif not (filter2 == '' or filter2 == ' '):
                    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())
                        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())
                    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 = unicode(self.Filter1_ComboBox_2.currentText())
            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
            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 """ + unicode(
                                self.xcol2
                            ) + """, """ + unicode(
                                self.ycol2
                            ) + """ from """ + unicode(
                                self.table2
                            ) + """ where """ + filter1 + """='""" + unicode(
                                item1.text()
                            ) + """' and """ + filter2 + """='""" + unicode(
                                item2.text()) + """' order by """ + unicode(
                                    self.xcol2)
                            self.plabels[i] = unicode(
                                item1.text()) + """, """ + 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 """ + unicode(
                            self.xcol2) + """, """ + unicode(
                                self.ycol2
                            ) + """ from """ + unicode(
                                self.table2
                            ) + """ where """ + filter1 + """='""" + unicode(
                                item1.text()) + """' order by """ + unicode(
                                    self.xcol2)
                        self.plabels[i] = 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 """ + unicode(
                            self.xcol2) + """, """ + unicode(
                                self.ycol2
                            ) + """ from """ + unicode(
                                self.table2
                            ) + """ where """ + filter2 + """='""" + unicode(
                                item2.text()) + """' order by """ + unicode(
                                    self.xcol2)
                        self.plabels[i] = unicode(item2.text())
                        self.createsingleplotobject(
                            sql, i, My_format, curs,
                            self.PlotType_comboBox_2.currentText())
                        i += 1
                else:
                    sql = r""" select """ + unicode(
                        self.xcol2) + """, """ + unicode(
                            self.ycol2) + """ from """ + unicode(
                                self.table2) + """ order by """ + unicode(
                                    self.xcol2)
                    self.plabels[i] = unicode(self.ycol2) + """, """ + 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 = unicode(self.Filter1_ComboBox_3.currentText())
            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
            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 """ + unicode(
                                self.xcol3
                            ) + """, """ + unicode(
                                self.ycol3
                            ) + """ from """ + unicode(
                                self.table3
                            ) + """ where """ + filter1 + """='""" + unicode(
                                item1.text()
                            ) + """' and """ + filter2 + """='""" + unicode(
                                item2.text()) + """' order by """ + unicode(
                                    self.xcol3)
                            self.plabels[i] = unicode(
                                item1.text()) + """, """ + 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 """ + unicode(
                            self.xcol3) + """, """ + unicode(
                                self.ycol3
                            ) + """ from """ + unicode(
                                self.table3
                            ) + """ where """ + filter1 + """='""" + unicode(
                                item1.text()) + """' order by """ + unicode(
                                    self.xcol3)
                        self.plabels[i] = 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 """ + unicode(
                            self.xcol3) + """, """ + unicode(
                                self.ycol3
                            ) + """ from """ + unicode(
                                self.table3
                            ) + """ where """ + filter2 + """='""" + unicode(
                                item2.text()) + """' order by """ + unicode(
                                    self.xcol3)
                        self.plabels[i] = unicode(item2.text())
                        self.createsingleplotobject(
                            sql, i, My_format, curs,
                            self.PlotType_comboBox_3.currentText())
                        i += 1
                else:
                    sql = r""" select """ + unicode(
                        self.xcol3) + """, """ + unicode(
                            self.ycol3) + """ from """ + unicode(
                                self.table3) + """ order by """ + unicode(
                                    self.xcol3)
                    self.plabels[i] = unicode(self.ycol3) + """, """ + 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',
                                        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',
                                        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])

    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...
        path = QtGui.QFileDialog.getOpenFileName(
            None, QtCore.QString.fromLocal8Bit("Select database:"), "*.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(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(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 = 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 = 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 = 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(unicode(self.database))
            curs = conn.cursor()
            sql = r"""SELECT * FROM '"""
            sql += 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 " + unicode(
            filtercolumn) + " from " + table + " order by " + unicode(
                filtercolumn)
        list_data = sql_load_fr_db(self.database, sql)
        for post in list_data:
            item = QtGui.QListWidgetItem(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)
Exemple #2
0
class NeuralNetworkWidget(QWidget, Ui_Widget):
    def __init__(self, plugin, parent=None):
        QWidget.__init__(self, parent)
        self.setupUi(self)

        self.plugin = plugin
        self.inputs = plugin.inputs
        self.settings = QSettings("NextGIS", "MOLUSCE")

        # init plot for learning curve
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.figure.suptitle(self.tr("Neural Network learning curve"))
        self.canvas = FigureCanvas(self.figure)
        self.mpltoolbar = NavigationToolbar(self.canvas, None)
        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.btnTrainNetwork.clicked.connect(self.trainNetwork)

        self.manageGui()

    def manageGui(self):
        self.spnNeigbourhood.setValue(
            int(self.settings.value("ui/ANN/neighborhood", 1)))
        self.spnLearnRate.setValue(
            float(self.settings.value("ui/ANN/learningRate", 0.1)))
        self.spnMaxIterations.setValue(
            int(self.settings.value("ui/ANN/maxIterations", 1000)))
        self.leTopology.setText(self.settings.value("ui/ANN/topology", "10"))
        self.spnMomentum.setValue(
            float(self.settings.value("ui/ANN/momentum", 0.05)))
        self.btnStop.setEnabled(False)

    def trainNetwork(self):
        if not utils.checkInputRasters(self.inputs):
            QMessageBox.warning(
                self.plugin, self.tr("Missed input data"),
                self.
                tr("Initial or final raster is not set. Please specify input data and try again"
                   ))
            return

        if not utils.checkFactors(self.inputs):
            QMessageBox.warning(
                self.plugin, self.tr("Missed input data"),
                self.
                tr("Factors rasters is not set. Please specify them and try again"
                   ))
            return

        if not utils.checkChangeMap(self.inputs):
            QMessageBox.warning(
                self.plugin, self.tr("Missed input data"),
                self.
                tr("Change map raster is not set. Please create it try again"))
            return

        if self.leTopology.text() == "":
            QMessageBox.warning(
                self.plugin, self.tr("Wrong network topology"),
                self.
                tr("Network topology is undefined. Please define it and try again"
                   ))
            return

        self.settings.setValue("ui/ANN/neighborhood",
                               self.spnNeigbourhood.value())
        self.settings.setValue("ui/ANN/learningRate",
                               self.spnLearnRate.value())
        self.settings.setValue("ui/ANN/maxIterations",
                               self.spnMaxIterations.value())
        self.settings.setValue("ui/ANN/topology", self.leTopology.text())
        self.settings.setValue("ui/ANN/momentum", self.spnMomentum.value())

        self.btnStop.setEnabled(True)
        self.btnTrainNetwork.setEnabled(False)

        self.plugin.logMessage(self.tr("Init ANN model"))

        model = MlpManager(ns=self.spnNeigbourhood.value())
        self.inputs["model"] = model
        model.createMlp(self.inputs["initial"],
                        self.inputs["factors"].values(),
                        self.inputs["changeMap"],
                        [int(n) for n in self.leTopology.text().split(" ")])

        self.plugin.logMessage(self.tr("Set training data"))
        model.setTrainingData(self.inputs["initial"],
                              self.inputs["factors"].values(),
                              self.inputs["changeMap"],
                              mode=self.inputs["samplingMode"],
                              samples=self.plugin.spnSamplesCount.value())

        model.setEpochs(self.spnMaxIterations.value())
        model.setValPercent(20)
        model.setLRate(self.spnLearnRate.value())
        model.setMomentum(self.spnMomentum.value())
        model.setContinueTrain()

        self.axes.cla()
        self.axes.grid(True)
        self.dataTrain = []
        self.dataVal = []
        self.plotTrain = self.axes.plot(self.dataTrain,
                                        linewidth=1,
                                        color="green",
                                        marker='o')[0]
        self.plotVal = self.axes.plot(
            self.dataVal,
            linewidth=1,
            color="red",
        )[0]
        leg = self.axes.legend(('Train', 'Validation'),
                               'upper right',
                               shadow=False)
        for t in leg.get_texts():
            t.set_fontsize('small')
        model.moveToThread(self.plugin.workThread)

        self.plugin.workThread.started.connect(model.startTrain)
        self.btnStop.clicked.connect(model.stopTrain)
        model.updateGraph.connect(self.__updateGraph)
        model.updateDeltaRMS.connect(self.__updateRMS)
        model.updateMinValErr.connect(self.__updateValidationError)
        model.updateKappa.connect(self.__updateKappa)
        model.processInterrupted.connect(self.__trainInterrupted)
        model.rangeChanged.connect(self.plugin.setProgressRange)
        model.updateProgress.connect(self.plugin.showProgress)
        model.errorReport.connect(self.plugin.logErrorReport)
        model.processFinished.connect(self.__trainFinished)
        model.processFinished.connect(self.plugin.workThread.quit)

        self.plugin.logMessage(self.tr("Start trainig ANN model"))
        self.plugin.workThread.start()

    def __trainFinished(self):
        model = self.inputs["model"]
        self.plugin.workThread.started.disconnect(model.startTrain)
        model.rangeChanged.disconnect(self.plugin.setProgressRange)
        model.updateProgress.disconnect(self.plugin.showProgress)
        model.errorReport.disconnect(self.plugin.logErrorReport)
        self.plugin.restoreProgressState()
        self.btnStop.setEnabled(False)
        self.btnTrainNetwork.setEnabled(True)
        self.plugin.logMessage(self.tr("ANN model trained"))

    def __trainInterrupted(self):
        self.plugin.workThread.quit()
        self.btnStop.setEnabled(False)
        self.btnTrainNetwork.setEnabled(True)
        self.plugin.logMessage(self.tr("ANN model training interrupted"))

    def __updateRMS(self, dRMS):
        self.leDeltaRMS.setText("%6.5f" % (dRMS))

    def __updateValidationError(self, error):
        self.leValidationError.setText("%6.5f" % (error))

    def __updateKappa(self, kappa):
        self.leKappa.setText("%6.5f" % (kappa))

    def __updateGraph(self, errTrain, errVal):
        self.dataTrain.append(errTrain)
        self.dataVal.append(errVal)

        ymin = min([min(self.dataTrain), min(self.dataVal)])
        ymax = max([max(self.dataTrain), max(self.dataVal)])

        self.axes.set_xbound(lower=0, upper=len(self.dataVal))
        self.axes.set_ybound(lower=ymin, upper=ymax)

        self.plotTrain.set_xdata(numpy.arange(len(self.dataTrain)))
        self.plotTrain.set_ydata(numpy.array(self.dataTrain))

        self.plotVal.set_xdata(numpy.arange(len(self.dataVal)))
        self.plotVal.set_ydata(numpy.array(self.dataVal))

        self.canvas.draw()
class NeuralNetworkWidget(QWidget, Ui_Widget):
  def __init__(self, plugin, parent=None):
    QWidget.__init__(self, parent)
    self.setupUi(self)

    self.plugin = plugin
    self.inputs = plugin.inputs
    self.settings = QSettings("NextGIS", "MOLUSCE")

    # init plot for learning curve
    self.figure = Figure()
    self.axes = self.figure.add_subplot(111)
    self.figure.suptitle(self.tr("Neural Network learning curve"))
    self.canvas = FigureCanvas(self.figure)
    self.mpltoolbar = NavigationToolbar(self.canvas, None)
    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.btnTrainNetwork.clicked.connect(self.trainNetwork)

    self.manageGui()

  def manageGui(self):
    self.spnNeigbourhood.setValue(int(self.settings.value("ui/ANN/neighborhood", 1)))
    self.spnLearnRate.setValue(float(self.settings.value("ui/ANN/learningRate", 0.1)))
    self.spnMaxIterations.setValue(int(self.settings.value("ui/ANN/maxIterations", 1000)))
    self.leTopology.setText(self.settings.value("ui/ANN/topology", "10"))
    self.spnMomentum.setValue(float(self.settings.value("ui/ANN/momentum", 0.05)))
    self.btnStop.setEnabled(False)

  def trainNetwork(self):
    if not utils.checkInputRasters(self.inputs):
      QMessageBox.warning(self.plugin,
                          self.tr("Missed input data"),
                          self.tr("Initial or final raster is not set. Please specify input data and try again")
                         )
      return

    if not utils.checkFactors(self.inputs):
      QMessageBox.warning(self.plugin,
                          self.tr("Missed input data"),
                          self.tr("Factors rasters is not set. Please specify them and try again")
                         )
      return

    if not utils.checkChangeMap(self.inputs):
      QMessageBox.warning(self.plugin,
                          self.tr("Missed input data"),
                          self.tr("Change map raster is not set. Please create it try again")
                         )
      return

    if self.leTopology.text() == "":
      QMessageBox.warning(self.plugin,
                          self.tr("Wrong network topology"),
                          self.tr("Network topology is undefined. Please define it and try again")
                         )
      return

    self.settings.setValue("ui/ANN/neighborhood", self.spnNeigbourhood.value())
    self.settings.setValue("ui/ANN/learningRate", self.spnLearnRate.value())
    self.settings.setValue("ui/ANN/maxIterations", self.spnMaxIterations.value())
    self.settings.setValue("ui/ANN/topology", self.leTopology.text())
    self.settings.setValue("ui/ANN/momentum", self.spnMomentum.value())

    self.btnStop.setEnabled(True)
    self.btnTrainNetwork.setEnabled(False)

    self.plugin.logMessage(self.tr("Init ANN model"))

    model = MlpManager(ns=self.spnNeigbourhood.value())
    self.inputs["model"] = model
    model.createMlp(self.inputs["initial"],
                         self.inputs["factors"].values(),
                         self.inputs["changeMap"],
                         [int(n) for n in self.leTopology.text().split(" ")]
                        )

    self.plugin.logMessage(self.tr("Set training data"))
    model.setTrainingData(self.inputs["initial"],
                               self.inputs["factors"].values(),
                               self.inputs["changeMap"],
                               mode=self.inputs["samplingMode"],
                               samples=self.plugin.spnSamplesCount.value()
                              )

    model.setEpochs(self.spnMaxIterations.value())
    model.setValPercent(20)
    model.setLRate(self.spnLearnRate.value())
    model.setMomentum(self.spnMomentum.value())
    model.setContinueTrain()

    self.axes.cla()
    self.axes.grid(True)
    self.dataTrain = []
    self.dataVal = []
    self.plotTrain = self.axes.plot(self.dataTrain,
                                    linewidth=1,
                                    color="green",  marker='o'
                                   )[0]
    self.plotVal = self.axes.plot(self.dataVal,
                                  linewidth=1,
                                  color="red",
                                 )[0]
    leg = self.axes.legend(('Train', 'Validation'), 'upper right', shadow=False)
    for t in leg.get_texts():
        t.set_fontsize('small')
    model.moveToThread(self.plugin.workThread)

    self.plugin.workThread.started.connect(model.startTrain)
    self.btnStop.clicked.connect(model.stopTrain)
    model.updateGraph.connect(self.__updateGraph)
    model.updateDeltaRMS.connect(self.__updateRMS)
    model.updateMinValErr.connect(self.__updateValidationError)
    model.updateKappa.connect(self.__updateKappa)
    model.processInterrupted.connect(self.__trainInterrupted)
    model.rangeChanged.connect(self.plugin.setProgressRange)
    model.updateProgress.connect(self.plugin.showProgress)
    model.errorReport.connect(self.plugin.logErrorReport)
    model.processFinished.connect(self.__trainFinished)
    model.processFinished.connect(self.plugin.workThread.quit)

    self.plugin.logMessage(self.tr("Start trainig ANN model"))
    self.plugin.workThread.start()

  def __trainFinished(self):
    model = self.inputs["model"]
    self.plugin.workThread.started.disconnect(model.startTrain)
    model.rangeChanged.disconnect(self.plugin.setProgressRange)
    model.updateProgress.disconnect(self.plugin.showProgress)
    model.errorReport.disconnect(self.plugin.logErrorReport)
    self.plugin.restoreProgressState()
    self.btnStop.setEnabled(False)
    self.btnTrainNetwork.setEnabled(True)
    self.plugin.logMessage(self.tr("ANN model trained"))

  def __trainInterrupted(self):
    self.plugin.workThread.quit()
    self.btnStop.setEnabled(False)
    self.btnTrainNetwork.setEnabled(True)
    self.plugin.logMessage(self.tr("ANN model training interrupted"))

  def __updateRMS(self, dRMS):
    self.leDeltaRMS.setText("%6.5f" % (dRMS))

  def __updateValidationError(self, error):
    self.leValidationError.setText("%6.5f" % (error))

  def __updateKappa(self, kappa):
    self.leKappa.setText("%6.5f" % (kappa))

  def __updateGraph(self, errTrain, errVal):
    self.dataTrain.append(errTrain)
    self.dataVal.append(errVal)

    ymin = min([min(self.dataTrain), min(self.dataVal)])
    ymax = max([max(self.dataTrain), max(self.dataVal)])

    self.axes.set_xbound(lower=0, upper=len(self.dataVal))
    self.axes.set_ybound(lower=ymin, upper=ymax)

    self.plotTrain.set_xdata(numpy.arange(len(self.dataTrain)))
    self.plotTrain.set_ydata(numpy.array(self.dataTrain))

    self.plotVal.set_xdata(numpy.arange(len(self.dataVal)))
    self.plotVal.set_ydata(numpy.array(self.dataVal))

    self.canvas.draw()
def createToolbar(canvas, widget):
    toolbar = NavigationToolbar(canvas, widget)
    lstActions = toolbar.actions()
    toolbar.removeAction(lstActions[7])
    return toolbar
class DrainageChannelBuilderDialog(QtGui.QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(DrainageChannelBuilderDialog, 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.iface = iface
        self.setupUi(self)

        self.resWarning = False

        self.btnOk = self.buttonBox.button(QtGui.QDialogButtonBox.Ok)
        self.btnOk.setText(self.tr("Run 2D"))
        self.btnClose = self.buttonBox.button(QtGui.QDialogButtonBox.Close)

        self.cbDEM.currentIndexChanged.connect(self.updateRasterRes)
        self.cbDEM.currentIndexChanged.connect(self.checkLayerExtents)
        self.cbCL.currentIndexChanged.connect(self.checkLayerExtents)
        self.spinElevStart.valueChanged.connect(self.calcDepth)
        self.spinElevEnd.valueChanged.connect(self.calcDepth)
        self.spinRightSideSlope.valueChanged.connect(self.updateMaxBankWidth)
        self.spinLeftSideSlope.valueChanged.connect(self.updateMaxBankWidth)
        self.spinWidth.valueChanged.connect(self.checkRes)
        self.spinRes.valueChanged.connect(self.checkRes)
        self.browseBtn.clicked.connect(self.writeDirName)
        self.btn1Dsave.clicked.connect(self.writeOut1Dresults)

        # add matplotlib figure to dialog
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.figure.subplots_adjust(left=.1,
                                    bottom=0.1,
                                    right=.95,
                                    top=.9,
                                    wspace=None,
                                    hspace=.2)
        self.canvas = FigureCanvas(self.figure)

        self.widgetPlotToolbar = NavigationToolbar(self.canvas,
                                                   self.widgetPlot)
        lstActions = self.widgetPlotToolbar.actions()
        self.widgetPlotToolbar.removeAction(lstActions[7])
        self.gPlot.addWidget(self.canvas)
        self.gPlot.addWidget(self.widgetPlotToolbar)
        self.figure.patch.set_visible(False)

        # 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.manageGui()

    def manageGui(self):
        print 'manageGui'
        self.cbCL.clear()
        self.cbCL.addItems(utils.getLineLayerNames())
        self.cbDEM.clear()
        self.cbDEM.addItems(utils.getRasterLayerNames())

    def refreshPlot(self):
        self.axes.clear()

        results1D = utils.getPlotArray(self.vLayer, self.rLayer,
                                       self.spinElevStart.value(),
                                       self.spinElevEnd.value(), self.xRes)

        self.stationA = results1D[0, :]

        self.zExistA = results1D[1, :]
        self.zPropA = results1D[2, :]
        self.xA = results1D[3, :]
        self.yA = results1D[4, :]
        self.calcCutAvgAreaEndMeth()

        self.axes.plot(self.stationA, self.zExistA)
        self.axes.plot(self.stationA, self.zPropA)
        self.axes.grid()
        formatter = ScalarFormatter(useOffset=False)
        self.axes.yaxis.set_major_formatter(formatter)

        self.axes.set_ylabel(unicode(self.tr("Elevation, z field units")))
        self.axes.set_xlabel(unicode(self.tr('Station, layer units')))
        self.axes.set_title(
            unicode(
                self.tr('Channel {} Profile and 1D Calculation Results'.format(
                    self.vLayer.name()))))
        at = AnchoredText(
            self.outText,
            prop=dict(size=12),
            frameon=True,
            loc=1,
        )
        at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")

        self.axes.add_artist(at)
        self.canvas.draw()

    def refreshPlotText(self):

        at = AnchoredText(
            self.outText,
            prop=dict(size=12),
            frameon=True,
            loc=1,
        )
        at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
        self.axes.add_artist(at)
        self.canvas.draw()

    def calcCutAvgAreaEndMeth(self):
        self.depth1D = self.zExistA - self.zPropA

        # find max bank width based on CL depth
        self.maxCLdepth = np.max(self.depth1D)
        leftSlope = self.spinLeftSideSlope.value()
        rightSlope = self.spinRightSideSlope.value()
        width = self.spinWidth.value()
        self.area = self.depth1D * (width + self.depth1D * leftSlope / 2.0 +
                                    self.depth1D * rightSlope / 2.0)
        self.length = self.stationA[1:] - self.stationA[:-1]
        self.vol1D = (self.area[1:] + self.area[:-1]) * self.length / 2.0
        self.vol1D = np.append(0, self.vol1D)
        self.totVol1D = np.sum(self.vol1D)
        self.maxDepth1D = np.max(self.depth1D)
        self.totLength = np.max(self.stationA)
        self.channelSlope = (self.zPropA[-1] - self.zPropA[0]) / self.totLength
        self.outText = 'Length: {2:.2f} layer units\nChannel Slope: {3:.6f}\n1D Max. Cut Depth: {0:,.2f} layer units\n1D Tot. Vol.: {1:,.2f} layer units$^3$'.format(
            self.maxDepth1D, self.totVol1D, self.totLength, self.channelSlope)

        #self.canvas.draw()

    def writeOut1Dresults(self):
        # assign results to numpy array for quick csv dump
        self.out1Dresults = np.zeros((self.stationA.size, 8))
        self.out1Dresults[:, 0] = self.stationA
        self.out1Dresults[:, 1] = self.vol1D
        self.out1Dresults[:, 2] = self.zExistA
        self.out1Dresults[:, 3] = self.zPropA
        self.out1Dresults[:, 4] = self.depth1D
        self.out1Dresults[:, 5] = self.area
        self.out1Dresults[:, 6] = self.xA
        self.out1Dresults[:, 7] = self.yA
        outPath = self.outputDir.text()
        home = os.path.expanduser("~")
        if outPath == '':
            outPath = os.path.join(home, 'Desktop',
                                   'QGIS2DrainageChannelBuilderFiles')
            self.outputDir.setText(outPath)
            if not os.path.exists(outPath):
                os.makedirs(outPath)

        os.chdir(outPath)
        fileName = 'Channel1Dresults_{}.txt'.format(self.vLayer.name())
        outHeader = 'DEM Layer:\t{0}\nChannel Centerline:\t{1}\nProjection (Proj4 format):\t{13}\nChannel Bottom Width:\t{3}\nChannel Start Elevation:\t{4}\nChannel End Elevation:\t{5}\nChannel Slope:\t{12:.06f}\nLeft Side Slope:\t{6}\nRight Side Slope:\t{7}\nLength:\t{9:,.2f}\n1D Max. Cut Depth:\t{10:,.2f}\n1D Tot. Vol:\t{11:,.2f}\nNote:\tAll units of length correspond to layer units, all units of area and volume are a combination of layer units and raster elevation units\n\nstation\tvol\tzExist\tzProp\tdepth\tcutArea\tx\ty\n'.format(
            self.cbDEM.currentText(), self.cbCL.currentText(),
            self.spinRes.value(), self.spinWidth.value(),
            self.spinElevStart.value(), self.spinElevEnd.value(),
            self.spinLeftSideSlope.value(), self.spinRightSideSlope.value(),
            self.spinBankWidth.value(), self.totLength, self.maxDepth1D,
            self.totVol1D, self.channelSlope,
            self.rLayer.crs().toProj4())
        np.savetxt(fileName,
                   self.out1Dresults,
                   fmt='%.3f',
                   header=outHeader,
                   delimiter='\t')
        self.canvas.print_figure('Channel1DresultsFigure_{}'.format(
            self.vLayer.name()))

    def updateMaxBankWidth(self):

        self.maxBankWidth = self.maxCLdepth * np.max(
            np.array([
                self.spinLeftSideSlope.value(),
                self.spinRightSideSlope.value()
            ]))
        self.spinBankWidth.setValue(self.maxBankWidth +
                                    self.spinRes.value() / 2.)
        self.calcCutAvgAreaEndMeth()
        self.refreshPlotText()

    def writeDirName(self):
        self.outputDir.clear()
        self.dirName = QtGui.QFileDialog.getExistingDirectory(
            self, 'Select Output Directory')
        self.outputDir.setText(self.dirName)
        self.checkBoxLoadLayers.setCheckState(True)

    def updateRasterRes(self):

        layer = utils.getRasterLayerByName(
            self.cbDEM.currentText().split(' EPSG')[0])
        if layer.isValid():
            self.xRes = layer.rasterUnitsPerPixelX()
            self.yRes = layer.rasterUnitsPerPixelY()
            self.labelDEMres.setText(
                'DEM Layer Resolution = {:.2f} X {:.2f} Y'.format(
                    self.xRes, self.yRes))

    def checkRes(self):

        if self.spinWidth.value() <= self.spinRes.value() * 10:

            self.resWarning = True
            self.errOutput()
        else:
            self.resWarning = False
            self.errOutput()
        self.calcCutAvgAreaEndMeth()
        self.refreshPlotText()

    def checkLayerExtents(self):

        self.rLayer = utils.getRasterLayerByName(
            self.cbDEM.currentText().split(' EPSG')[0])
        self.vLayer = utils.getVectorLayerByName(
            self.cbCL.currentText().split(' EPSG')[0])
        try:
            if self.rLayer.isValid() and self.vLayer.isValid():
                if self.rLayer.extent().xMaximum() >= self.vLayer.extent(
                ).xMaximum() and self.rLayer.extent().xMinimum(
                ) <= self.vLayer.extent().xMinimum() and self.rLayer.extent(
                ).yMaximum() >= self.vLayer.extent().yMaximum(
                ) and self.rLayer.extent().yMinimum() <= self.vLayer.extent(
                ).yMinimum():
                    self.layersOverlap = True
                    self.calcElev()
                    self.btn1Dsave.setEnabled(True)
                    self.btnOk.setEnabled(True)
                    self.errOutput()

                else:
                    self.btnOk.setEnabled(False)
                    self.spinElevStart.setEnabled(False)
                    self.spinElevEnd.setEnabled(False)
                    self.layersOverlap = False
                    self.errOutput()
        except:
            self.btnOk.setEnabled(False)
            self.spinElevStart.setEnabled(False)
            self.spinElevEnd.setEnabled(False)
            self.btn1Dsave.setEnabled(False)
            self.overlayError = True
            self.layersOverlap = False
            self.errOutput()
            pass

    def calcDepth(self):
        if self.layersOverlap:

            self.layersOverlap = utils.calcDepth(self)
        if self.layersOverlap:
            self.refreshPlot()

    def calcElev(self):
        if self.layersOverlap:
            self.spinElevStart.setEnabled(True)
            self.spinElevEnd.setEnabled(True)
            self.spinElevStart.setValue(utils.calcElev(self)[0])
            self.spinElevEnd.setValue(utils.calcElev(self)[1])
            self.refreshPlot()

    def updateProgressText(self, message):
        self.labelProgress.setText(message)

    def updateOutputText(self, message):
        self.textBrowser.setPlainText(message)

    def workerError(self, e, exception_string):
        print 'workerError\n{}\n'.format(exception_string)
        QgsMessageLog.logMessage(
            'Worker thread raised an exception:\n{}'.format(exception_string),
            level=QgsMessageLog.CRITICAL)
        self.iface.messageBar().pushMessage(
            "Drainge Channel Builder",
            'It didnt work, see log for details',
            level=QgsMessageBar.CRITICAL,
            duration=3)
        self.progressBar.setMaximum(100)
        self.btnOk.setEnabled(True)
        self.btn1Dsave.setEnabled(True)

    def stopWorker(self):
        self.worker.kill()
        if self.worker is not None:

            self.worker.deleteLater()
            self.thread.quit()
            self.thread.wait()
            self.thread.deleteLater()

    def errOutput(self):
        if self.resWarning and not self.layersOverlap:
            self.labelErrMessage.setText(
                'Error: Vector is not completely within raster domain\nWarning: For best 2D results, channel bottom width should be at least ten times greater than 2D grid calculation resolution'
            )
        elif self.resWarning:
            self.labelErrMessage.setText(
                'Warning: For best 2D results, channel bottom width should be at least ten times greater than 2D grid calculation resolution'
            )
        elif not self.layersOverlap:
            self.labelErrMessage.setText(
                'Error: Vector is not completely within raster domain')
        else:
            self.labelErrMessage.setText('')

    def workerFinished(self, values):
        # print 'values = ',values
        self.stopWorker()
        self.values = values
        maxCut = values[0][0]
        avgCut = values[0][1]
        totVol = values[0][2]
        self.dirName = values[0][3]
        self.outputDir.setText(self.dirName)
        demChannelPath = values[0][4]
        demCutDepth = values[0][5]
        length = values[0][6]
        outText = 'Summary of 2D Results:\nTot. Vol.\t{2:,.2f}\nLength\t{3:,.2f}\nMax. Cut Depth\t{0:.2f}\nAvg. Cut Depth\t{1:.2f}'.format(
            maxCut, avgCut, totVol, length)
        self.updateOutputText(outText)

        #            for layer in self.layers:
        #                utils.addSlLayer(self.iface,self.dbase,layer)

        self.iface.messageBar().pushMessage(
            "Drainge Channel Builder",
            'Channel elevation DEM, channel depth of cut DEM, and channel grid points located at {}.  Please delete when finished'
            .format(self.dirName),
            duration=30)

        # set channel dem qml by coping dem layer style to channel dem qml
        self.rLayer.saveNamedStyle(
            os.path.join(self.dirName,
                         demChannelPath.split('.tif')[0] + '.qml'))

        # set depth qml w/ function
        xmlString = utils.depthQMLwriter(maxCut)
        demCutDepthQML = open(demCutDepth.split('.tif')[0] + '.qml', 'w')
        demCutDepthQML.write(xmlString)
        demCutDepthQML.close()

        if self.checkBoxLoadLayers.checkState():
            for fileName in [demChannelPath, demCutDepth]:
                fileInfo = QFileInfo(fileName)
                baseName = fileInfo.baseName()
                layer = QgsRasterLayer(fileName, baseName)
                if not layer.isValid():
                    print "Layer failed to load!"
                QgsMapLayerRegistry.instance().addMapLayer(layer)

        self.progressBar.setMaximum(100)
        self.cbCL.setEnabled(True)
        self.cbDEM.setEnabled(True)
        self.spinRes.setEnabled(True)
        self.spinWidth.setEnabled(True)
        self.spinElevStart.setEnabled(True)
        self.spinElevEnd.setEnabled(True)
        self.spinLeftSideSlope.setEnabled(True)
        self.spinRightSideSlope.setEnabled(True)
        self.spinBankWidth.setEnabled(True)
        self.browseBtn.setEnabled(True)
        self.btn1Dsave.setEnabled(True)
        self.btnClose.setEnabled(True)
        self.btnOk.setEnabled(True)

        self.writeOut1Dresults()
        fileName = 'Channel2DresultsSummary_{}.txt'.format(self.vLayer.name())
        outText = 'DEM Layer:\t{0}\nChannel Centerline:\t{1}\nProjection (Proj4 format):\t{14}\n2D Grid Calc Res.:\t{2}\nChannel Bottom Width:\t{3}\nChannel Start Elevation:\t{4}\nChannel End Elevation:\t{5}\nChannel Slope:\t{13:.06f}\nLeft Side Slope:\t{6}\nRight Side Slope:\t{7}\n2D Maximum Bank Width:\t{8}\n\nLength:\t{9:,.2f}\n2D Max. Cut Depth:\t{10:,.2f}\n2D Avg. Cut Depth:\t{11:,.2f}\n2D Tot. Vol:\t{12:,.2f}\n\nNote:\tAll units of length correspond to layer units, all units of area and volume are a combination of layer units and raster elevation units\n\n'.format(
            self.cbDEM.currentText(), self.cbCL.currentText(),
            self.spinRes.value(), self.spinWidth.value(),
            self.spinElevStart.value(), self.spinElevEnd.value(),
            self.spinLeftSideSlope.value(), self.spinRightSideSlope.value(),
            self.spinBankWidth.value(), self.totLength, maxCut, avgCut, totVol,
            self.channelSlope,
            self.rLayer.crs().toProj4())
        outFile = open(fileName, 'w')
        outFile.write(outText)
        outFile.close()
        self.checkBoxLoadLayers.setCheckState(False)
        self.iface.mapCanvas().refresh()

    def accept(self):
        print 'accepted'

        args = [
            self.rLayer, self.vLayer,
            self.spinWidth.value(),
            self.spinRes.value(),
            self.spinElevStart.value(),
            self.spinElevEnd.value(),
            self.spinLeftSideSlope.value(),
            self.spinRightSideSlope.value(),
            self.spinBankWidth.value(),
            self.outputDir.text()
        ]
        self.thread = QThread()
        # create a new worker instance
        self.worker = DrainageChannelThread.DrainageChannelBuilder(args)

        # create a new worker instance
        self.worker.moveToThread(self.thread)
        self.worker.updateProgressText.connect(self.updateProgressText)

        self.worker.workerFinished.connect(self.workerFinished)
        self.worker.error.connect(self.workerError)

        self.btnClose.setEnabled(False)
        self.cbCL.setEnabled(False)
        self.cbDEM.setEnabled(False)
        self.spinRes.setEnabled(False)
        self.spinWidth.setEnabled(False)
        self.spinElevStart.setEnabled(False)
        self.spinElevEnd.setEnabled(False)
        self.spinLeftSideSlope.setEnabled(False)
        self.spinRightSideSlope.setEnabled(False)
        self.spinBankWidth.setEnabled(False)
        self.browseBtn.setEnabled(False)
        self.btn1Dsave.setEnabled(False)
        self.btnOk.setEnabled(False)
        self.tabWidgetOutput.setCurrentWidget(self.tabOutputSummary)

        #self.buttonBox.rejected.disconnect(self.reject)

        self.progressBar.setMaximum(0)
        self.thread.started.connect(self.worker.run)
        self.thread.start()

    def reject(self):
        print 'rejected'
        QtGui.QDialog.reject(self)
class ProfileFromPointsDialog(QtGui.QDialog, FORM_CLASS):
    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()
        self.uPointLayer.addItems(utils.getPointLayerNames())
        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 = processing.getObject(str(self.uPointLayer.currentText()))
        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 = processing.getObject(str(self.uLineLayer.currentText()))
        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(unicode(self.tr("Elevation, z field units")))
        self.axes.set_xlabel(unicode(self.tr('Station, layer units')))

        self.mplCanvas.draw()  


    def buildLine(self, pointSelectFlag):
        print 'buildLine'
        pointLayer = processing.getObject(str(self.uPointLayer.currentText()))
        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])
        
        ###build line
        # create a new memory layer
        newLineLayer = QgsVectorLayer("LineString?crs="+crs, "profileFromPointsLine", "memory")
        pr = newLineLayer.dataProvider()
        feat = QgsFeature()
        geom = QgsGeometry.fromPolyline(pointList)
        feat.setGeometry(geom)
        pr.addFeatures( [ feat ] )
        
        newLineLayer.updateExtents()
        QgsMapLayerRegistry.instance().addMapLayers([newLineLayer])
        return newLineLayer


    def accept(self):
        print 'run'
        pointLayer = processing.getObject(str(self.uPointLayer.currentText()))
        # 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 = processing.getObject(str(self.uLineLayer.currentText()))

        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 = lineLayer.getFeatures().next()
        lineGeom = lineFeat.geometry()
        lineShap = LineString(lineGeom.asPolyline())
        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)
Exemple #7
0
class ApplicationWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.lastImage=None ##TODO: change?
        self.copyContent = None
        self.imageAnnotations=[]
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setWindowTitle("%s %s - new project"%((progname,progversion)))
        self.iconObj=QtGui.QIcon('images/mainIcon.png')
        self.setWindowIcon(self.iconObj)
        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.createDockWindows()
        self.createToolBars()
        self.newProject()
        self.previewCheck.setChecked(True)
        self.posPatches=[]
        self.endSelector=None
        
    def raiseError(self,ex):
        msgBox=QtGui.QMessageBox()
        msgBox.setInformativeText(str(ex))
        msgBox.setText("Error")
        msgBox.exec_()
        self.updateAll()
        raise ex
    
    def appendToLog(self,string):
        tstr=time.strftime("%H:%m:%S")
        self.Log.append(tstr+" "+string)
        
        
    def newProject(self):
        self.project=autoContact.ContactProject()
        self.setWindowTitle("%s %s - new project"%((progname,progversion)))
        self.fileList.clear()
        self.fileName=""
        
    def save(self):
        if self.project.filename==None:
            self.saveAs()
#        try:
        fileName=self.project.filename
        self.project.save(fileName)
        self.fileName=fileName
        self.statusBar().showMessage("Saved '%s'" % fileName)
        self.appendToLog("Saves '%s'\n" % fileName)
        self.setWindowTitle("%s %s - %s"%((progname,progversion,os.path.basename(fileName))))
#        except Exception as exception:
#            self.statusBar().showMessage("Error '%s'" % exception, 10000)
            
    def saveAs(self):
        fileName = QtGui.QFileDialog.getSaveFileName(self,
                "Choose a file name", '*.nwcpr', "NW Contact Project (*.nwcpr)")
        if fileName:
#            try:
            self.fileName=fileName
            self.project.save(str(fileName))
            self.statusBar().showMessage("Saved '%s'" % fileName)
            self.appendToLog("Saved '%s'" % fileName)
            self.setWindowTitle("%s %s - %s"%((progname,progversion,os.path.basename(str(fileName)))))
#            except Exception as exception:
#                self.statusBar().showMessage("Error '%s'" % exception, 10000)    

    def open(self):
        fileName = QtGui.QFileDialog.getOpenFileName(self,
                "Choose a file ", '*.nwcpr', "NW Contact Project (*.nwcpr)")
        if fileName:
#            try:
            self.fileName=fileName
            self.project.load(str(fileName))
            print self.project.version
            print autoContact.version
            if self.project.version == "<0.970" or float(self.project.version) < float(autoContact.version):
                QtGui.QMessageBox.about(self, "Warning","Project file with version to old\n"+\
                                              "It is incompatible with the current version\n"+\
                                              "and will most likely not work.")
                                    
            files=self.project.paths
            self.fileList.clear()
            self.__addItems__(files)
            self.updateAll()
            self.statusBar().showMessage("Loaded '%s'" % fileName)
            self.appendToLog("Loaded '%s'" % fileName)
            self.setWindowTitle("%s %s - %s"%((progname,progversion,os.path.basename(str(fileName)))))
#            except Exception as exception:
#                self.statusBar().showMessage("Error '%s'" % exception, 10000)
                
    def exportGDS(self):
        indices=self.getIndices()
        self.export(indices,fileType="GDS")
        
    def exportCATS(self):
        indices=None
        self.export(indices,fileType="CATS")
    
    def exportSettings(self):
        filt="*.txt"
        inf="Text file (*.txt)"
        fileName = QtGui.QFileDialog.getSaveFileName(self,
                "Choose a file name", filt, inf )
        if fileName:
            indices=self.getIndices()
            self.project.exportSettings(str(fileName),indices)
            self.statusBar().showMessage("Exported to '%s'" % fileName)
            self.appendToLog("Exported to '%s'" % fileName)
        
    def autoExport(self):
        filt="*.gds"
        inf="GDSII file"
        indices=self.getIndices()
        fileName = r"C:\Users\rueffer\Desktop\test.gds"
        if fileName:
            fn=str(fileName)
            self.project.export(fn,indices,fileType="GDS")
            self.statusBar().showMessage("Exported to '%s'" % fileName)
            self.appendToLog("Exported to '%s'" % fileName)
            
    def export(self,indices,fileType):
        if fileType == "GDS":
            filt="*.gds"
            inf="GDSII file"
        elif fileType == "CATS":
            filt="*.nwco"
            inf="NW Contact Output (*.nwco)"
        fileName = QtGui.QFileDialog.getSaveFileName(self,
                "Choose a file name", filt, inf )
        if fileName:
            fn=str(fileName)
            self.project.export(fn,indices,fileType=fileType)
            self.statusBar().showMessage("Exported to '%s'" % fileName)
            self.appendToLog("Exported to '%s'" % fileName)

    def __addItems__(self,strings):
        if not (isinstance(strings,list) or isinstance(strings,QtCore.QStringList)):
            strings=[strings]
        items=[]
        for string in strings:
            item=QtGui.QTreeWidgetItem(self.fileList)
            item.setText(0,string)
            item.setText(4,self.project.defaultPattern)
#            item.setCheckState(0,QtCore.Qt.Unchecked)
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            items.append(item)
        self.fileList.addTopLevelItems(items)
        
    def endsMoved(self,i,new):
        index=self.getIndices()[0]
        transForm=self.project.createTransformFunc(index)
        new=transForm(new)
        if i == 0:
            name = "end1"
        elif i == 1:
            name = "end2"
        else:
            raise ValueError("this should not happen")
        self.project.setEnd(index,name,new)
        self.updateAll()
        

    def filesDropped(self, l):
        self.__addFiles__(l)    
        
    def __addFiles__(self,fileNames):
        if fileNames:
            try:
                append=[]
                allItems=[self.fileList.topLevelItem(i).text(0) for i in range(self.fileList.topLevelItemCount())]
                for n,fileName in enumerate(fileNames):
                    self.statusBar().showMessage("Loading... %.1f" %(n*100./len(fileNames))+r"%")
                    if fileName not in allItems:
                        self.project.addImage(str(fileName))
                        append.append(fileName)
                        QtGui.QApplication.processEvents()
                self.__addItems__(append)
                self.updateAll()
                if len(fileNames) == 1:
                    self.statusBar().showMessage("Added '%s'" % fileNames[0])
                    self.appendToLog("Added '%s'" % fileNames[0])
                else:
                    self.statusBar().showMessage("Added %d files" % len(fileNames))
                    self.appendToLog("Added %d files" % len(fileNames))
            except Exception as exception:
                self.raiseError(exception)
                    
    def addFiles(self):
        fileNames = QtGui.QFileDialog.getOpenFileNames(self,
                "Choose files ", '*.jpg', "image files")
        self.__addFiles__(fileNames)
        
    def refitImages(self):
        indices=self.getIndices()
        if indices:
            for n,index in enumerate(indices):
                self.project.refitImages(index)
                self.statusBar().showMessage("Fitting... %.1f" %(n*100./len(indices))+r"%")
            self.statusBar().showMessage("Refitted %d image(s)" % len(indices))
            self.appendToLog("Refitted %d image(s)" % len(indices))
            self.lastImage=None
            self.updateAll()
    
    def removeFiles(self):
        indices=self.getIndices()
        if indices:
            self.project.removeImages(indices)
            if len(indices) == 1:
                f= self.fileList.takeTopLevelItem(indices[0])
                self.statusBar().showMessage("Removed '%s'" % f.text(0))
                self.appendToLog("Removed '%s'" % f.text(0))
            else:
                self.fileList.itemSelectionChanged.disconnect(self.fileSelectionChanged)
                for index in sorted(indices)[::-1]:
                    self.fileList.takeTopLevelItem(index)
                self.statusBar().showMessage("Removed %d files" % len(indices))
                self.appendToLog("Removed %d files" % len(indices))
                self.fileList.itemSelectionChanged.connect(self.fileSelectionChanged)
            self.updateAll()
                
    def getIndices(self):
        items=self.fileList.selectedItems()
        indices=[self.fileList.indexOfTopLevelItem(i) for i in items]
        return indices
        
    def updateFitLogs(self):
        items=self.fileList.selectedItems()
        if not items:
            self.fitLog.clear()
            return
        index=self.fileList.indexOfTopLevelItem(items[0])
        string=self.project.fitLogs[index]
        self.fitLog.setText(string)
        
    
    def updateProperties(self):
        items=self.fileList.selectedItems()
        if not items:
            return
        index=self.fileList.indexOfTopLevelItem(items[0])
        keys=self.project.settings[index].keys()
        if "wires" in keys:
            keys.remove("wires")
            wires=self.project.settings[index]["wires"]
        else:
            wires=[]
        self.propertiesDisplay.setRowCount(len(keys)+len(wires))
        for n,key in enumerate(sorted(keys)):
            item=QtGui.QTableWidgetItem()
            item.setText(key)
            item.setFlags( QtCore.Qt.ItemIsSelectable |  QtCore.Qt.ItemIsEnabled )
            self.propertiesDisplay.setItem(n,0,item)
            item=QtGui.QTableWidgetItem()
            data=self.project.settings[index][key]
            if isinstance(data,np.ndarray) or isinstance(data,list):
                if isinstance(data[0],float) or isinstance(data[0],np.float):
                    string="("
                    for i in data:
                        string=string+"%.4f,"%i
                    string=string[:-1]+")"
                else:
                    string = str(data)
            elif isinstance(data,float):
                string="%.4f"%data
            else:
                string =str(data)
            item.setText(string)
            item.setFlags( QtCore.Qt.ItemIsSelectable |  QtCore.Qt.ItemIsEnabled )
            self.propertiesDisplay.setItem(n,1,item)
        for m,wire in enumerate(wires):
            item=QtGui.QTableWidgetItem()
            item.setText("wire_%d"%m)
            item.setFlags( QtCore.Qt.ItemIsSelectable |  QtCore.Qt.ItemIsEnabled )
            self.propertiesDisplay.setItem(n+m+1,0,item)
            item=QtGui.QTableWidgetItem()
            item.setText("[(%.4f;%.4f),(%.4f,%.4f)]"%((wire["end1"][0],wire["end1"][1],wire["end2"][0],wire["end2"][1])))
            item.setFlags( QtCore.Qt.ItemIsSelectable |  QtCore.Qt.ItemIsEnabled )
            self.propertiesDisplay.setItem(n+m+1,1,item)
            
        
    def updateAll(self):
        t0=time.time()
        self.updateProperties()
        self.updateWireOptions()
        self.updateList()
        self.updateContactsOption()
        self.updateExposureOptions()
        self.updateFitLogs()
        indices=self.getIndices()
        if len(indices)==0:
            self.copyAct.setEnabled(False)
            self.pasteAct.setEnabled(False)
        elif len(indices)==1:
            self.copyAct.setEnabled(True)
            if self.copyContent == None:
                self.pasteAct.setEnabled(False)
            else:
                self.pasteAct.setEnabled(True)
        else:
            self.copyAct.setEnabled(True)
            self.pasteAct.setEnabled(True)
#        t1=time.time()
#        print "rest: %.3f"%((t1-t0)*1000)
        self.updateImage()
#        t2=time.time()
#        print "image: %.3f"%((t2-t1)*1000)
    
    def previewCheckBoxChanged(self,i):
        self.updateImage()
    
    def fillWireCombo(self,index):
        self.wireCombo.clear()
        items=[]
        for wire in range(len(self.project.settings[index]["wires"])):
            items.append("Wire %d"%wire)
        self.wireCombo.insertItems(0,items)
        self.wireCombo.setCurrentIndex(self.project.getWireNo(index))
#        
    def updateExposureOptions(self):
        layers=list(self.project.getLayers())
        length=len(layers)
        if length < 1:
            self.exposureOptions.setEnabled(False)
            self.exposureCombo.setEnabled(False)
            self.exposureOptions.setRowCount(0)
            return         
        self.exposureCombo.setEnabled(True)
        self.exposureOptions.setEnabled(True)
#        print layers
        index=self.exposureCombo.currentIndex()
        self.exposureCombo.clear()        
        for layer in layers[::-1]:
            self.exposureCombo.insertItem(0,"Layer %d"%layer)
        if not index < len(layers):
            index=0
        if index < 0:
            index = 0
        self.exposureCombo.setCurrentIndex(index)
            
#        print "index: "+str(index)
        if index == -1:
            return
#        self.exposureCombo.setCurrentIndex(layers[0])
#        print self.project.exposureSettings
        optionDict=self.project.getExposureSettings(index)
        options=optionDict.keys()
#        print optionDict
        self.exposureOptions.setRowCount(len(options))
        try:
            self.exposureOptions.cellChanged.disconnect(self.exposureOptionsChanged)
        except:
            pass
        for n,key in enumerate(sorted(options)):
            item=QtGui.QTableWidgetItem()
            item.setText(key)
            item.setFlags( QtCore.Qt.ItemIsSelectable |  QtCore.Qt.ItemIsEnabled )
            self.exposureOptions.setItem(n,0,item)
            if optionDict.has_key(key):
                if isinstance(optionDict[key],float) or isinstance(optionDict[key],np.float):
                    value="%.3f"%optionDict[key]
                else:
                    value=str(optionDict[key])
            else:
                print key," not found"
                value="%.3f"%options[key]
                self.project.changeSingleContactOptions(index,key,value)
            item=QtGui.QTableWidgetItem()
            if length == 1:
                item.setText(value)
            else:
                item.setText(value)
            item.setFlags( QtCore.Qt.ItemIsSelectable |  QtCore.Qt.ItemIsEnabled |  QtCore.Qt.ItemIsEditable )
            self.exposureOptions.setItem(n,1,item)
        self.exposureOptions.cellChanged.connect(self.exposureOptionsChanged)
        
        
    def exposureOptionsChanged(self,row,column):
        try:
            index=self.exposureCombo.currentIndex()
            key=str(self.exposureOptions.item(row,0).text())
            value=str(self.exposureOptions.item(row,1).text())
#            if not key in ["beam"]:
#                value=atof(value)
            self.project.changeExposureSetting(key,index,value)
            self.updateAll()
        except Exception as exception:
            self.raiseError(exception)

    def updateWireOptions(self):
        items=self.fileList.selectedItems()
        if not items:
            self.modeCombo.setEnabled(False)
            self.wireCombo.setEnabled(False)
            return
        index=self.fileList.indexOfTopLevelItem(items[0])
        if not self.project.settings[index]["fit"]:
            self.modeCombo.setEnabled(False)
            self.wireCombo.setEnabled(False)
            return            
        mode=self.project.settings[index]["mode"]
        self.modeCombo.setEnabled(True)
        if mode == "auto":
            self.wireCombo.setEnabled(False)
            self.modeCombo.setCurrentIndex(0)
            self.wireCombo.clear()
        elif mode == "select":
            self.wireCombo.setEnabled(True)
            self.modeCombo.setCurrentIndex(1)
            self.fillWireCombo(index)
        else:
            self.wireCombo.setEnabled(False)
            self.modeCombo.setCurrentIndex(2)
            self.wireCombo.clear()
    
    def updateContactsOption(self):
        items=self.fileList.selectedItems()
        length=len(items)
        if length < 1:
            self.contactsOptions.setEnabled(False)
            self.contactsCombo.setEnabled(False)
            self.contactsOptions.setRowCount(0)
            return         
        contactName0=self.project.settings[self.fileList.indexOfTopLevelItem(items[0])]["contact"]
        for item in items:
            index=self.fileList.indexOfTopLevelItem(item)
            if not self.project.settings[index]["fit"] or self.project.settings[index]["contact"] != contactName0:
                self.contactsOptions.setEnabled(False)
                self.contactsCombo.setEnabled(False)
                self.contactsOptions.setRowCount(0)
                return   
        self.contactsCombo.setEnabled(True)
        self.contactsOptions.setEnabled(True)
        allItems = [self.contactsCombo.itemText(i) for i in range(self.contactsCombo.count())]
        contactName=self.project.settings[index]["contact"]
        i=allItems.index(contactName)
        self.contactsCombo.setCurrentIndex(i)
        options=self.project.getContactOptions(contactName)
        optionDict=self.project.settings[index]["contactOptions"]
        self.contactsOptions.setRowCount(len(options))
#        print options
#        print optionDict
        try:
            self.contactsOptions.cellChanged.disconnect(self.contactsOptionsChanged)
        except:
            pass
        for n,key in enumerate(sorted(options.keys())):
            item=QtGui.QTableWidgetItem()
            item.setText(key)
            item.setFlags( QtCore.Qt.ItemIsSelectable |  QtCore.Qt.ItemIsEnabled )
            self.contactsOptions.setItem(n,0,item)
            found=True
            if not optionDict.has_key(key):
                value=None
                found=False
                self.project.changeSingleContactOptions(index,key,value)
                options=self.project.getContactOptions(contactName)
                value="%.3f"%options[key]
            if isinstance(optionDict[key],float) or isinstance(optionDict[key],np.float):
                value="%.3f"%optionDict[key]
            else:
                value=str(optionDict[key])
            if not found:
                self.statusBar().showMessage("%s not found, using default: %s"%((key,value)))
                self.appendToLog("%s not found, using default: %s"%((key,value)))
            item=QtGui.QTableWidgetItem()
            if length == 1:
                item.setText(value)
            else:
                it=True
                for index in [self.fileList.indexOfTopLevelItem(im) for im in items]:
                    if not self.project.settings[index]["contactOptions"].has_key(key):
                        it=False
                        break
                    elif self.project.settings[index]["contactOptions"][key] != optionDict[key]:
                        it=False
                        break
                if it:
                    item.setText(value)
                else:
                    item.setText("--")
            item.setFlags( QtCore.Qt.ItemIsSelectable |  QtCore.Qt.ItemIsEnabled |  QtCore.Qt.ItemIsEditable )
            self.contactsOptions.setItem(n,1,item)
        self.contactsOptions.cellChanged.connect(self.contactsOptionsChanged)
        
    def contactsOptionsChanged(self,row,column):
        try:
            indices=self.getIndices()
            key=str(self.contactsOptions.item(row,0).text())
            value=str(self.contactsOptions.item(row,1).text())
            print value
            self.project.changeSingleContactOptions(indices,key,value)
            self.updateAll()
        except Exception as exception:
            self.raiseError(exception)

    def contactNameChange(self,index):   
        try:
            contactName=str(self.contactsCombo.currentText())
            indices=self.getIndices()
            self.project.changeContactType(indices,contactName)
            self.updateAll()
        except Exception as exception:
            self.raiseError(exception)
        
    def exposureLayerChange(self,index):
        try:
            self.updateAll()
        except Exception as exception:
            self.raiseError(exception)
    
    def modeChanged(self,index):
        try:
            mode=str(self.modeCombo.currentText())
            indices=self.getIndices()
            self.project.changeMode(indices,mode)
            self.updateAll()
        except Exception as exception:
            self.raiseError(exception)
        
    def wireChanged(self,index):
        try:
            indices=self.getIndices()
            self.project.changeWire(indices[0],index)
            self.updateAll()
        except Exception as exception:
            self.raiseError(exception)
            
    def copySettings(self):
        indices=self.getIndices()
        if not indices:
            return
        index=indices[0]
        self.copyContent={"contact":self.project.settings[index]["contact"],
                          "contactOptions":self.project.settings[index]["contactOptions"]}
    def pasteSettings(self):
        try:
            indices=self.getIndices()
            if not indices or self.copyContent == None:
                return
            self.project.changeContactOptions(indices,self.copyContent["contact"],self.copyContent["contactOptions"])
            #self.copyContent=None
            self.updateAll()
        except Exception as exception:
            self.raiseError(exception)
                
    def fileListPopup(self,pos):
        contextMenu=QtGui.QMenu()
        contextMenu.addAction(self.addFilesAct)
        contextMenu.addAction(self.removeFilesAct)
        contextMenu.addAction(self.refitImagesAct)
        contextMenu.addSeparator()
        contextMenu.addAction(self.selectAllAct)
        contextMenu.addAction(self.copyAct)
        contextMenu.addAction(self.pasteAct)
        contextMenu.addSeparator()
        contextMenu.addAction(self.exportGDSAct)
        contextMenu.addAction(self.exportSettingsAct)
        action = contextMenu.exec_(self.fileList.mapToGlobal(pos))
        if action:
            action.trigger()

    def updateList(self):
        for n in range(self.fileList.topLevelItemCount ()):
            item = self.fileList.topLevelItem(n)
#            print "Toplevelitemcount: "+str(n)
            try:
                if self.project.settings[n]["fit"]:
    #                    item.setCheckState(0,QtCore.Qt.Checked)
                    cell=self.project.settings[n]["cell"]
                    cellstring="%d,%d"%(tuple(cell))
                    block=self.project.descriptor.getBlockNo(cell)
                    blockstring="%d,%d"%(tuple(block))
                    mode=self.project.settings[n]["mode"]
                    item.setText(1,cellstring)
                    item.setText(2,blockstring)
                    item.setText(3,mode)
                else:
    #                    item.setCheckState(0,QtCore.Qt.Unchecked)
                    item.setText(1,"")
                    item.setText(2,"")
                    item.setText(3,"")
                contact=self.project.settings[n]["contact"]
                item.setText(4,contact)
            except IndexError:
                pass #TODO: uggly hack here, solve in a better way
            except Exception as exception:
                self.raiseError(exception)
         
                
    def updateImage(self):
        items=self.fileList.selectedItems()
        if not items:
            for i in range(len(self.imageAnnotations)):
                self.imageAnnotations.pop(0).remove()
            for i in range(len(self.canvas.axes.images)):
                self.canvas.axes.images[i].remove()
            try:
                self.endSelector.disconnect()
            except:
                pass
            self.endSelector = None
            self.lastImage=None
            self.canvas.draw()
            return
        index=self.fileList.indexOfTopLevelItem(items[0])
        for i in range(len(self.imageAnnotations)):
            self.imageAnnotations.pop(0).remove()
#        self.canvas.axes.clear()
            ##  TODO: get directly from axes, avoid the list
        if index >= 0:
            if self.lastImage!=self.project.paths[index]:
                for i in range(len(self.canvas.axes.images)):
                    self.canvas.axes.images[i].remove()
#                print imread(self.project.paths[index])
                self.canvas.axes.imshow(imread(self.project.paths[index]),interpolation="None")
                self.lastImage=self.project.paths[index]
#            if items[0].checkState(0):
            if self.project.settings[index]["cell"]==None:
                self.canvas.draw()
                return
            for pos in self.project.settings[index]["markers"]:
                p=plt.Line2D([pos[0]],[pos[1]],color=[1,0,0],marker="+",ms=5)
                self.canvas.axes.add_artist(p)
                self.imageAnnotations.append(p)
            pos=self.project.settings[index]["center"]
            p=plt.Line2D([pos[0]],[pos[1]],color=[1,0,0],marker="+",ms=10)
            self.canvas.axes.add_artist(p)
            self.imageAnnotations.append(p)
            px,py,tx,ty=self.project.descriptor.getBits(self.project.settings[index]["cell"])
            invTransForm=self.project.createInverseTransformFunc(index)
            scale=self.project.settings[index]["scale"]
            angle=self.project.settings[index]["angle"]
            truth=np.hstack((tx,ty))
            for i,pos in enumerate(np.vstack((px,py))):
                if truth[i]:
                    fc="r"
                else:
                    fc="none"
                xy=invTransForm([(pos[0]-self.project.descriptor.markerSize*2.),(pos[1]-self.project.descriptor.markerSize*2.)])
                p = Rectangle(xy,width=self.project.descriptor.bitDistance/scale,height=-self.project.descriptor.bitDistance/scale,
                              fc=fc,lw=1,alpha=0.3)
                t = MPLTransforms.Affine2D().rotate_around(xy[0],xy[1],-angle/180.*np.pi) + self.canvas.axes.transData
                p.set_transform(t)
                self.canvas.axes.add_artist(p)
                self.imageAnnotations.append(p)
            if self.previewCheck.checkState():
                a=self.project.showCell(self.canvas.axes,index)
                self.imageAnnotations.extend(a)
            if self.project.settings[index]["mode"]=="manual":
                try:
                    self.endSelector.disconnect()
                except:
                    pass
                self.endSelector=endSelector(self,index) ## TODO improve: change properties, do not always override
            else:
                try:
                    self.endSelector.disconnect()
                except:
                    pass
                self.endSelector = None
#            else: ## TODO: clean up this mess with disconnect
#                try:
#                    self.endSelector.disconnect()
#                except:
#                    pass
#                self.endSelector = None
        
        else:
            for i in range(len(self.canvas.axes.images)):
                self.canvas.axes.images[i].remove()
            try:
                self.endSelector.disconnect()
            except:
                pass
            self.endSelector = None
            self.lastImage=None
        self.canvas.draw()
    
    def fileSelectionChanged(self):
        self.updateAll()
        a=len(self.getIndices())
        if a:
            self.statusBar().showMessage("Selected %d files" % a)
        else:
            self.statusBar().showMessage("No files selected")
        
        
    def createFileListDock(self):
        dock = QtGui.QDockWidget("Files", self)
        self.fileListWidget=QtGui.QMainWindow()
        self.fileListWidget.setParent(dock)
        dock.setWidget(self.fileListWidget)
        dock.setMaximumWidth(340)
        dock.setMinimumWidth(280)
        self.fileList = myFileList(parent=self.fileListWidget)
#        self.fileList = QtGui.QTreeWidget(parent=self.fileListWidget)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        self.fileList.setRootIsDecorated(False)
        self.fileList.setAlternatingRowColors(True)
        self.fileList.setHeaderLabels(["File","Cell","Block","Mode","Contact"])
        self.fileListWidget.setCentralWidget(self.fileList)
        self.fileList.setSelectionMode(3)
        self.fileList.setTextElideMode(QtCore.Qt.ElideLeft)
        self.fileList.header().resizeSection(0,80)
        self.fileList.header().resizeSection(1,40)
        self.fileList.header().resizeSection(2,40)
        self.fileList.header().resizeSection(3,40)
        self.fileList.header().resizeSection(4,50)
        self.fileList.itemSelectionChanged.connect(self.fileSelectionChanged)
        self.fileList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.fileList.customContextMenuRequested.connect(self.fileListPopup)
        self.connect(self.fileList, QtCore.SIGNAL("dropped"), self.filesDropped)

        
        
    def createDockWindows(self):
        self.createFileListDock() 
        self.createImageDock()
        self.createWireOptions()  
        self.createContactOptions() 
        self.createExposureOptions()
        dock = QtGui.QDockWidget("Properties", self)
        self.propertiesDisplay=QtGui.QTableWidget()
        dock.setWidget(self.propertiesDisplay)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        self.propertiesDisplay.setColumnCount(2)
        self.propertiesDisplay.setHorizontalHeaderLabels(["Property","Value"])
        header=self.propertiesDisplay.horizontalHeader()
        header.setStretchLastSection(True)
        dock.setHidden(True)
        
        dock = QtGui.QDockWidget("Log", self)
        self.Log = QtGui.QTextEdit(dock)
        dock.setWidget(self.Log)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        self.Log.setReadOnly(True)
        
        dock = QtGui.QDockWidget("Fit Log", self)
        self.fitLog = QtGui.QTextEdit(dock)
        dock.setWidget(self.fitLog)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        self.fitLog.setReadOnly(True)
        
            
        
    def createImageDock(self):   
        dock = QtGui.QDockWidget("Image & Preview", self)
        self.imageWidget=QtGui.QMainWindow()
        self.imageWidget.setParent(dock)
        dock.setWidget(self.imageWidget)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        self.canvas = MPLCanvas(dock)
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.imageWidget,coordinates=False)
        actlist= self.mpl_toolbar.actions()
        names=["Save","Customize","Subplots"]
        for action in actlist:
            if str(action.text()) in names:
                self.mpl_toolbar.removeAction(action)
        self.previewCheck=QtGui.QCheckBox("Preview")
        self.previewCheck.stateChanged.connect(self.previewCheckBoxChanged)
        self.mpl_toolbar.addWidget(self.previewCheck)
        self.mpl_toolbar.setMovable(False)
        self.imageWidget.addToolBar(self.mpl_toolbar)
        self.imageWidget.setCentralWidget(self.canvas)
        self.imageWidget.setMinimumSize(600,450)        
        
    def createWireOptions(self):
        dock = QtGui.QDockWidget("Wire Options", self)
        dock.setMaximumWidth(340)
        dock.setMinimumWidth(280)
        widget=QtGui.QWidget()
        dock.setWidget(widget)
        self.wireOptionsLayout=QtGui.QGridLayout()
        widget.setLayout(self.wireOptionsLayout)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        self.modeCombo=QtGui.QComboBox()
        self.wireOptionsLayout.addWidget(self.modeCombo,0,0)
        self.modeCombo.insertItem(0,"manual")
        self.modeCombo.insertItem(0,"select")
        self.modeCombo.insertItem(0,"auto")
        self.modeCombo.setEnabled(False)
        self.wireCombo=QtGui.QComboBox()
        self.wireOptionsLayout.addWidget(self.wireCombo,0,1)
        self.wireCombo.setEnabled(False)
        self.wireCombo.activated.connect(self.wireChanged)
        self.modeCombo.activated.connect(self.modeChanged)
        
    def createContactOptions(self):
        dock = QtGui.QDockWidget("Contact Settings", self)
        dock.setMaximumWidth(340)
        dock.setMinimumWidth(280)
        widget=QtGui.QWidget()
        dock.setWidget(widget)
        self.contactOptionsLayout=QtGui.QVBoxLayout()
        widget.setLayout(self.contactOptionsLayout)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        self.contactsCombo=QtGui.QComboBox()
        self.contactOptionsLayout.addWidget(self.contactsCombo)
        for key in sorted(autoContact.allPatterns.keys()):
            self.contactsCombo.insertItem(0,key)
        self.contactsCombo.setEnabled(False)
        self.contactsCombo.activated.connect(self.contactNameChange)
        self.contactsOptions = QtGui.QTableWidget()
        self.contactOptionsLayout.addWidget(self.contactsOptions)
        self.contactsOptions.setAlternatingRowColors(True)
        self.contactsOptions.setColumnCount(2)
        self.contactsOptions.horizontalHeader().setStretchLastSection(True)
        self.contactsOptions.setHorizontalHeaderLabels(["Option","Value"])
        self.contactsOptions.setEnabled(False)
        self.contactsCombo.setEnabled(False)
        self.contactsOptions.setRowCount(0)
        
        
    def createExposureOptions(self):
        dock = QtGui.QDockWidget("Exposure Settings", self)
        dock.setMaximumWidth(340)
        dock.setMinimumWidth(280)
        widget=QtGui.QWidget()
        dock.setWidget(widget)
        self.exposureOptionsLayout=QtGui.QVBoxLayout()
        widget.setLayout(self.exposureOptionsLayout)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        self.exposureCombo=QtGui.QComboBox()
        self.exposureOptionsLayout.addWidget(self.exposureCombo)
#        for key in sorted(autoContact.allPatterns.keys()):
#            self.exposureCombo.insertItem(0,key)
        self.exposureCombo.setEnabled(False)
        self.exposureCombo.activated.connect(self.exposureLayerChange)
        self.exposureOptions = QtGui.QTableWidget()
        self.exposureOptionsLayout.addWidget(self.exposureOptions)
        self.exposureOptions.setAlternatingRowColors(True)
        self.exposureOptions.setColumnCount(2)
        self.exposureOptions.horizontalHeader().setStretchLastSection(True)
        self.exposureOptions.setHorizontalHeaderLabels(["Option","Value"])
        self.exposureOptions.setEnabled(False)
        self.exposureCombo.setEnabled(False)
        self.exposureOptions.setRowCount(0)
        

    def createToolBars(self):
        self.fileToolBar = self.addToolBar("Project")
        self.fileToolBar.setMovable(False)
        self.fileToolBar.addAction(self.newAct)
        self.fileToolBar.addAction(self.openAct)
        self.fileToolBar.addAction(self.saveAct)
        self.fileToolBar.addAction(self.saveAsAct)
        self.fileToolBar.addSeparator()
        self.fileToolBar.addAction(self.exportCATSAct)
        self.fileToolBar.addSeparator()
        self.fileToolBar.addAction(self.quitAct)

        self.editToolBar = self.fileListWidget.addToolBar("Edit")
        self.editToolBar.setMovable(False)
        self.editToolBar.addAction(self.addFilesAct)
        self.editToolBar.addAction(self.removeFilesAct)
        self.editToolBar.addAction(self.refitImagesAct)
        self.editToolBar.addSeparator()
        self.editToolBar.addAction(self.selectAllAct)
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.pasteAct)
        self.editToolBar.addSeparator()
#        self.editToolBar.addAction(self.fitAct)
        self.editToolBar.addAction(self.exportGDSAct)
        self.editToolBar.addAction(self.exportSettingsAct)
        self.copyAct.setEnabled(False)
        self.pasteAct.setEnabled(False)


    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&Project")
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.quitAct)

        self.menuBar().addSeparator()

        self.viewMenu = self.menuBar().addMenu("&View")
        self.menuBar().addSeparator()
        
        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)
        
    def createStatusBar(self):
        self.statusBar().showMessage("Ready")
        
    def __selectAll__(self):
        self.fileList.selectAll()
        
    def createActions(self):
        self.newAct = QtGui.QAction(QtGui.QIcon('images/new.png'),
                "&New", self, shortcut=QtGui.QKeySequence.New,
                statusTip="Create a new project",
                triggered=self.newProject)
        self.selectAllAct = QtGui.QAction(QtGui.QIcon('images/selectall.png'),
                "&Select All", self, shortcut=QtGui.QKeySequence.SelectAll,
                statusTip="Select all files",
                triggered=self.__selectAll__)
        self.saveAct = QtGui.QAction(QtGui.QIcon('images/save.png'),
                "&Save", self, shortcut=QtGui.QKeySequence.Save,
                statusTip="Save the current project",
                triggered=self.save)
        self.saveAsAct = QtGui.QAction(QtGui.QIcon('images/saveas.png'),
                "&Save As...", self, shortcut=QtGui.QKeySequence.SaveAs,
                statusTip="Save the current project as ...",
                triggered=self.saveAs)
        self.openAct = QtGui.QAction(QtGui.QIcon('images/open.png'),
                "&Open...", self, shortcut=QtGui.QKeySequence.Open,
                statusTip="Open an existing project",
                triggered=self.open)
        self.quitAct = QtGui.QAction(QtGui.QIcon('images/exit.png'),
                "&Exit", self, shortcut="Ctrl+Q",
                statusTip="Exit the application", triggered=self.close)
        self.aboutAct = QtGui.QAction("&About", self,
                statusTip="Show the application's About box",
                triggered=self.about)
        self.addFilesAct = QtGui.QAction(QtGui.QIcon('images/plus.png'),
                "&Add files...", self,
                statusTip="Add files to current project",
                triggered=self.addFiles)
        self.removeFilesAct = QtGui.QAction(QtGui.QIcon('images/minus.png'),
                "&Remove files", self,shortcut=QtGui.QKeySequence.Delete,
                statusTip="Remove the selected files from project",
                triggered=self.removeFiles)
        self.refitImagesAct = QtGui.QAction(QtGui.QIcon('images/refresh.png'),
                "&Refit Images", self,shortcut=QtGui.QKeySequence.Refresh,
                statusTip="Refit the selected images",
                triggered=self.refitImages)
        self.exportGDSAct = QtGui.QAction(QtGui.QIcon('images/exportgds.png'),
                "&Export GDS", self,
                statusTip="Export selected cells to a GDS file",
                triggered=self.exportGDS)
        self.exportCATSAct = QtGui.QAction(QtGui.QIcon('images/exportcats.png'),
                "&Export CATS", self,
                statusTip="Export the project for CATS conversion",
                triggered=self.exportCATS)
                
        self.exportSettingsAct=QtGui.QAction(QtGui.QIcon('images/exportFile.png'),
                "&Export setttings to file",self,
                statusTip="Export the settings of selected files to a tab-separated file",
                triggered=self.exportSettings)
#        self.fitAct = QtGui.QAction(QtGui.QIcon('images/curve.png'),
#                "&Fit selected", self,
#                statusTip="Perform fit for selected images",
#                triggered=self.fitSelected)
        self.copyAct=QtGui.QAction(QtGui.QIcon('images/copy.png'),
                "&Copy settings",self,shortcut=QtGui.QKeySequence.Copy,
                statusTip="Copy the settings of the selected wire",
                triggered=self.copySettings)

        self.pasteAct=QtGui.QAction(QtGui.QIcon('images/paste.png'),
                "&Paste settings",self,shortcut=QtGui.QKeySequence.Paste,
                statusTip="Paste the settings to all selected wires",
                triggered=self.pasteSettings)
                

    def fileQuit(self):
        self.close()

    def closeEvent(self, ce):
        self.fileQuit()

    def about(self):
        string=u"""%(prog)s version %(version)s
Copyright \N{COPYRIGHT SIGN} 2012 Daniel Rüffer

This program does automatic contacting of
nanowires dispersed on the FlexiPattern substrates.
Modulversions:
"""% {"prog": progname, "version": progversion}+\
        "autoContact: "+autoContact.version+"\n"+\
        "autoDetect: "+autoContact.autoDetectVersion+"\n"+\
        "createCJOB: "+autoContact.createCJOBVersion+"\n"+\
        "PatternGenerator: "+autoContact.PatternGeneratorVersion+"\n"+\
        "GDSGenerator: "+autoContact.GDSGeneratorVersion

        QtGui.QMessageBox.about(self, "About %s" % progname,string
)
class NeuralNetworkWidget(QWidget, Ui_Widget):
  def __init__(self, plugin, parent=None):
    QWidget.__init__(self, parent)
    self.setupUi(self)

    self.plugin = plugin
    self.inputs = plugin.inputs
    self.settings = QSettings("NextGIS", "MOLUSCE")

    # init plot for learning curve
    self.figure = Figure()
    self.axes = self.figure.add_subplot(111)
    self.axes.grid(True)
    self.figure.suptitle(self.tr("Neural Network learning curve"))
    self.canvas = FigureCanvas(self.figure)
    self.mpltoolbar = NavigationToolbar(self.canvas, None)
    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.chkCreateReport.toggled.connect(self.__toggleLineEdit)
    self.chkSaveSamples.toggled.connect(self.__toggleLineEdit)

    self.btnSelectReport.clicked.connect(self.__selectFile)
    self.btnSelectSamples.clicked.connect(self.__selectFile)

    self.btnTrainNetwork.clicked.connect(self.trainNetwork)

    self.manageGui()

  def manageGui(self):
    self.spnNeigbourhood.setValue(self.settings.value("ui/ANN/neighborhood", 1).toInt()[0])
    self.spnLearnRate.setValue(self.settings.value("ui/ANN/learningRate", 0.1).toFloat()[0])
    self.spnMaxIterations.setValue(self.settings.value("ui/ANN/maxIterations", 1000).toInt()[0])
    self.leTopology.setText(self.settings.value("ui/ANN/topology", "10").toString())
    self.spnMomentum.setValue(self.settings.value("ui/ANN/momentum", 0.05).toFloat()[0])

    self.chkCreateReport.setChecked(self.settings.value("ui/ANN/createReport", False).toBool())
    self.chkSaveSamples.setChecked(self.settings.value("ui/ANN/saveSamples", False).toBool())

  def trainNetwork(self):
    self.settings.setValue("ui/ANN/neighborhood", self.spnNeigbourhood.value())
    self.settings.setValue("ui/ANN/learningRate", self.spnLearnRate.value())
    self.settings.setValue("ui/ANN/maxIterations", self.spnMaxIterations.value())
    self.settings.setValue("ui/ANN/topology", self.leTopology.text())
    self.settings.setValue("ui/ANN/momentum", self.spnMomentum.value())

    self.settings.setValue("ui/ANN/createReport", self.chkCreateReport.isChecked())
    self.settings.setValue("ui/ANN/saveSamples", self.chkSaveSamples.isChecked())

    self.model = MlpManager(ns=self.spnNeigbourhood.value())
    self.model.createMlp(self.inputs["initial"],
                         self.inputs["factors"].values(),
                         self.inputs["changeMap"],
                         [int(n) for n in self.leTopology.text().split(" ")]
                        )

    self.model.setTrainingData(self.inputs["initial"],
                               self.inputs["factors"].values(),
                               self.inputs["final"],
                               mode=self.inputs["samplingMode"],
                               samples=self.plugin.spnSamplesCount.value()
                              )

    self.model.setEpochs(self.spnMaxIterations.value())
    self.model.setValPercent(20)
    self.model.setLRate(self.spnLearnRate.value())
    self.model.setMomentum(self.spnMomentum.value())
    self.model.setContinueTrain()

    self.dataTrain = [1]
    self.dataVal = [1]
    self.plotTrain = self.axes.plot(self.dataTrain,
                                    linewidth=1,
                                    color="green",
                                   )[0]
    self.plotVal = self.axes.plot(self.dataVal,
                                  linewidth=1,
                                  color="red",
                                 )[0]

    self.model.moveToThread(self.plugin.workThread)

    self.plugin.workThread.started.connect(self.model.startTrain)
    self.model.updateGraph.connect(self.__updateGraph)
    self.model.updateDeltaRMS.connect(self.__updateRMS)
    self.model.updateMinValErr.connect(self.__updateValidationError)
    self.model.processFinished.connect(self.__trainFinished)
    self.model.processFinished.connect(self.plugin.workThread.quit)

    self.plugin.workThread.start()

    self.inputs["model"] = self.model

  def __trainFinished(self):
    self.plugin.workThread.started.disconnect(self.model.startTrain)

  def __updateRMS(self, dRMS):
    self.leDeltaRMS.setText(QString.number(dRMS))

  def __updateValidationError(self, error):
    self.leValidationError.setText(QString.number(error))

  def __updateGraph(self, errTrain, errVal):
    self.dataTrain.append(errTrain)
    self.dataVal.append(errVal)

    ymin = min([min(self.dataTrain), min(self.dataVal)])
    ymax = max([max(self.dataTrain), max(self.dataVal)])

    self.axes.set_xbound(lower=0, upper=len(self.dataVal))
    self.axes.set_ybound(lower=ymin, upper=ymax)

    self.plotTrain.set_xdata(numpy.arange(len(self.dataTrain)))
    self.plotTrain.set_ydata(numpy.array(self.dataTrain))

    self.plotVal.set_xdata(numpy.arange(len(self.dataVal)))
    self.plotVal.set_ydata(numpy.array(self.dataVal))

    self.canvas.draw()

  def __selectFile(self):
    senderName = self.sender().objectName()

    # TODO: implement dialog for necessary data type
    fileName = utils.saveRasterDialog(self,
                                      self.settings,
                                      self.tr("Save file"),
                                      self.tr("GeoTIFF (*.tif *.tiff *.TIF *.TIFF)")
                                     )
    if fileName.isEmpty():
      return

    if senderName == "btnSelectReport":
      self.leReportPath.setText(fileName)
    elif senderName == "btnSelectSamples":
      self.leSamplesPath.setText(fileName)

  def __toggleLineEdit(self, checked):
    senderName = self.sender().objectName()
    if senderName == "chkCreateReport":
      if checked:
        self.leReportPath.setEnabled(True)
        self.btnSelectReport.setEnabled(True)
      else:
        self.leReportPath.setEnabled(False)
        self.btnSelectReport.setEnabled(False)
    elif senderName == "chkSaveSamples":
      if checked:
        self.leSamplesPath.setEnabled(True)
        self.btnSelectSamples.setEnabled(True)
      else:
        self.leSamplesPath.setEnabled(False)
        self.btnSelectSamples.setEnabled(False)
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
        
    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 )
        
        self.show()
        
    def drawPlot(self):
        QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))#show the user this may take a long time...

        self.axes.clear()
        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
            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())
                            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())
                        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())
                        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())
                    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
            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())
                            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())
                        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())
                        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())
                    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
            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())
                            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())
                        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())
                        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())
                    i += 1

        #rs.close() # close the cursor
        myconnection.closedb()  # 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.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  == "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),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]) 

    def LastSelections(self):#set same selections as last plot
        #table1
        searchindex = self.table_ComboBox_1.findText(self.ms.settingsdict['custplot_table1'])
        if searchindex >= 0:
            self.table_ComboBox_1.setCurrentIndex(searchindex)
            self.Table1Changed()
            searchindex = self.xcol_ComboBox_1.findText(self.ms.settingsdict['custplot_xcol1'])
            if searchindex >= 0:
                self.xcol_ComboBox_1.setCurrentIndex(searchindex)
            searchindex = self.ycol_ComboBox_1.findText(self.ms.settingsdict['custplot_ycol1'])
            if searchindex >= 0:
                self.ycol_ComboBox_1.setCurrentIndex(searchindex)
        #table2
        self.tabWidget.setCurrentIndex(int(self.ms.settingsdict['custplot_tabwidget']))
        searchindex = self.table_ComboBox_2.findText(self.ms.settingsdict['custplot_table2'])
        if searchindex >= 0:
            self.table_ComboBox_2.setCurrentIndex(searchindex)
            self.Table2Changed()
            searchindex = self.xcol_ComboBox_2.findText(self.ms.settingsdict['custplot_xcol2'])
            if searchindex >= 0:
                self.xcol_ComboBox_2.setCurrentIndex(searchindex)
            searchindex = self.ycol_ComboBox_2.findText(self.ms.settingsdict['custplot_ycol2'])
            if searchindex >= 0:
                self.ycol_ComboBox_2.setCurrentIndex(searchindex)
        #table3
        searchindex = self.table_ComboBox_3.findText(self.ms.settingsdict['custplot_table3'])
        if searchindex >= 0:
            self.table_ComboBox_3.setCurrentIndex(searchindex)
            self.Table3Changed()
            searchindex = self.xcol_ComboBox_3.findText(self.ms.settingsdict['custplot_xcol3'])
            if searchindex >= 0:
                self.xcol_ComboBox_3.setCurrentIndex(searchindex)
            searchindex = self.ycol_ComboBox_3.findText(self.ms.settingsdict['custplot_ycol3'])
            if searchindex >= 0:
                self.ycol_ComboBox_3.setCurrentIndex(searchindex)
        #filtre1_1
        searchindex = self.Filter1_ComboBox_1.findText(self.ms.settingsdict['custplot_filter1_1'])
        if searchindex >= 0:
            self.Filter1_ComboBox_1.setCurrentIndex(searchindex)
            self.FilterChanged(1, 1)
        #filtre2_1
        searchindex = self.Filter2_ComboBox_1.findText(self.ms.settingsdict['custplot_filter2_1'])
        if searchindex >= 0:
            self.Filter2_ComboBox_1.setCurrentIndex(searchindex)
            self.FilterChanged(2, 1)
        #filtre1_2
        searchindex = self.Filter1_ComboBox_2.findText(self.ms.settingsdict['custplot_filter1_2'])
        if searchindex >= 0:
            self.Filter1_ComboBox_2.setCurrentIndex(searchindex)
            self.FilterChanged( 1, 2)
        #filtre2_2
        searchindex = self.Filter2_ComboBox_2.findText(self.ms.settingsdict['custplot_filter2_2'])
        if searchindex >= 0:
            self.Filter2_ComboBox_2.setCurrentIndex(searchindex)
            self.FilterChanged(2, 2)
        #filtre1_3
        searchindex = self.Filter1_ComboBox_3.findText(self.ms.settingsdict['custplot_filter1_3'])
        if searchindex >= 0:
            self.Filter1_ComboBox_3.setCurrentIndex(searchindex)
            self.FilterChanged(1, 3)
        #filtre2_3
        searchindex = self.Filter2_ComboBox_3.findText(self.ms.settingsdict['custplot_filter2_3'])
        if searchindex >= 0:
            self.Filter2_ComboBox_3.setCurrentIndex(searchindex)
            self.FilterChanged(2, 3) 
        #filtre1_1_selection
        for index in xrange(self.Filter1_QListWidget_1.count()):
            for item in self.ms.settingsdict['custplot_filter1_1_selection']:
                if self.Filter1_QListWidget_1.item(index).text()==item:#earlier str(item) but that caused probs for non-ascii
                     self.Filter1_QListWidget_1.item(index).setSelected(True)
        #filtre2_1_selection
        for index in xrange(self.Filter2_QListWidget_1.count()):
            for item in self.ms.settingsdict['custplot_filter2_1_selection']:
                if self.Filter2_QListWidget_1.item(index).text()==item:#earlier str(item) but that caused probs for non-ascii
                     self.Filter2_QListWidget_1.item(index).setSelected(True)
        #filtre1_2_selection
        for index in xrange(self.Filter1_QListWidget_2.count()):
            for item in self.ms.settingsdict['custplot_filter1_2_selection']:
                if self.Filter1_QListWidget_2.item(index).text()==item:#earlier str(item) but that caused probs for non-ascii
                     self.Filter1_QListWidget_2.item(index).setSelected(True)
        #filtre2_2_selection
        for index in xrange(self.Filter2_QListWidget_2.count()):
            for item in self.ms.settingsdict['custplot_filter2_2_selection']:
                if self.Filter2_QListWidget_2.item(index).text()==item:#earlier str(item) but that caused probs for non-ascii
                     self.Filter2_QListWidget_2.item(index).setSelected(True)
        #filtre1_3_selection
        for index in xrange(self.Filter1_QListWidget_3.count()):
            for item in self.ms.settingsdict['custplot_filter1_3_selection']:
                if self.Filter1_QListWidget_3.item(index).text()==item:#earlier str(item) but that caused probs for non-ascii
                     self.Filter1_QListWidget_3.item(index).setSelected(True)
        #filtre2_3_selection
        for index in xrange(self.Filter2_QListWidget_3.count()):
            for item in self.ms.settingsdict['custplot_filter2_3_selection']:
                if self.Filter2_QListWidget_3.item(index).text()==item:#earlier str(item) but that caused probs for non-ascii
                     self.Filter2_QListWidget_3.item(index).setSelected(True)
        #plottype1
        searchindex = self.PlotType_comboBox_1.findText(self.ms.settingsdict['custplot_plottype1'])
        if searchindex >= 0:
            self.PlotType_comboBox_1.setCurrentIndex(searchindex)
        #plottype2
        searchindex = self.PlotType_comboBox_2.findText(self.ms.settingsdict['custplot_plottype2'])
        if searchindex >= 0:
            self.PlotType_comboBox_2.setCurrentIndex(searchindex)
        #plottype3
        searchindex = self.PlotType_comboBox_3.findText(self.ms.settingsdict['custplot_plottype3'])
        if searchindex >= 0:
            self.PlotType_comboBox_3.setCurrentIndex(searchindex)
        #max time step, titles, grid, legend
        self.spnmaxtstep.setValue(self.ms.settingsdict['custplot_maxtstep'])
        if len(self.ms.settingsdict['custplot_title'])>0:
            self.title_QLineEdit.setText(self.ms.settingsdict['custplot_title'])
        if len(self.ms.settingsdict['custplot_xtitle'])>0:
            self.xtitle_QLineEdit.setText(self.ms.settingsdict['custplot_xtitle'])
        if len(self.ms.settingsdict['custplot_ytitle'])>0:
            self.ytitle_QLineEdit.setText(self.ms.settingsdict['custplot_ytitle'])
        if self.ms.settingsdict['custplot_legend']==2:
            self.Legend_checkBox.setChecked(True)
        else:
            self.Legend_checkBox.setChecked(False)
        if self.ms.settingsdict['custplot_grid']==2:
            self.Grid_checkBox.setChecked(True)
        else:
            self.Grid_checkBox.setChecked(False)
            
    def LoadTablesFromDB( self ):    # Open the SpatiaLite file to extract info about tables 
        self.table_ComboBox_1.clear()  
        self.table_ComboBox_2.clear()  
        self.table_ComboBox_3.clear()  
        for i in range (1,3):
            self.clearthings(i)
        myconnection = utils.dbconnection()
        if myconnection.connect2db() == True:
            # skapa en cursor
            curs = myconnection.conn.cursor()
            rs=curs.execute(r"""SELECT tbl_name FROM sqlite_master WHERE (type='table' or type='view') and not (name in""" + midvatten_defs.SQLiteInternalTables() + r""") 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 curs:
                self.table_ComboBox_1.addItem(row[0])
                self.table_ComboBox_2.addItem(row[0])
                self.table_ComboBox_3.addItem(row[0])
            
            rs.close()
            myconnection.closedb()        

    def LoadColumnsFromTable(self, table=''):
        """ This method returns a list with all the columns in the table"""
        if len(table)>0:            # Should not be needed since the function never should be called without existing table...
            myconnection = utils.dbconnection()
            if myconnection.connect2db() == True:
                # skapa en cursor
                curs = myconnection.conn.cursor()
                sql = r"""SELECT * FROM '"""
                sql += unicode(table)
                sql += """'"""     
                rs=curs.execute(sql)
                columns = {} 
                columns = [tuple[0] for tuple in curs.description]
                rs.close()
                myconnection.closedb()        
        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 clearthings(self,tabno=1):   #clear xcol,ycol,filter1,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.ms.settingsdict['custplot_table1'] = 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.ms.settingsdict['custplot_table2'] = 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.ms.settingsdict['custplot_table2'] = 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 FilterChanged(self, filterno, tabno):
        TableCombobox = 'table_ComboBox_' + str(tabno)
        FilterCombobox = 'Filter' + str(filterno) + '_ComboBox_' + str(tabno)
        FilterQListWidget = 'Filter' + str(filterno) + '_QListWidget_' + str(tabno)
        getattr(self,FilterQListWidget).clear()
        if not getattr(self,FilterCombobox).currentText()=='':
            self.PopulateFilterList(getattr(self,TableCombobox).currentText(),FilterQListWidget,getattr(self,FilterCombobox).currentText())
        
    def Filter1_1Changed(self):
        self.FilterChanged(1,1)
    
    def Filter2_1Changed(self):
        self.FilterChanged(2,1)

    def Filter1_2Changed(self):
        self.FilterChanged(1,2)
            
    def Filter2_2Changed(self):
        self.FilterChanged(2,2)

    def Filter1_3Changed(self):
        self.FilterChanged(1,3)
        
    def Filter2_3Changed(self):
        self.FilterChanged(2,3)
                        
    def PopulateFilterList(self, table, QListWidgetname='', filtercolumn=None):
        sql = "select distinct " + unicode(filtercolumn) + " from " + table + " order by " + unicode(filtercolumn)
        ConnectionOK, list_data=utils.sql_load_fr_db(sql)
        for post in list_data:
            item = QtGui.QListWidgetItem(unicode(post[0]))
            getattr(self, QListWidgetname).addItem(item)

    def refreshPlot( self ):
        self.storesettings()    #all custom plot related settings are stored when plotting data (or pressing "redraw")
        self.axes.legend_=None
        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.custplotfigure.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.custplotfigure.autofmt_xdate()
        self.canvas.draw()
        plt.close(self.custplotfigure)#this closes reference to self.custplotfigure 

    def storesettings(self):
        self.ms.settingsdict['custplot_table1'] = unicode(self.table_ComboBox_1.currentText())
        self.ms.settingsdict['custplot_xcol1'] = unicode(self.xcol_ComboBox_1.currentText())
        self.ms.settingsdict['custplot_ycol1'] = unicode(self.ycol_ComboBox_1.currentText())
        self.ms.settingsdict['custplot_table2'] = unicode(self.table_ComboBox_2.currentText())
        self.ms.settingsdict['custplot_xcol2'] = unicode(self.xcol_ComboBox_2.currentText())
        self.ms.settingsdict['custplot_ycol2'] = unicode(self.ycol_ComboBox_2.currentText())
        self.ms.settingsdict['custplot_table3'] = unicode(self.table_ComboBox_3.currentText())
        self.ms.settingsdict['custplot_xcol3'] = unicode(self.xcol_ComboBox_3.currentText())
        self.ms.settingsdict['custplot_ycol3'] = unicode(self.ycol_ComboBox_3.currentText())
        self.ms.settingsdict['custplot_filter1_1']=unicode(self.Filter1_ComboBox_1.currentText())
        self.ms.settingsdict['custplot_filter2_1']=unicode(self.Filter2_ComboBox_1.currentText())
        self.ms.settingsdict['custplot_filter1_2']=unicode(self.Filter1_ComboBox_2.currentText())
        self.ms.settingsdict['custplot_filter2_2']=unicode(self.Filter2_ComboBox_2.currentText())
        self.ms.settingsdict['custplot_filter1_3']=unicode(self.Filter1_ComboBox_3.currentText())
        self.ms.settingsdict['custplot_filter2_3']=unicode(self.Filter2_ComboBox_3.currentText())
        self.ms.settingsdict['custplot_filter1_1_selection']=[]
        self.ms.settingsdict['custplot_filter2_1_selection']=[]
        self.ms.settingsdict['custplot_filter1_2_selection']=[]
        self.ms.settingsdict['custplot_filter2_2_selection']=[]
        self.ms.settingsdict['custplot_filter1_3_selection']=[]
        self.ms.settingsdict['custplot_filter2_3_selection']=[]
        for item in self.Filter1_QListWidget_1.selectedItems(): 
            self.ms.settingsdict['custplot_filter1_1_selection'].append(unicode(item.text()))
        for item in self.Filter2_QListWidget_1.selectedItems(): 
            self.ms.settingsdict['custplot_filter2_1_selection'].append(unicode(item.text()))
        for item in self.Filter1_QListWidget_2.selectedItems(): 
            self.ms.settingsdict['custplot_filter1_2_selection'].append(unicode(item.text()))
        for item in self.Filter2_QListWidget_2.selectedItems(): 
            self.ms.settingsdict['custplot_filter2_2_selection'].append(unicode(item.text()))
        for item in self.Filter1_QListWidget_3.selectedItems(): 
            self.ms.settingsdict['custplot_filter1_3_selection'].append(unicode(item.text()))
        for item in self.Filter2_QListWidget_3.selectedItems(): 
            self.ms.settingsdict['custplot_filter2_3_selection'].append(unicode(item.text()))
        self.ms.settingsdict['custplot_plottype1']=unicode(self.PlotType_comboBox_1.currentText())
        self.ms.settingsdict['custplot_plottype2']=unicode(self.PlotType_comboBox_2.currentText())
        self.ms.settingsdict['custplot_plottype3']=unicode(self.PlotType_comboBox_3.currentText())
        self.ms.settingsdict['custplot_maxtstep'] = self.spnmaxtstep.value()
        self.ms.settingsdict['custplot_legend']=self.Legend_checkBox.checkState()
        self.ms.settingsdict['custplot_grid']=self.Grid_checkBox.checkState()
        self.ms.settingsdict['custplot_title'] = unicode(self.title_QLineEdit.text())
        self.ms.settingsdict['custplot_xtitle'] = unicode(self.xtitle_QLineEdit.text())
        self.ms.settingsdict['custplot_ytitle'] = unicode(self.ytitle_QLineEdit.text())
        self.ms.settingsdict['custplot_tabwidget'] = self.tabWidget.currentIndex()
        self.ms.save_settings()
Exemple #10
0
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(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 = unicode(self.Filter1_ComboBox_1.currentText())
            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
            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 """ + 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())
                            i += 1
                elif not (filter1 == '' or filter1==' '):
                    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())
                        i += 1
                elif not (filter2 == '' or filter2==' '):
                    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())
                        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())
                    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 = unicode(self.Filter1_ComboBox_2.currentText())
            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
            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 """ + unicode(self.xcol2) + """, """ + unicode(self.ycol2) + """ from """ + unicode(self.table2) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' and """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol2)
                            self.plabels[i] = unicode(item1.text()) + """, """ + 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 """ + unicode(self.xcol2) + """, """ + unicode(self.ycol2) + """ from """ + unicode(self.table2) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' order by """ + unicode(self.xcol2)
                        self.plabels[i] = 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 """ + unicode(self.xcol2) + """, """ + unicode(self.ycol2) + """ from """ + unicode(self.table2) + """ where """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol2)
                        self.plabels[i] = unicode(item2.text())
                        self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_2.currentText())
                        i += 1            
                else:
                    sql = r""" select """ + unicode(self.xcol2) + """, """ + unicode(self.ycol2) + """ from """ + unicode(self.table2) + """ order by """ + unicode(self.xcol2)
                    self.plabels[i] = unicode(self.ycol2)+""", """+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 = unicode(self.Filter1_ComboBox_3.currentText())
            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
            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 """ + unicode(self.xcol3) + """, """ + unicode(self.ycol3) + """ from """ + unicode(self.table3) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' and """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol3)
                            self.plabels[i] = unicode(item1.text()) + """, """ + 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 """ + unicode(self.xcol3) + """, """ + unicode(self.ycol3) + """ from """ + unicode(self.table3) + """ where """ + filter1 + """='""" + unicode(item1.text())+ """' order by """ + unicode(self.xcol3)
                        self.plabels[i] = 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 """ + unicode(self.xcol3) + """, """ + unicode(self.ycol3) + """ from """ + unicode(self.table3) + """ where """ + filter2 + """='""" + unicode(item2.text())+ """' order by """ + unicode(self.xcol3)
                        self.plabels[i] = unicode(item2.text())
                        self.createsingleplotobject(sql,i,My_format,curs,self.PlotType_comboBox_3.currentText())
                        i += 1            
                else:
                    sql = r""" select """ + unicode(self.xcol3) + """, """ + unicode(self.ycol3) + """ from """ + unicode(self.table3) + """ order by """ + unicode(self.xcol3)
                    self.plabels[i] = unicode(self.ycol3)+""", """+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',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',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]) 
                
    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...
        path = QtGui.QFileDialog.getOpenFileName(None,QtCore.QString.fromLocal8Bit("Select database:"),"*.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( 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( 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 = 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 = 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 = 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(unicode(self.database))  
            curs = conn.cursor()
            sql = r"""SELECT * FROM '"""
            sql += 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 " + unicode(filtercolumn) + " from " + table + " order by " + unicode(filtercolumn)
        list_data=sql_load_fr_db(self.database, sql)
        for post in list_data:
            item = QtGui.QListWidgetItem(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) 
class StatistDialog(QDialog, Ui_StatistDialog):
    def __init__(self, iface):
        QDialog.__init__(self)
        self.iface = iface
        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.btnOk = self.buttonBox.button(QDialogButtonBox.Ok)
        self.btnClose = self.buttonBox.button(QDialogButtonBox.Close)

        self.cmbLayers.currentIndexChanged.connect(self.reloadFields)
        self.chkUseTextFields.stateChanged.connect(self.reloadFields)

        self.chkShowGrid.stateChanged.connect(self.refreshPlot)
        self.chkAsPlot.stateChanged.connect(self.refreshPlot)
        self.btnRefresh.clicked.connect(self.refreshPlot)

        self.manageGui()
        self.axes.set_title(self.tr("Frequency distribution"))

    def manageGui(self):
        self.cmbLayers.clear()
        self.cmbLayers.addItems(utils.getVectorLayerNames())

        self.btnRefresh.setEnabled(False)

    def reloadFields(self):
        self.cmbFields.clear()

        self.axes.clear()
        self.lstStatistics.clearContents()
        self.lstStatistics.setRowCount(0)

        self.spnMinX.setValue(0.0)
        self.spnMaxX.setValue(0.0)

        layer = utils.getVectorLayerByName(self.cmbLayers.currentText())

        if layer.selectedFeatureCount() != 0:
            self.chkUseSelected.setCheckState(Qt.Checked)
        else:
            self.chkUseSelected.setCheckState(Qt.Unchecked)

        if self.chkUseTextFields.checkState():
            self.cmbFields.addItems(utils.getFieldNames(layer, [QVariant.String]))
        else:
            self.cmbFields.addItems(utils.getFieldNames(layer, [QVariant.Int, QVariant.Double]))

    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())

        if self.chkUseSelected.isChecked() and \
                layer.selectedFeatureCount() == 0:
            QMessageBox.warning(self,
                                self.tr('No selection'),
                                self.tr('There is no selection in input '
                                        'layer. Uncheck corresponding option '
                                        'or select some features before '
                                        'running analysis'))
            return

        self.workThread = statistthread.StatistThread(layer,
                                                      self.cmbFields.currentText(),
                                                      self.chkUseSelected.isChecked()
                                                     )
        self.workThread.rangeChanged.connect(self.setProgressRange)
        self.workThread.updateProgress.connect(self.updateProgress)
        self.workThread.processFinished.connect(self.processFinished)
        self.workThread.processInterrupted.connect(self.processInterrupted)

        self.btnOk.setEnabled(False)
        self.btnClose.setText(self.tr("Cancel"))
        self.buttonBox.rejected.disconnect(self.reject)
        self.btnClose.clicked.connect(self.stopProcessing)

        self.workThread.start()

    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):
        self.stopProcessing()

        # 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):
            tmp = self.tableData[i].split(":")
            item = QTableWidgetItem(tmp[0])
            self.lstStatistics.setItem(i, 0, item)
            item = QTableWidgetItem(tmp[1])
            self.lstStatistics.setItem(i, 1, item)

        self.lstStatistics.resizeRowsToContents()

        self.btnRefresh.setEnabled(True)

        # create histogram
        self.refreshPlot()

        self.restoreGui()

    def processInterrupted(self):
        self.restoreGui()

    def stopProcessing(self):
        if self.workThread is not None:
            self.workThread.stop()
            self.workThread = None

    def restoreGui(self):
        self.progressBar.setFormat("%p%")
        self.progressBar.setRange(0, 1)
        self.progressBar.setValue(0)

        self.buttonBox.rejected.connect(self.reject)
        self.btnClose.clicked.disconnect(self.stopProcessing)
        self.btnClose.setText(self.tr("Close"))
        self.btnOk.setEnabled(True)

    def refreshPlot(self):
        self.axes.clear()
        self.axes.set_title(self.tr("Frequency distribution"))
        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")
        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.cmbFields.currentText()))
        self.figure.autofmt_xdate()
        self.canvas.draw()

    def keyPressEvent(self, event):
        if event.modifiers() in [Qt.ControlModifier, Qt.MetaModifier] and event.key() == Qt.Key_C:
            clipboard = QApplication.clipboard()
            clipboard.setText("\n".join(self.tableData))
        else:
            QDialog.keyPressEvent(self, event)
Exemple #12
0
class MplCanvas(QWidget):
    """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
    def __init__(self, parent=None):
        super(MplCanvas, self).__init__(parent)
        #屏幕图片分辨率
        self.fig = Figure(figsize=(8, 6), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.canvas.setParent(parent)
        #调整画布区
        self.fig.subplots_adjust(left=0.02, bottom=0.08, top=0.95, right=0.95)
        self.fig.clear()
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.addWidget(self.canvas)
        self.mpl_toolbar = NavigationToolbar(self.canvas,
                                             parent,
                                             coordinates=False)
        #self._init_MplToolBar()
        self.mpl_toolbar.hide()
        #self.layout.addWidget(self.mpl_toolbar)
        self.setLayout(self.layout)
        self._init_Axes()

    def _init_MplToolBar(self):
        """设置toolbar上的功能键"""
        a = self.mpl_toolbar.actions()
        for i in a:
            if i.iconText() == 'Home':
                i.setToolTip(u'初始视图')
            elif i.iconText() == 'Back':
                i.setToolTip(u'后退')
            elif i.iconText() == 'Forward':
                i.setToolTip(u'前进')
            elif i.iconText() == 'Pan':
                i.setToolTip(u'鼠标左键平移,右键横竖缩放')
            elif i.iconText() == 'Zoom':
                i.setToolTip(u'局部缩放')
            elif i.iconText() == 'Subplots':
                self.mpl_toolbar.removeAction(i)
            elif i.iconText() == 'Customize':
                self.mpl_toolbar.removeAction(i)
            elif i.iconText() == 'Save':
                i.setToolTip(u'保存图片')

    def _init_Axes(self):
        self.axes = self.fig.add_subplot(111)
        self.axes.yaxis.set_visible(False)
        #self.axes.tick_params(axis='y', left='off', labelleft='off', width=0)
        self.axes.tick_params(axis='x', top='off')
        self.axes.spines['right'].set_visible(False)
        self.axes.spines['top'].set_visible(False)
        self.axes.spines['left'].set_visible(False)
        self.axes.spines['bottom'].set_visible(True)
        self.axes.set_xlabel(u'时间(s)')
        self.cur_axes = self.axes
        self.x_left, self.x_right = self.cur_axes.get_xlim()
        self.y_bottom, self.y_top = self.cur_axes.get_ylim()

    def _init_View(self):
        """
        记录当前canvas
        """
        self.mpl_toolbar.update()
        self.mpl_toolbar.push_current()
        self.x_left, self.x_right = self.cur_axes.get_xlim()
        self.y_bottom, self.y_top = self.cur_axes.get_ylim()
class StatistDialog(QDialog, Ui_StatistDialog):
    def __init__(self, iface):
        QDialog.__init__(self)
        self.iface = iface
        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.btnOk = self.buttonBox.button(QDialogButtonBox.Ok)
        self.btnClose = self.buttonBox.button(QDialogButtonBox.Close)

        self.cmbLayers.currentIndexChanged.connect(self.reloadFields)
        self.chkUseTextFields.stateChanged.connect(self.reloadFields)

        self.chkShowGrid.stateChanged.connect(self.refreshPlot)
        self.chkAsPlot.stateChanged.connect(self.refreshPlot)
        self.btnRefresh.clicked.connect(self.refreshPlot)

        self.manageGui()
        self.axes.set_title(self.tr("Frequency distribution"))

    def manageGui(self):
        self.cmbLayers.clear()
        self.cmbLayers.addItems(utils.getVectorLayerNames())

        self.btnRefresh.setEnabled(False)

    def reloadFields(self):
        self.cmbFields.clear()

        self.axes.clear()
        self.lstStatistics.clearContents()
        self.lstStatistics.setRowCount(0)

        self.spnMinX.setValue(0.0)
        self.spnMaxX.setValue(0.0)

        layer = utils.getVectorLayerByName(self.cmbLayers.currentText())

        if layer.selectedFeatureCount() != 0:
            self.chkUseSelected.setCheckState(Qt.Checked)
        else:
            self.chkUseSelected.setCheckState(Qt.Unchecked)

        if self.chkUseTextFields.checkState():
            self.cmbFields.addItems(
                utils.getFieldNames(layer, [QVariant.String]))
        else:
            self.cmbFields.addItems(
                utils.getFieldNames(layer, [QVariant.Int, QVariant.Double]))

    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())

        if self.chkUseSelected.isChecked() and \
                layer.selectedFeatureCount() == 0:
            QMessageBox.warning(
                self, self.tr('No selection'),
                self.tr('There is no selection in input '
                        'layer. Uncheck corresponding option '
                        'or select some features before '
                        'running analysis'))
            return

        self.workThread = statistthread.StatistThread(
            layer, self.cmbFields.currentText(),
            self.chkUseSelected.isChecked())
        self.workThread.rangeChanged.connect(self.setProgressRange)
        self.workThread.updateProgress.connect(self.updateProgress)
        self.workThread.processFinished.connect(self.processFinished)
        self.workThread.processInterrupted.connect(self.processInterrupted)

        self.btnOk.setEnabled(False)
        self.btnClose.setText(self.tr("Cancel"))
        self.buttonBox.rejected.disconnect(self.reject)
        self.btnClose.clicked.connect(self.stopProcessing)

        self.workThread.start()

    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):
        self.stopProcessing()

        # 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):
            tmp = self.tableData[i].split(":")
            item = QTableWidgetItem(tmp[0])
            self.lstStatistics.setItem(i, 0, item)
            item = QTableWidgetItem(tmp[1])
            self.lstStatistics.setItem(i, 1, item)

        self.lstStatistics.resizeRowsToContents()

        self.btnRefresh.setEnabled(True)

        # create histogram
        self.refreshPlot()

        self.restoreGui()

    def processInterrupted(self):
        self.restoreGui()

    def stopProcessing(self):
        if self.workThread is not None:
            self.workThread.stop()
            self.workThread = None

    def restoreGui(self):
        self.progressBar.setFormat("%p%")
        self.progressBar.setRange(0, 1)
        self.progressBar.setValue(0)

        self.buttonBox.rejected.connect(self.reject)
        self.btnClose.clicked.disconnect(self.stopProcessing)
        self.btnClose.setText(self.tr("Close"))
        self.btnOk.setEnabled(True)

    def refreshPlot(self):
        self.axes.clear()
        self.axes.set_title(self.tr("Frequency distribution"))
        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")
        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.cmbFields.currentText()))
        self.figure.autofmt_xdate()
        self.canvas.draw()

    def keyPressEvent(self, event):
        if event.modifiers() in [Qt.ControlModifier, Qt.MetaModifier
                                 ] and event.key() == Qt.Key_C:
            clipboard = QApplication.clipboard()
            clipboard.setText("\n".join(self.tableData))
        else:
            QDialog.keyPressEvent(self, event)
class MatplotlibWidget(QtGui.QWidget):
    '''Base class for matplotlib widgets
    '''
    def __init__(self, parent):
        '''Inits matplotlib widget.
        
        Args:
            parent: A Parent class object.
        '''
        super().__init__()
        self.main_frame = parent
        self.dpi = 75
        self.show_axis_ticks = True
        self.__create_frame()


    def __create_frame(self):
        self.fig = Figure((5.0, 3.0), dpi=self.dpi)
        self.fig.patch.set_facecolor("white")
        self.canvas = FigureCanvas(self.fig)
        self.canvas.manager = MockManager(self.main_frame)
        self.canvas.setParent(self.main_frame)
        self.axes = self.fig.add_subplot(111)
        
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)
        hbox = QtGui.QHBoxLayout()
        
        self.main_frame.ui.matplotlib_layout.addWidget(self.canvas)
        self.main_frame.ui.matplotlib_layout.addWidget(self.mpl_toolbar)
        self.main_frame.ui.matplotlib_layout.addLayout(hbox)


    def fork_toolbar_buttons(self):
        '''Remove figure options & subplot config that might not work properly.
        '''
        try:
            self.mpl_toolbar.removeAction(self.mpl_toolbar.children()[21]) 
            self.mpl_toolbar.removeAction(self.mpl_toolbar.children()[17])
        except:
            pass  # Already removed
    
    
    def remove_axes_ticks(self):
        '''Remove ticks from axes.
        '''
        if not self.show_axis_ticks:
            for tick in self.axes.yaxis.get_major_ticks():
                tick.label1On = False
                tick.label2On = False
            for tick in self.axes.xaxis.get_major_ticks():
                tick.label1On = False
                tick.label2On = False
                
                
    def delete(self):
        '''Delete matplotlib objects.
        '''
        self.axes.clear()  # Might be useless with fig.clf()
        self.canvas.close()
        self.fig.clf()
        self.close()
        
        del self.fig
        del self.canvas
        del self.axes
        
        import gc
        gc.collect()
class ProfilefromPointsDialog(QDialog, Ui_ProfilefromPoints):
    def __init__(self,iface):
        QDialog.__init__(self)
        # 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.iface = iface
        
        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)
        self.figure.patch.set_visible(False)
        
        # 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.btnOk = self.buttonBox.button(QDialogButtonBox.Ok)
        self.btnClose = self.buttonBox.button(QDialogButtonBox.Close)

        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()
        self.uPointLayer.addItems(utils.getPointLayerNames())
        self.uLineLayer.clear()
        self.uLineLayer.addItems(utils.getLineLayerNames())

    
    def reloadFields(self):
        print 'reload fields'
        self.uZfield.clear()
        self.uOrderField.clear()

        self.axes.clear()

        point_layer = processing.getObject(str(self.uPointLayer.currentText()))
        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]))

    def checkSelectedLine(self):
        print 'check if line layer selected'
        line_layer = processing.getObject(str(self.uLineLayer.currentText()))
        if line_layer:
            if line_layer.selectedFeatureCount() != 0:
                self.uSelectedLine.setCheckState(Qt.Checked)
            else:
                self.uSelectedLine.setCheckState(Qt.Unchecked)

             
    def accept(self):
        print 'accepted'
        
        self.axes.clear()

        point_layer = processing.getObject(self.uPointLayer.currentText())
        line_layer = processing.getObject(self.uLineLayer.currentText())
        z_field=(self.uZfield.currentText())
        order_field=str(self.uOrderField.currentText())
        if str(self.uOrder.currentText())=='Ascending':
            sort = 'ASC'
        else:
            sort = 'DESC'
        buff=float(self.uBuffer.displayText())
        
        if self.utabWidget.currentIndex()==0:
            createLine=True        
        else:
            createLine=False
        



        if self.uSelectedPoints.isChecked() and \
                point_layer.selectedFeatureCount() == 0 or self.uSelectedLine.isChecked() and \
                line_layer.selectedFeatureCount() == 0:
            QMessageBox.warning(self,
                                self.tr('No selection'),
                                self.tr('There is no selection in input '
                                        'layer. Uncheck corresponding option '
                                        'or select some features before '
                                        'running analysis'))
            return
        
        if not createLine and not self.uSelectedLine.isChecked() and \
                line_layer.featureCount() != 1:
            QMessageBox.warning(self,
                                self.tr('Line Layer Error'),
                                self.tr('There are multiple line features within the line layer.\n Please select one.'))
            return
        
        if utils.checkMultipart(point_layer):
            QMessageBox.warning(self,
                                self.tr('Point Layer Error'),
                                self.tr('Point layer has multi-part geometery.\n Please convert to single part geometery.'))
            return
            
        if not createLine and utils.checkMultipart(line_layer):
            QMessageBox.warning(self,
                                self.tr('Line Layer Error'),
                                self.tr('Line layer has multi-part geometery.\n Please convert to single part geometery.'))
            return
        
        selected_points = self.uSelectedPoints.checkState()
        selected_line = self.uSelectedLine.checkState()

        self.workThread = profilefrompoints_thread.ProfilefromPointsThread(point_layer,z_field,createLine,order_field,sort,line_layer,buff,selected_points,selected_line)
        

        self.workThread.processFinished.connect(self.processFinished)
        self.workThread.processInterrupted.connect(self.processInterrupted)

        self.btnOk.setEnabled(False)
        self.btnClose.setText(self.tr("Cancel"))
        self.buttonBox.rejected.disconnect(self.reject)
        self.btnClose.clicked.connect(self.stopProcessing)
        
        self.uprogressBar.setMaximum(0)
        self.workThread.start()
        
        self.dbase=os.path.join( os.environ['HOME'],'Desktop','tmp_'+point_layer.name()+'.sqlite')

        
    def reject(self):
        print 'rejected'
        QDialog.reject(self)



    def processFinished(self, values):
        self.stopProcessing()
        self.values = values[0]
        self.uCopytoClip.setEnabled(True)
        self.iface.messageBar().pushMessage(QCoreApplication.translate("ProfilefromPoints", 'Profile from Points  - A temporary spatialite database was created at {}.  Please delete when finished'.format(self.dbase)))
      

        # create plot
        self.refreshPlot()

        self.restoreGui()

    def processInterrupted(self):
        self.restoreGui()

    def stopProcessing(self):
        if self.workThread is not None:
            self.workThread.stop()
            self.workThread = None

    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]))
        self.axes.grid()
        formatter = ScalarFormatter(useOffset=False)
        self.axes.yaxis.set_major_formatter(formatter)

        self.axes.set_ylabel(unicode(self.tr("Elevation, z field units")))
        self.axes.set_xlabel(unicode(self.tr('Station, layer units')))

        self.canvas.draw()    
            
    def copyClipboard (self):
        if self.values is None:
            return
        else:
            clipboard = QApplication.clipboard()
            clipboard.setText('\n'.join('%s\t%s' % x for x in zip(self.values[0],self.values[1])))
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("Calibrate logger") # Set the title for the dialog
        self.connect(self.pushButton, PyQt4.QtCore.SIGNAL("clicked()"), self.calibrateandplot)
        self.INFO.setText("Select the observation point with logger data to be calibrated.")
        self.log_calc_manual.setText("<a href=\"https://sites.google.com/site/midvattenpluginforqgis/usage/3-edit-data?pli=1#TOC-Calibrate-water-level-measurements-from-data-logger-\">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.show()

        self.cid =[]
                
        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.pushButtonCalcBestFit, PyQt4.QtCore.SIGNAL("clicked()"), self.calc_best_fit)

        self.connect(self.pushButton_delete_logger, PyQt4.QtCore.SIGNAL("clicked()"), lambda: self.delete_selected_range(u'w_levels_logger'))
        self.connect(self.pushButton_delete_meas, PyQt4.QtCore.SIGNAL("clicked()"), lambda: self.delete_selected_range(u'w_levels'))

        self.get_tolerance()

        # 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):
        self.combobox_obsid.clear()
        myconnection = utils.dbconnection()
        if myconnection.connect2db() == True:
            # 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:
                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")

        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 += """\nwas """ + str(self.lastcalibr[0][1]) + """ masl\nat """ +  str(self.lastcalibr[0][0])
            else:
                text = """There is no earlier known\nposition for the logger\nin """ + unicode(self.combobox_obsid.currentText())#self.obsid[0]
            self.INFO.setText(text)

    def calibrateandplot(self):
        obsid = self.load_obsid_and_init()
        if not self.LoggerPos.text() == '':
            self.calibrate()
        self.update_plot()
        
#    def calibrate(self, fr_d_t=self.FromDateTime.dateTime().toPyDateTime(), to_d_t=self.ToDateTime.dateTime().toPyDateTime()):
    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.LoggerPos.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.
        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()
        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('Calibration 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.canvas.draw()
        plt.close(self.calibrplotfigure)#this closes reference to self.calibrplotfigure
        PyQt4.QtGui.QApplication.restoreOverrideCursor()
        self.calib_help.setText("")

    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 calibrate_from_plot_selection(self):
        """ Calibrates by selecting a line node and a y-position on the plot

            The user have to click on the button three times and follow instructions.
        
            The process:
            1. Selecting a line node.
            2. Selecting a selecting a y-position from the plot.
            3. Extracting 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.
        """            
        #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()

        if self.log_pos is None:
            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))  
        
        if self.log_pos is not None and self.y_pos is 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))
            
        if self.log_pos is not None and self.y_pos is not None:
            PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor)

            if self.loggerpos_masl_or_offset_state == 1:
                logger_ts = self.head_ts
            else:
                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 idx, date_value_tuple in enumerate(logger_ts):
                raw_date, logger_value = date_value_tuple
                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 head_ts dates and logger date could be made!\nTry again or choose a new logger line node!")   
            else:
                self.LoggerPos.setText(str(float(y_pos) - float(logger_value)))

                PyQt4.QtGui.QApplication.restoreOverrideCursor()
                self.calibrateandplot()

            self.calib_help.setText("")
        
    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.log_pos = found_date
        self.reset_cid()
 
    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.reset_cid()
        
    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 - tolerance and self.meas_ts date + tolerance.
            (this could probably be change to get only the closest logger value
            inside the tolerance instead)
            (Tolerance is gotten from self.get_tolerance())
            
            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()
        tolerance = self.get_tolerance()
        really_calibrate_question = utils.askuser("YesNo", """This will calibrate all values inside the chosen period\nusing the mean difference between logger values and measurements.\n\nTime tolerance for matching logger and measurement nodes set to '""" + ' '.join(tolerance) + """'\n\nContinue?""")
        if really_calibrate_question.result == 0: # if the user wants to abort
            return

        PyQt4.QtGui.QApplication.setOverrideCursor(PyQt4.QtCore.Qt.WaitCursor)
        if self.loggerpos_masl_or_offset_state == 1:
            logger_ts = self.head_ts
        else:
            logger_ts = self.level_masl_ts



        coupled_vals = self.match_ts_values(self.meas_ts, logger_ts, tolerance)
        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 tolerance!")
        else:            
            self.LoggerPos.setText(str(utils.calc_mean_diff(coupled_vals)))
            self.calibrateandplot()
        PyQt4.QtGui.QApplication.restoreOverrideCursor()
     
    def match_ts_values(self, meas_ts, logger_ts, tolerance):
        """ 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 tolerance, default to 10 minutes
        tol = int(tolerance[0])
        tol_period = tolerance[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, -tol, tol_period)
            step_end = dateshift(meas_step, tol, tol_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 logger_step <= step_end and logger_step <= outer_end:
                if not math.isnan(float(l[1])) or l[1] == 'nan' or l[1] == '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_tolerance(self):
        """ Get the period tolerance, default to 10 minutes """
        if not self.bestFitTolerance.text():
            tol = '10 minutes'
            self.bestFitTolerance.setText(tol)
        else:
            tol = self.bestFitTolerance.text()

        tol_splitted = tol.split()
        if len(tol_splitted) != 2:
            utils.pop_up_info("Must write time resolution also, ex. 10 minutes")
        return tuple(tol_splitted)

    def loggerpos_masl_or_offset_change(self):
        if self.loggerpos_masl_or_offset_state == 1:
            self.label_11.setText("Offset relative to calibrated values:")
            self.loggerpos_masl_or_offset.setText("Change to logger position")
            self.label_adjustment_info.setText("Adjustments made from calibrated values")
            self.loggerpos_masl_or_offset_state = 0
        else:
            self.label_11.setText("Logger position, masl:")
            self.loggerpos_masl_or_offset.setText("Change to offset")
            self.label_adjustment_info.setText("Adjustments made from head")
            self.loggerpos_masl_or_offset_state = 1

    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

        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()
Exemple #17
0
class ProfilefromPointsDialog(QDialog, Ui_ProfilefromPoints):
    def __init__(self, iface):
        QDialog.__init__(self)
        # 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.iface = iface

        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)
        self.figure.patch.set_visible(False)

        # 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.btnOk = self.buttonBox.button(QDialogButtonBox.Ok)
        self.btnClose = self.buttonBox.button(QDialogButtonBox.Close)

        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()
        self.uPointLayer.addItems(utils.getPointLayerNames())
        self.uLineLayer.clear()
        self.uLineLayer.addItems(utils.getLineLayerNames())

    def reloadFields(self):
        print 'reload fields'
        self.uZfield.clear()
        self.uOrderField.clear()

        self.axes.clear()

        point_layer = processing.getObject(str(self.uPointLayer.currentText()))
        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]))

    def checkSelectedLine(self):
        print 'check if line layer selected'
        line_layer = processing.getObject(str(self.uLineLayer.currentText()))
        if line_layer:
            if line_layer.selectedFeatureCount() != 0:
                self.uSelectedLine.setCheckState(Qt.Checked)
            else:
                self.uSelectedLine.setCheckState(Qt.Unchecked)

    def accept(self):
        print 'accepted'

        self.axes.clear()

        point_layer = processing.getObject(self.uPointLayer.currentText())
        line_layer = processing.getObject(self.uLineLayer.currentText())
        z_field = (self.uZfield.currentText())
        order_field = str(self.uOrderField.currentText())
        if str(self.uOrder.currentText()) == 'Ascending':
            sort = 'ASC'
        else:
            sort = 'DESC'
        buff = float(self.uBuffer.displayText())

        if self.utabWidget.currentIndex() == 0:
            createLine = True
        else:
            createLine = False




        if self.uSelectedPoints.isChecked() and \
                point_layer.selectedFeatureCount() == 0 or self.uSelectedLine.isChecked() and \
                line_layer.selectedFeatureCount() == 0:
            QMessageBox.warning(
                self, self.tr('No selection'),
                self.tr('There is no selection in input '
                        'layer. Uncheck corresponding option '
                        'or select some features before '
                        'running analysis'))
            return

        if not createLine and not self.uSelectedLine.isChecked() and \
                line_layer.featureCount() != 1:
            QMessageBox.warning(
                self, self.tr('Line Layer Error'),
                self.
                tr('There are multiple line features within the line layer.\n Please select one.'
                   ))
            return

        if utils.checkMultipart(point_layer):
            QMessageBox.warning(
                self, self.tr('Point Layer Error'),
                self.
                tr('Point layer has multi-part geometery.\n Please convert to single part geometery.'
                   ))
            return

        if not createLine and utils.checkMultipart(line_layer):
            QMessageBox.warning(
                self, self.tr('Line Layer Error'),
                self.
                tr('Line layer has multi-part geometery.\n Please convert to single part geometery.'
                   ))
            return

        selected_points = self.uSelectedPoints.checkState()
        selected_line = self.uSelectedLine.checkState()

        self.workThread = profilefrompoints_thread.ProfilefromPointsThread(
            point_layer, z_field, createLine, order_field, sort, line_layer,
            buff, selected_points, selected_line)

        self.workThread.processFinished.connect(self.processFinished)
        self.workThread.processInterrupted.connect(self.processInterrupted)

        self.btnOk.setEnabled(False)
        self.btnClose.setText(self.tr("Cancel"))
        self.buttonBox.rejected.disconnect(self.reject)
        self.btnClose.clicked.connect(self.stopProcessing)

        self.uprogressBar.setMaximum(0)
        self.workThread.start()

        self.dbase = os.path.join(os.environ['HOME'], 'Desktop',
                                  'tmp_' + point_layer.name() + '.sqlite')

    def reject(self):
        print 'rejected'
        QDialog.reject(self)

    def processFinished(self, values):
        self.stopProcessing()
        self.values = values[0]
        self.uCopytoClip.setEnabled(True)
        self.iface.messageBar().pushMessage(
            QCoreApplication.translate(
                "ProfilefromPoints",
                'Profile from Points  - A temporary spatialite database was created at {}.  Please delete when finished'
                .format(self.dbase)))

        # create plot
        self.refreshPlot()

        self.restoreGui()

    def processInterrupted(self):
        self.restoreGui()

    def stopProcessing(self):
        if self.workThread is not None:
            self.workThread.stop()
            self.workThread = None

    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]))
        self.axes.grid()
        formatter = ScalarFormatter(useOffset=False)
        self.axes.yaxis.set_major_formatter(formatter)

        self.axes.set_ylabel(unicode(self.tr("Elevation, z field units")))
        self.axes.set_xlabel(unicode(self.tr('Station, layer units')))

        self.canvas.draw()

    def copyClipboard(self):
        if self.values is None:
            return
        else:
            clipboard = QApplication.clipboard()
            clipboard.setText('\n'.join(
                '%s\t%s' % x for x in zip(self.values[0], self.values[1])))
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=''):
        #self.obsid = obsid
        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("Calibrate logger") # Set the title for the dialog
        self.connect(self.pushButton, PyQt4.QtCore.SIGNAL("clicked()"), self.calibrateandplot)
        self.INFO.setText("Select the observation point with logger data to be calibrated.")

        # 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.show()

        # Populate combobox with obsid from table w_levels_logger
        self.load_obsid_from_db()

    def load_obsid_from_db(self):
        self.combobox_obsid.clear()
        myconnection = utils.dbconnection()
        if myconnection.connect2db() == True:
            # 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:
                self.combobox_obsid.addItem(row[0])
            rs.close()
            myconnection.closedb()        

    def getlastcalibration(self):
        obsid = unicode(self.combobox_obsid.currentText())
        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 > 0 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 += """\nwas """ + str(self.lastcalibr[0][1]) + """ masl\nat """ +  str(self.lastcalibr[0][0])
            else:
                text = """There is no earlier known\nposition for the logger\nin """ + unicode(self.combobox_obsid.currentText())#self.obsid[0]
            self.INFO.setText(text)

    def calibrateandplot(self):
        obsid = unicode(self.combobox_obsid.currentText())
        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()
                newzref = self.LoggerPos.text()
                if len(newzref)>0:
                    sql =r"""UPDATE w_levels_logger SET level_masl = """
                    sql += str(newzref)
                    sql += """ + head_cm / 100 WHERE obsid = '"""
                    sql += obsid   
                    sql += """' AND date_time >= '"""
                    sql += str(fr_d_t)
                    sql += """' AND date_time <= '"""
                    sql += str(to_d_t)
                    sql += """' """
                    dummy = utils.sql_alter_db(sql)
                self.CalibrationPlot(obsid)
                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.")

    def CalibrationPlot(self,obsid):
        self.axes.clear()
        
        conn = sqlite.connect(self.settingsdict['database'],detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
        # skapa en cursor
        curs = conn.cursor()
        # Create a plot window with one single subplot
        #fig = plt.figure()  # causes conflict with plugins "statist" and "chartmaker"
        #ax = fig.add_subplot(111)
        
        p=[None]*2 # List for plot objects
        My_format = [('date_time', datetime.datetime), ('values', float)] #Define (with help from function datetime) a good format for numpy array 
        
        # Load manual reading (full time series) for the obsid
        sql =r"""SELECT date_time, level_masl FROM w_levels WHERE obsid = '"""
        sql += obsid   
        sql += """' ORDER BY date_time"""
        rs = curs.execute(sql) #Send SQL-syntax to cursor
        recs = rs.fetchall()  # All data are stored in recs
        #Transform data to a numpy.recarray
        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    
        # Get help from function datestr2num to get date and time into float
        myTimestring = []  #LIST
        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
        p[0] = self.axes.plot_date(numtime, table2.values, 'o-', label=obsid)    # LINEPLOT WITH DOTS!!
        
        # Load Loggerlevels (full time series) for the obsid
        sql =r"""SELECT date_time as 'date [datetime]', level_masl FROM w_levels_logger WHERE obsid = '"""
        sql += obsid   # The result has format 'Qstring' - no good
        sql += """' ORDER BY date_time"""
        rs = curs.execute(sql) #Send SQL-syntax to cursor
        recs = rs.fetchall()  # All data are stored in recs
        #Transform data to a numpy.recarray
        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    
        # Get help from function datestr2num to get date and time into float
        myTimestring = []  #LIST
        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
        p[1] = self.axes.plot_date(numtime, table2.values, '-', label = obsid + unicode(' logger', 'utf-8'))    # LINEPLOT WITH DOTS!!

        """ Close SQLite-connections """
        rs.close() # First close the table 
        conn.close()  # then close the database

        """ 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('Calibration 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.canvas.draw()
        plt.close(self.calibrplotfigure)#this closes reference to self.calibrplotfigure