Пример #1
0
class PrettyWidget(QtGui.QWidget):
    def __init__(self):
        super(PrettyWidget, self).__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(600, 300, 1300, 600)
        self.setFixedSize(1300, 600)
        self.center()
        self.setWindowTitle('Health Statistics & Analysis')
        self.setWindowIcon(QtGui.QIcon('hospital-2.png'))
        grid = QtGui.QGridLayout()
        self.setLayout(grid)

        bar = QtGui.QMenuBar()
        file = bar.addMenu('File')
        file.addAction('New')
        save = QtGui.QAction('Save', self)
        file.addAction(save)
        edit = bar.addMenu('Edit')
        edit.addAction('Copy')
        edit.addAction('paste')
        quit = bar.addMenu('Quit')
        exit = QtGui.QAction('Exit', self)
        quit.addAction(exit)
        grid.addWidget(bar, 0, 0, 1, 2)

        pic = QtGui.QLabel()
        pic.setPixmap(QtGui.QPixmap('electrocardiogram.png'))
        pic.resize(pic.sizeHint())
        label1 = QtGui.QLabel('Data Manipulation')
        label1.setFont(QtGui.QFont('Calibri', 11, QtGui.QFont.Bold))
        file_import = QtGui.QPushButton('Import File')
        file_import.resize(file_import.sizeHint())
        self.connect(file_import, SIGNAL('clicked()'), self.file_dialog)
        self.connect(self, SIGNAL('main2closed()'), self.file_clear)
        button2 = QtGui.QPushButton('Display DataFrame')
        button2.resize(button2.sizeHint())
        self.connect(button2, SIGNAL('clicked()'), self.disp_df)
        self.connect(self, SIGNAL('main2closed()'), self.df_clear)

        describ = QtGui.QPushButton('Description')
        describ.clicked.connect(self.description)

        sublayout1 = QtGui.QGridLayout()
        sublayout1.addWidget(pic, 0, 0)
        sublayout1.addWidget(label1, 1, 0)
        sublayout1.addWidget(file_import, 2, 0)
        sublayout1.addWidget(button2, 2, 1)

        sublayout1.addWidget(describ, 3, 0)
        grid.addLayout(sublayout1, 1, 0)

        label2 = QtGui.QLabel('Statistical Visualization')
        label2.setFont(QtGui.QFont('Calibri', 11, QtGui.QFont.Bold))
        button4 = QtGui.QPushButton('Distribution(Histogram)')
        button4.resize(button4.sizeHint())
        self.connect(button4, SIGNAL('clicked()'), self.Hist)
        self.connect(self, SIGNAL('main2closed()'), self.hist_clear)
        button5 = QtGui.QPushButton('Time Chart Series')
        button5.resize(button5.sizeHint())
        button5.clicked.connect(self.plot_series)
        button6 = QtGui.QPushButton('Pie Chart')
        button6.clicked.connect(self.Pie)
        button7 = QtGui.QPushButton('Clear Canvas')
        button7.clicked.connect(self.clear_canvas)
        sublayout2 = QtGui.QGridLayout()
        sublayout2.addWidget(label2, 0, 0)
        sublayout2.addWidget(button4, 1, 0)
        sublayout2.addWidget(button5, 1, 1)
        sublayout2.addWidget(button6, 2, 0)
        sublayout2.addWidget(button7, 2, 1)
        grid.addLayout(sublayout2, 2, 0, 1, 1)

        label3 = QtGui.QLabel('Supervised / UnSupervised Learning')
        label3.setFont(QtGui.QFont('Calibri', 11, QtGui.QFont.Bold))
        button7 = QtGui.QPushButton('Decision Tree Classifier')
        button7.resize(button7.sizeHint())
        button7.clicked.connect(self.classifier)
        self.connect(button7, SIGNAL('clicked()'), self.dc_tree_info)
        self.connect(self, SIGNAL('main2closed()'), self.clearDecision)
        self.button8 = QtGui.QPushButton('Clustering(KMean)')
        self.connect(self.button8, SIGNAL('clicked()'), self.clustering)
        self.connect(self, SIGNAL('main2closed()'), self.clearCluster)
        button9 = QtGui.QPushButton('Predictive Learning')
        self.connect(button9, SIGNAL('clicked()'), self.prediction)
        self.connect(self, SIGNAL('main2closed()'), self.pred_close)
        sublayout3 = QtGui.QVBoxLayout()
        sublayout3.addWidget(label3)
        sublayout3.addWidget(button7)
        sublayout3.addWidget(self.button8)
        sublayout3.addWidget(button9)
        grid.addLayout(sublayout3, 3, 0, 1, 1)

        verticalLine = QtGui.QFrame()
        verticalLine.setFrameStyle(QtGui.QFrame.VLine)
        verticalLine.setSizePolicy(QtGui.QSizePolicy.Minimum,
                                   QtGui.QSizePolicy.Expanding)
        grid.addWidget(verticalLine, 1, 1, 6, 1)
        self.figure = plt.figure(figsize=(15, 5))
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        grid.addWidget(self.canvas, 1, 2, 1, 2)
        grid.addWidget(self.toolbar, 0, 2, 1, 2)

        self.show()

    def disp_df(self):
        self.display_df = Table_Widget()
        self.connect(self.display_df, SIGNAL('closed()'), self.df_clear)
        self.display_df.show()

    def df_clear(self):
        self.emit(SIGNAL('main2closed()'))

    def file_dialog(self):
        self.file_diag = file_dialog()
        self.connect(self.file_diag, SIGNAL('closed()'), self.hist_close)
        self.file_diag.show()

    def file_clear(self):
        self.emit(SIGNAL('main2closed()'))

    def file_import(self):
        print('file_import')
        deef = file_dialog
        deef.get_csv_filename(self)
        return deef

        #data description mean, std, count, min, max, quartile, median.
    def description(self):
        df = pd.read_csv('2015 data.csv')
        fig, ax = plt.subplots(figsize=(13, 3))  # set size frame
        ax.xaxis.set_visible(False)  # hide the x axis
        ax.yaxis.set_visible(False)  # hide the y axis
        ax.set_frame_on(False)  # no visible frame, uncomment if size is ok
        #tabla = table(ax, df.describe(), loc='center')  # where df is your data frame
        #tabla.auto_set_font_size(False) # Activate set fontsize manually
        #tabla.set_fontsize(12) # if ++fontsize is necessary ++colWidths
        #tabla.scale(1.2, 1.2) # change size table
        plt.show()

        #plot time curve series for the trend of Malaria
    def plot_series(self):
        time_plot()

        #plot pie chart to represent the fraction of Gender and Malaria cases from a Whole.
    def Pie(self):
        self.pie_window = Pie_Distr()
        self.connect(self.hist_window, SIGNAL('closed()'), self.pie_close)
        self.pie_window.show()

    def pie_close(self):
        self.emit(SIGNAL('main2closed()'))

    def pie_clear(self):
        del self.pie_window
        self.pie_window = None

    def clear_canvas(self):
        self.canvas.clear()

    def plot1(self):
        plt.cla()
        ax = self.figure.add_subplot(111)
        x = [i for i in range(100)]
        y = [i**2 for i in x]
        ax.plot(x, y, 'b.-')
        ax.set_title('Quadratic Plot')
        self.canvas.draw()

    def plot2(self):
        self.canvas.clearFocus()
        plt.cla()
        ax = self.figure.add_subplot(111)
        x = [i for i in range(100)]
        y = [i**0.5 for i in x]
        ax.plot(x, y, 'r.-')
        ax.set_title('Square Root Plot')
        self.canvas.draw()

    def plot3(self):
        return 0
        '''To plot the distribution of health from data gathered;
        Histogram will determine Age, Height & Weight Distribution'''

    def Hist(self):
        self.hist_window = Hist_Distr()
        self.connect(self.hist_window, SIGNAL('closed()'), self.hist_close)
        self.hist_window.show()

    def hist_close(self):
        self.emit(SIGNAL('main2closed()'))

    def hist_clear(self):
        del self.hist_window
        self.hist_window = None

    def classifier(self):

        print("\n-- get data:")
        df = get_iris_data()

        print("\n-- df.head():")
        #print(df.head(), end="\n\n")

        features = ["Age", "Height", "Weight", "BMI"]
        df, targets = encode_target(df, "Malaria")
        #Learning of the algorithm

        y = df["Target"]
        X = df[features]

        #dt = DecisionTreeClassifier(min_samples_split=20, random_state=99)
        #dt.fit(X, y)

        print("\n-- get_code:")
        get_code(dt, features, targets)

        print("\n-- Target Class")
        #print(df[df['Weight'] <= 50]['Malaria'].unique(), end="\n\n")

        #visualize_tree(dt, features)
    def dc_tree_info(self):
        self.decision_details = d_tree_info()
        self.connect(self.decision_details, SIGNAL('closed()'),
                     self.decision_close)
        self.decision_details.show()

    def decision_close(self):
        self.emit(SIGNAL('main2closed()'))

    def clearDecision(self):
        del self.decision_details
        self.decision_details = None
        #Unspervised learning where the algorithm trys to group the data from the dataset, based on the
    def clustering(self):
        self.other_window = clustered_layout()
        self.connect(self.other_window, SIGNAL('closed()'),
                     self.clustering_close)
        self.other_window.show()

    def clustering_close(self):
        self.emit(SIGNAL('main2closed()'))

    def clearCluster(self):
        del self.other_window
        self.other_window = None

        #To carry out the prediction of target class representing Malaria and its Types based on
        # the characteristics they potray from the data collected.
    def prediction(self):
        self.pred_window = prediction()
        self.connect(self.pred_window, SIGNAL('closed()'), self.pred_close)
        self.pred_window.show()

    def pred_close(self):
        self.emit(SIGNAL('main2closed'))

    def clearPred(self):
        del self.pred_window
        self.pred_window = None

        #position the main window in the center position of the screen layout.
    def center(self):
        qr = self.frameGeometry()
        cp = QtGui.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
Пример #2
0
class ProfileDockWidget(QDockWidget):
    """
    DockWidget class to display the profile
    """

    closeSignal = pyqtSignal()

    def __init__(self, iface):
        """
        Constructor
        :param iface: interface
        """
        QDockWidget.__init__(self)
        self.setWindowTitle(QCoreApplication.translate("VDLTools", "Profile Tool"))
        self.resize(1024, 400)
        self.__iface = iface
        self.__canvas = self.__iface.mapCanvas()
        self.__types = ['PDF', 'PNG']  # ], 'SVG', 'PS']
        self.__libs = []
        if Qwt5_loaded:
            self.__lib = 'Qwt5'
            self.__libs.append('Qwt5')
            if matplotlib_loaded:
                self.__libs.append('Matplotlib')
        elif matplotlib_loaded:
            self.__lib = 'Matplotlib'
            self.__libs.append('Matplotlib')
        else:
            self.__lib = None
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "No graph lib available (qwt5 or matplotlib)"),
                level=QgsMessageBar.CRITICAL, duration=0)

        self.__doTracking = False
        self.__vline = None

        self.__profiles = None
        self.__numLines = None
        self.__mntPoints = None

        self.__marker = None
        self.__tabmouseevent = None

        self.__contentWidget = QWidget()
        self.setWidget(self.__contentWidget)

        self.__boxLayout = QHBoxLayout()
        self.__contentWidget.setLayout(self.__boxLayout)

        self.__plotFrame = QFrame()
        self.__frameLayout = QHBoxLayout()
        self.__plotFrame.setLayout(self.__frameLayout)

        self.__printLayout = QHBoxLayout()
        self.__printLayout.addWidget(self.__plotFrame)

        self.__legendLayout = QVBoxLayout()
        self.__printLayout.addLayout(self.__legendLayout)

        self.__printWdg = QWidget()
        self.__printWdg.setLayout(self.__printLayout)

        self.__plotWdg = None
        self.__changePlotWidget()

        size = QSize(150, 20)

        self.__boxLayout.addWidget(self.__printWdg)

        self.__vertLayout = QVBoxLayout()

        self.__libCombo = QComboBox()
        self.__libCombo.setFixedSize(size)
        self.__libCombo.addItems(self.__libs)
        self.__vertLayout.addWidget(self.__libCombo)
        self.__libCombo.currentIndexChanged.connect(self.__setLib)

        self.__maxLabel = QLabel("y max")
        self.__maxLabel.setFixedSize(size)
        self.__vertLayout.addWidget(self.__maxLabel)
        self.__maxSpin = QSpinBox()
        self.__maxSpin.setFixedSize(size)
        self.__maxSpin.setRange(-10000, 10000)
        self.__maxSpin.valueChanged.connect(self.__reScalePlot)
        self.__vertLayout.addWidget(self.__maxSpin)
        self.__vertLayout.insertSpacing(10, 20)

        self.__minLabel = QLabel("y min")
        self.__minLabel.setFixedSize(size)
        self.__vertLayout.addWidget(self.__minLabel)
        self.__minSpin = QSpinBox()
        self.__minSpin.setFixedSize(size)
        self.__minSpin.setRange(-10000, 10000)
        self.__minSpin.valueChanged.connect(self.__reScalePlot)
        self.__vertLayout.addWidget(self.__minSpin)
        self.__vertLayout.insertSpacing(10, 40)

        self.__typeCombo = QComboBox()
        self.__typeCombo.setFixedSize(size)
        self.__typeCombo.addItems(self.__types)
        self.__vertLayout.addWidget(self.__typeCombo)
        self.__saveButton = QPushButton(QCoreApplication.translate("VDLTools", "Save"))
        self.__saveButton.setFixedSize(size)
        self.__saveButton.clicked.connect(self.__save)
        self.__vertLayout.addWidget(self.__saveButton)

        self.__boxLayout.addLayout(self.__vertLayout)

        self.__maxSpin.setEnabled(False)
        self.__minSpin.setEnabled(False)

        self.__colors = []
        for cn in QColor.colorNames():
            qc = QColor(cn)
            val = qc.red() + qc.green() + qc.blue()
            if 0 < val < 450:
                self.__colors.append(cn)

    def __changePlotWidget(self):
        """
        When plot widget is change (qwt <-> matplotlib)
        """
        self.__activateMouseTracking(False)
        while self.__frameLayout.count():
            child = self.__frameLayout.takeAt(0)
            child.widget().deleteLater()
        self.__plotWdg = None

        if self.__lib == 'Qwt5':
            self.__plotWdg = QwtPlot(self.__plotFrame)
            sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            sizePolicy.setHorizontalStretch(10)
            sizePolicy.setVerticalStretch(0)
            self.__plotWdg.setSizePolicy(sizePolicy)
            self.__plotWdg.setAutoFillBackground(False)
            # Decoration
            self.__plotWdg.setCanvasBackground(Qt.white)
            self.__plotWdg.plotLayout().setAlignCanvasToScales(False)
            self.__plotWdg.plotLayout().setSpacing(100)
            self.__plotWdg.plotLayout().setCanvasMargin(10, QwtPlot.xBottom)
            self.__plotWdg.plotLayout().setCanvasMargin(10, QwtPlot.yLeft)
            title = QwtText(QCoreApplication.translate("VDLTools", "Distance [m]"))
            title.setFont(QFont("Helvetica", 10))
            self.__plotWdg.setAxisTitle(QwtPlot.xBottom, title)
            title.setText(QCoreApplication.translate("VDLTools", "Elevation [m]"))
            title.setFont(QFont("Helvetica", 10))
            self.__plotWdg.setAxisTitle(QwtPlot.yLeft, title)
            self.__zoomer = QwtPlotZoomer(QwtPlot.xBottom, QwtPlot.yLeft, QwtPicker.DragSelection, QwtPicker.AlwaysOff,
                                          self.__plotWdg.canvas())
            self.__zoomer.setRubberBandPen(QPen(Qt.blue))
            grid = QwtPlotGrid()
            grid.setPen(QPen(QColor('grey'), 0, Qt.DotLine))
            grid.attach(self.__plotWdg)
            self.__frameLayout.addWidget(self.__plotWdg)

        elif self.__lib == 'Matplotlib':
            # __plotWdg.figure : matplotlib.figure.Figure
            fig = Figure((1.0, 1.0), linewidth=0.0, subplotpars=SubplotParams(left=0, bottom=0, right=1, top=1,
                                                                              wspace=0, hspace=0))

            font = {'family': 'arial', 'weight': 'normal', 'size': 12}
            rc('font', **font)

            rect = fig.patch
            rect.set_facecolor((0.9, 0.9, 0.9))

            self.__axes = fig.add_axes((0.07, 0.16, 0.92, 0.82))
            self.__axes.set_xbound(0, 1000)
            self.__axes.set_ybound(0, 1000)
            self.__manageMatplotlibAxe(self.__axes)
            self.__plotWdg = FigureCanvasQTAgg(fig)
            sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            self.__plotWdg.setSizePolicy(sizePolicy)
            self.__frameLayout.addWidget(self.__plotWdg)

    def setProfiles(self, profiles, numLines):
        """
        To set the profiles
        :param profiles: profiles : positions with elevations (for line and points)
        :param numLines: number of selected connected lines
        """
        self.__numLines = numLines
        self.__profiles = profiles
        if self.__lib == 'Matplotlib':
            self.__prepare_points()

    def __getLinearPoints(self):
        """
        To extract the linear points of the profile
        """
        profileLen = 0
        self.__profiles[0]['l'] = profileLen
        for i in range(0, len(self.__profiles)-1):
            x1 = float(self.__profiles[i]['x'])
            y1 = float(self.__profiles[i]['y'])
            x2 = float(self.__profiles[i+1]['x'])
            y2 = float(self.__profiles[i+1]['y'])
            profileLen += sqrt(((x2-x1)*(x2-x1)) + ((y2-y1)*(y2-y1)))
            self.__profiles[i+1]['l'] = profileLen

    def __getMnt(self, settings):
        """
        To get the MN data for the profile
        :param settings: settings containing MN url
        """
        if settings is None or settings.mntUrl is None or settings.mntUrl == "None":
            url = 'http://map.lausanne.ch/main/wsgi/profile.json'
        elif settings.mntUrl == "":
            return
        else:
            url = settings.mntUrl
        names = ['mnt', 'mns', 'toit_rocher']
        url += '?layers='
        pos = 0
        for name in names:
            if pos > 0:
                url += ','
            pos += 1
            url += name
        url += '&geom={"type":"LineString","coordinates":['
        pos = 0
        for i in range(len(self.__profiles)):
            if pos > 0:
                url += ','
            pos += 1
            url += '[' + str(self.__profiles[i]['x']) + ',' + str(self.__profiles[i]['y']) + ']'
        url = url + ']}&nbPoints=' + str(int(self.__profiles[len(self.__profiles)-1]['l']))
        try:
            response = urlopen(url)
            j = response.read()
            j_obj = json.loads(j)
            profile = j_obj['profile']
            self.__mntPoints = []
            self.__mntPoints.append(names)
            mnt_l = []
            mnt_z = []
            for p in range(len(names)):
                z = []
                mnt_z.append(z)
            for pt in profile:
                mnt_l.append(float(pt['dist']))
                values = pt['values']
                for p in range(len(names)):
                    if names[p] in values:
                        mnt_z[p].append(float(values[names[p]]))
                    else:
                        mnt_z[p].append(None)
            self.__mntPoints.append(mnt_l)
            self.__mntPoints.append(mnt_z)
        except HTTPError as e:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "HTTP Error"),
                QCoreApplication.translate("VDLTools", "status error [" + str(e.code) + "] : " + e.reason),
                level=QgsMessageBar.CRITICAL, duration=0)
        except URLError as e:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "URL Error"),
                e.reason, level=QgsMessageBar.CRITICAL, duration=0)

    def attachCurves(self, names, settings, usedMnts):
        """
        To attach the curves for the layers to the profile
        :param names: layers names
        """
        if (self.__profiles is None) or (self.__profiles == 0):
            return

        self.__getLinearPoints()
        if usedMnts is not None and (usedMnts[0] or usedMnts[1] or usedMnts[2]):
            self.__getMnt(settings)

        c = 0

        if self.__mntPoints is not None:
                for p in range(len(self.__mntPoints[0])):
                    if usedMnts[p]:
                        legend = QLabel("<font color='" + self.__colors[c] + "'>" + self.__mntPoints[0][p]
                                        + "</font>")
                        self.__legendLayout.addWidget(legend)

                        if self.__lib == 'Qwt5':

                            xx = [list(g) for k, g in itertools.groupby(self.__mntPoints[1],
                                                                        lambda x: x is None) if not k]
                            yy = [list(g) for k, g in itertools.groupby(self.__mntPoints[2][p], lambda x: x is None)
                                  if not k]

                            for j in range(len(xx)):
                                curve = QwtPlotCurve(self.__mntPoints[0][p])
                                curve.setData(xx[j], yy[j])
                                curve.setPen(QPen(QColor(self.__colors[c]), 3))
                                curve.attach(self.__plotWdg)

                        elif self.__lib == 'Matplotlib':
                            qcol = QColor(self.__colors[c])
                            self.__plotWdg.figure.get_axes()[0].plot(self.__mntPoints[1], self.__mntPoints[2][p],
                                                                     gid=self.__mntPoints[0][p], linewidth=3)
                            tmp = self.__plotWdg.figure.get_axes()[0].get_lines()
                            for t in range(len(tmp)):
                                if self.__mntPoints[0][p] == tmp[t].get_gid():
                                    tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0),
                                                      old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0)))
                                    self.__plotWdg.draw()
                                    break
                        c += 1

        if 'z' in self.__profiles[0]:
            for i in range(len(self.__profiles[0]['z'])):
                if i < self.__numLines:
                    v = 0
                else:
                    v = i - self.__numLines + 1
                name = names[v]
                xx = []
                yy = []
                for prof in self.__profiles:
                    xx.append(prof['l'])
                    yy.append(prof['z'][i])

                for j in range(len(yy)):
                    if yy[j] is None:
                        xx[j] = None

                if i == 0 or i > (self.__numLines-1):
                    legend = QLabel("<font color='" + self.__colors[c] + "'>" + name + "</font>")
                    self.__legendLayout.addWidget(legend)

                if self.__lib == 'Qwt5':

                    # Split xx and yy into single lines at None values
                    xx = [list(g) for k, g in itertools.groupby(xx, lambda x: x is None) if not k]
                    yy = [list(g) for k, g in itertools.groupby(yy, lambda x: x is None) if not k]

                    # Create & attach one QwtPlotCurve per one single line
                    for j in range(len(xx)):
                        curve = QwtPlotCurve(name)
                        curve.setData(xx[j], yy[j])
                        curve.setPen(QPen(QColor(self.__colors[c]), 3))
                        if i > (self.__numLines-1):
                            curve.setStyle(QwtPlotCurve.Dots)
                            pen = QPen(QColor(self.__colors[c]), 8)
                            pen.setCapStyle(Qt.RoundCap)
                            curve.setPen(pen)
                        curve.attach(self.__plotWdg)

                elif self.__lib == 'Matplotlib':
                    qcol = QColor(self.__colors[c])
                    if i < self.__numLines:
                        self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=3)
                    else:
                        self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=5, marker='o',
                                                                 linestyle='None')
                    tmp = self.__plotWdg.figure.get_axes()[0].get_lines()
                    for t in range(len(tmp)):
                        if name == tmp[t].get_gid():
                            tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0),
                                              old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0)))
                            self.__plotWdg.draw()
                            break
                c += 1

        # scaling this
        try:
            self.__reScalePlot(None, True)
        except:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "Rescale problem... (trace printed)"),
                level=QgsMessageBar.CRITICAL, duration=0)
            print(
                QCoreApplication.translate("VDLTools", "rescale problem : "), sys.exc_info()[0], traceback.format_exc())
        if self.__lib == 'Qwt5':
            self.__plotWdg.replot()
        elif self.__lib == 'Matplotlib':
            self.__plotWdg.figure.get_axes()[0].redraw_in_frame()
            self.__plotWdg.draw()
            self.__activateMouseTracking(True)
            self.__marker.show()

    def __reScalePlot(self, value=None, auto=False):
        """
        To rescale the profile plot depending to the bounds
        """
        if (self.__profiles is None) or (self.__profiles == 0):
            self.__plotWdg.replot()
            return

        maxi = 0
        for i in range(len(self.__profiles)):
            if (int(self.__profiles[i]['l'])) > maxi:
                maxi = int(self.__profiles[i]['l']) + 1
        if self.__lib == 'Qwt5':
            self.__plotWdg.setAxisScale(2, 0, maxi, 0)
        elif self.__lib == 'Matplotlib':
            self.__plotWdg.figure.get_axes()[0].set_xbound(0, maxi)

        minimumValue = self.__minSpin.value()
        maximumValue = self.__maxSpin.value()

        # to set max y and min y displayed
        if auto:
            minimumValue = 1000000000
            maximumValue = -1000000000
            for i in range(len(self.__profiles)):
                if 'z' in self.__profiles[i]:
                    mini = self.__minTab(self.__profiles[i]['z'])
                    if int(mini) < minimumValue:
                        minimumValue = int(mini) - 1
                    maxi = self.__maxTab(self.__profiles[i]['z'])
                    if int(maxi) > maximumValue:
                        maximumValue = int(maxi) + 1
                if self.__mntPoints is not None:
                    for pts in self.__mntPoints[2]:
                        miniMnt = self.__minTab(pts)
                        if int(miniMnt) < minimumValue:
                            minimumValue = int(miniMnt) - 1
                        maxiMnt = self.__maxTab(pts)
                        if int(maxiMnt) > maximumValue:
                            maximumValue = int(maxiMnt) + 1
        self.__maxSpin.setValue(maximumValue)
        self.__minSpin.setValue(minimumValue)
        self.__maxSpin.setEnabled(True)
        self.__minSpin.setEnabled(True)

        if self.__lib == 'Qwt5':
            rect = QRectF(0, minimumValue, maxi, maximumValue-minimumValue)
            self.__zoomer.setZoomBase(rect)

        # to draw vertical lines
        for i in range(len(self.__profiles)):
            zz = []
            for j in range(self.__numLines):
                if self.__profiles[i]['z'][j] is not None:
                    zz.append(j)
            color = None
            if len(zz) == 2:
                width = 3
                color = QColor('red')
            else:
                width = 1

            if self.__lib == 'Qwt5':
                vertLine = QwtPlotMarker()
                vertLine.setLineStyle(QwtPlotMarker.VLine)
                pen = vertLine.linePen()
                pen.setWidth(width)
                if color is not None:
                    pen.setColor(color)
                vertLine.setLinePen(pen)
                vertLine.setXValue(self.__profiles[i]['l'])
                label = vertLine.label()
                label.setText(str(i))
                vertLine.setLabel(label)
                vertLine.setLabelAlignment(Qt.AlignLeft)
                vertLine.attach(self.__plotWdg)
            elif self.__lib == 'Matplotlib':
                self.__plotWdg.figure.get_axes()[0].vlines(self.__profiles[i]['l'], minimumValue, maximumValue,
                                                           linewidth=width)

        if minimumValue < maximumValue:
            if self.__lib == 'Qwt5':
                self.__plotWdg.setAxisScale(0, minimumValue, maximumValue, 0)
                self.__plotWdg.replot()
            elif self.__lib == 'Matplotlib':
                self.__plotWdg.figure.get_axes()[0].set_ybound(minimumValue, maximumValue)
                self.__plotWdg.figure.get_axes()[0].redraw_in_frame()
                self.__plotWdg.draw()

    @staticmethod
    def __minTab(tab):
        """
        To get the minimum value in a table
        :param tab: table to scan
        :return: minimum value
        """
        mini = 1000000000
        for t in tab:
            if t is None:
                continue
            if t < mini:
                mini = t
        return mini

    @staticmethod
    def __maxTab(tab):
        """
        To get the maximum value in a table
        :param tab: table to scan
        :return: maximum value
        """
        maxi = -1000000000
        for t in tab:
            if t is None:
                continue
            if t > maxi:
                maxi = t
        return maxi

    def __setLib(self):
        """
        To set the new widget library (qwt <-> matplotlib)
        """
        self.__lib = self.__libs[self.__libCombo.currentIndex()]
        self.__changePlotWidget()

    def __save(self):
        """
        To save the profile in a file, on selected format
        """
        idx = self.__typeCombo.currentIndex()
        if idx == 0:
            self.__outPDF()
        elif idx == 1:
            self.__outPNG()
        else:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "Invalid index ") + str(idx),
                level=QgsMessageBar.CRITICAL, duration=0)

    def __outPDF(self):
        """
        To save the profile as pdf file
        """
        fileName = QFileDialog.getSaveFileName(
            self.__iface.mainWindow(), QCoreApplication.translate("VDLTools", "Save As"),
            QCoreApplication.translate("VDLTools", "Profile.pdf"),"Portable Document Format (*.pdf)")
        if fileName is not None:
            if self.__lib == 'Qwt5':
                printer = QPrinter()
                printer.setCreator(QCoreApplication.translate("VDLTools", "QGIS Profile Plugin"))
                printer.setOutputFileName(fileName)
                printer.setOutputFormat(QPrinter.PdfFormat)
                printer.setOrientation(QPrinter.Landscape)
                self.__plotWdg.print_(printer)
            elif self.__lib == 'Matplotlib':
                self.__plotWdg.figure.savefig(str(fileName))
            # printer = QPrinter()
            # printer.setCreator(QCoreApplication.translate("VDLTools", "QGIS Profile Plugin"))
            # printer.setOutputFileName(fileName)
            # printer.setOutputFormat(QPrinter.PdfFormat)
            # printer.setOrientation(QPrinter.Landscape)
            # printer.setPaperSize(QSizeF(self.__printWdg.size()), QPrinter.Millimeter)
            # printer.setFullPage(True)
            # self.__printWdg.render(printer)

    def __outPNG(self):
        """
        To save the profile as png file
        """
        fileName = QFileDialog.getSaveFileName(
            self.__iface.mainWindow(), QCoreApplication.translate("VDLTools", "Save As"),
            QCoreApplication.translate("VDLTools", "Profile.png"),"Portable Network Graphics (*.png)")
        if fileName is not None:
            QPixmap.grabWidget(self.__printWdg).save(fileName, "PNG")

    def clearData(self):
        """
        To clear the displayed data
        """
        if self.__profiles is None:
            return
        if self.__lib == 'Qwt5':
            self.__plotWdg.clear()
            self.__profiles = None
            temp1 = self.__plotWdg.itemList()
            for j in range(len(temp1)):
                if temp1[j].rtti() == QwtPlotItem.Rtti_PlotCurve:
                    temp1[j].detach()
        elif self.__lib == 'Matplotlib':
            self.__plotWdg.figure.get_axes()[0].cla()
            self.__manageMatplotlibAxe(self.__plotWdg.figure.get_axes()[0])
        self.__maxSpin.setEnabled(False)
        self.__minSpin.setEnabled(False)
        self.__maxSpin.setValue(0)
        self.__minSpin.setValue(0)

        # clear legend
        while self.__legendLayout.count():
            child = self.__legendLayout.takeAt(0)
            child.widget().deleteLater()

    def __manageMatplotlibAxe(self, axe):
        """
        To manage the axes for matplotlib library
        :param axe: the axes element
        """
        axe.grid()
        axe.tick_params(axis="both", which="major", direction="out", length=10, width=1, bottom=True, top=False,
                        left=True, right=False)
        axe.minorticks_on()
        axe.tick_params(axis="both", which="minor", direction="out", length=5, width=1, bottom=True, top=False,
                        left=True, right=False)
        axe.set_xlabel(QCoreApplication.translate("VDLTools", "Distance [m]"))
        axe.set_ylabel(QCoreApplication.translate("VDLTools", "Elevation [m]"))

    def __activateMouseTracking(self, activate):
        """
        To (de)activate the mouse tracking on the profile for matplotlib library
        :param activate: true to activate, false to deactivate
        """
        if activate:
            self.__doTracking = True
            self.__loadRubber()
            self.cid = self.__plotWdg.mpl_connect('motion_notify_event', self.__mouseevent_mpl)
        elif self.__doTracking:
            self.__doTracking = False
            self.__plotWdg.mpl_disconnect(self.cid)
            if self.__marker is not None:
                self.__canvas.scene().removeItem(self.__marker)
            try:
                if self.__vline is not None:
                    self.__plotWdg.figure.get_axes()[0].lines.remove(self.__vline)
                    self.__plotWdg.draw()
            except Exception as e:
                self.__iface.messageBar().pushMessage(
                    QCoreApplication.translate("VDLTools", "Tracking exception : ") + str(e),
                    level=QgsMessageBar.CRITICAL, duration=0)

    def __mouseevent_mpl(self, event):
        """
        To manage matplotlib mouse tracking event
        :param event: mouse tracking event
        """
        if event.xdata is not None:
            try:
                if self.__vline is not None:
                    self.__plotWdg.figure.get_axes()[0].lines.remove(self.__vline)
            except Exception as e:
                self.__iface.messageBar().pushMessage(
                    QCoreApplication.translate("VDLTools", "Mouse event exception : ") + str(e),
                    level=QgsMessageBar.CRITICAL, duration=0)
            xdata = float(event.xdata)
            self.__vline = self.__plotWdg.figure.get_axes()[0].axvline(xdata, linewidth=2, color='k')
            self.__plotWdg.draw()
            i = 1
            while i < len(self.__tabmouseevent)-1 and xdata > self.__tabmouseevent[i][0]:
                i += 1
            i -= 1

            x = self.__tabmouseevent[i][1] + (self.__tabmouseevent[i + 1][1] - self.__tabmouseevent[i][1]) / (
            self.__tabmouseevent[i + 1][0] - self.__tabmouseevent[i][0]) * (xdata - self.__tabmouseevent[i][0])
            y = self.__tabmouseevent[i][2] + (self.__tabmouseevent[i + 1][2] - self.__tabmouseevent[i][2]) / (
            self.__tabmouseevent[i + 1][0] - self.__tabmouseevent[i][0]) * (xdata - self.__tabmouseevent[i][0])
            self.__marker.show()
            self.__marker.setCenter(QgsPoint(x, y))

    def __loadRubber(self):
        """
        To load te rubber band for mouse tracking on map
        """
        self.__marker = QgsVertexMarker(self.__canvas)
        self.__marker.setIconSize(5)
        self.__marker.setIconType(QgsVertexMarker.ICON_BOX)
        self.__marker.setPenWidth(3)

    def __prepare_points(self):
        """
        To prepare the points on map for mouse tracking on profile
        """
        self.__tabmouseevent = []
        length = 0
        for i, point in enumerate(self.__profiles):
            if i == 0:
                self.__tabmouseevent.append([0, point['x'], point['y']])
            else:
                length += ((self.__profiles[i]['x'] - self.__profiles[i-1]['x']) ** 2 +
                           (self.__profiles[i]['y'] - self.__profiles[i-1]['y']) ** 2) ** 0.5
                self.__tabmouseevent.append([float(length), float(point['x']), float(point['y'])])

    def closeEvent(self, event):
        """
        When the dock widget is closed
        :param event: close event
        """
        if self.__maxSpin is not None:
            Signal.safelyDisconnect(self.__maxSpin.valueChanged, self.__reScalePlot)
            self.__maxSpin = None
        if self.__minSpin is not None:
            Signal.safelyDisconnect(self.__minSpin.valueChanged, self.__reScalePlot)
            self.__minSpin = None
        if self.__saveButton is not None:
            Signal.safelyDisconnect(self.__saveButton.clicked, self.__save)
            self.__saveButton = None
        if self.__libCombo is not None:
            Signal.safelyDisconnect(self.__libCombo.currentIndexChanged, self.__setLib)
            self.__libCombo = None
        self.closeSignal.emit()
        if self.__marker is not None:
            self.__marker.hide()
        QDockWidget.closeEvent(self, event)
Пример #3
0
class ProfileDockWidget(QDockWidget):
    """
    DockWidget class to display the profile
    """

    closeSignal = pyqtSignal()

    def __init__(self, iface, geometry, mntButton=False, zerosButton=False):
        """
        Constructor
        :param iface: interface
        :param width: dock widget geometry
        """
        QDockWidget.__init__(self)
        self.setWindowTitle(QCoreApplication.translate("VDLTools", "Profile Tool"))
        self.__iface = iface
        self.__geom = geometry
        self.__canvas = self.__iface.mapCanvas()
        self.__types = ['PDF', 'PNG']  # ], 'SVG', 'PS']
        self.__libs = []
        if Qwt5_loaded:
            self.__lib = 'Qwt5'
            self.__libs.append('Qwt5')
            if matplotlib_loaded:
                self.__libs.append('Matplotlib')
        elif matplotlib_loaded:
            self.__lib = 'Matplotlib'
            self.__libs.append('Matplotlib')
        else:
            self.__lib = None
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "No graph lib available (qwt5 or matplotlib)"),
                level=QgsMessageBar.CRITICAL, duration=0)

        self.__doTracking = False
        self.__vline = None

        self.__profiles = None
        self.__numLines = None
        self.__mntPoints = None

        self.__marker = None
        self.__tabmouseevent = None

        if self.__geom is not None:
            self.setGeometry(self.__geom)

        self.__contentWidget = QWidget()
        self.setWidget(self.__contentWidget)

        self.__boxLayout = QHBoxLayout()
        self.__contentWidget.setLayout(self.__boxLayout)

        self.__plotFrame = QFrame()
        self.__frameLayout = QHBoxLayout()
        self.__plotFrame.setLayout(self.__frameLayout)

        self.__printLayout = QHBoxLayout()
        self.__printLayout.addWidget(self.__plotFrame)

        self.__legendLayout = QVBoxLayout()
        self.__printLayout.addLayout(self.__legendLayout)

        self.__printWdg = QWidget()
        self.__printWdg.setLayout(self.__printLayout)

        self.__plotWdg = None
        self.__changePlotWidget()

        size = QSize(150, 20)

        self.__boxLayout.addWidget(self.__printWdg)

        self.__vertLayout = QVBoxLayout()

        self.__libCombo = QComboBox()
        self.__libCombo.setFixedSize(size)
        self.__libCombo.addItems(self.__libs)
        self.__vertLayout.addWidget(self.__libCombo)
        self.__libCombo.currentIndexChanged.connect(self.__setLib)

        if mntButton:
            self.__displayMnt = False
            self.__mntButton = QPushButton(QCoreApplication.translate("VDLTools", "Display MNT"))
            self.__mntButton.setFixedSize(size)
            self.__mntButton.clicked.connect(self.__mnt)
            self.__vertLayout.addWidget(self.__mntButton)

        if zerosButton:
            self.__displayZeros = False
            self.__zerosButton = QPushButton(QCoreApplication.translate("VDLTools", "Display Zeros"))
            self.__zerosButton.setFixedSize(size)
            self.__zerosButton.clicked.connect(self.__zeros)
            self.__vertLayout.addWidget(self.__zerosButton)
        else:
            self.__displayZeros = True

        self.__maxLabel = QLabel("y max")
        self.__maxLabel.setFixedSize(size)
        self.__vertLayout.addWidget(self.__maxLabel)
        self.__maxSpin = QSpinBox()
        self.__maxSpin.setFixedSize(size)
        self.__maxSpin.setRange(-10000, 10000)
        self.__maxSpin.valueChanged.connect(self.__reScalePlot)
        self.__vertLayout.addWidget(self.__maxSpin)
        self.__vertLayout.insertSpacing(10, 20)

        self.__minLabel = QLabel("y min")
        self.__minLabel.setFixedSize(size)
        self.__vertLayout.addWidget(self.__minLabel)
        self.__minSpin = QSpinBox()
        self.__minSpin.setFixedSize(size)
        self.__minSpin.setRange(-10000, 10000)
        self.__minSpin.valueChanged.connect(self.__reScalePlot)
        self.__vertLayout.addWidget(self.__minSpin)
        self.__vertLayout.insertSpacing(10, 40)

        self.__typeCombo = QComboBox()
        self.__typeCombo.setFixedSize(size)
        self.__typeCombo.addItems(self.__types)
        self.__vertLayout.addWidget(self.__typeCombo)
        self.__saveButton = QPushButton(QCoreApplication.translate("VDLTools", "Save"))
        self.__saveButton.setFixedSize(size)
        self.__saveButton.clicked.connect(self.__save)
        self.__vertLayout.addWidget(self.__saveButton)

        self.__boxLayout.addLayout(self.__vertLayout)

        self.__maxSpin.setEnabled(False)
        self.__minSpin.setEnabled(False)

        self.__colors = []
        for cn in QColor.colorNames():
            qc = QColor(cn)
            val = qc.red() + qc.green() + qc.blue()
            if 0 < val < 450:
                self.__colors.append(cn)

    def mntButton(self):
        """
        To get the mnt button instance
        :return: mnt button instance
        """
        return self.__mntButton

    def zerosButton(self):
        """
        To get the zeros button instance
        :return: zeros button instance
        """
        return self.__zerosButton

    def displayMnt(self):
        """
        To get if we want to display mnt
        :return: true or false
        """
        return self.__displayMnt

    def __mnt(self):
        """
        To toggle mnt display choice
        """
        if self.__displayMnt:
            self.__displayMnt = False
            self.__mntButton.setText(QCoreApplication.translate("VDLTools", "Display MNT"))
        else:
            self.__displayMnt = True
            self.__mntButton.setText(QCoreApplication.translate("VDLTools", "Remove MNT"))

    def __zeros(self):
        """
        To toggle if we want to display zero elevations or not
        """
        if self.__displayZeros:
            self.__displayZeros = False
            self.__zerosButton.setText(QCoreApplication.translate("VDLTools", "Display Zeros"))
        else:
            self.__displayZeros = True
            self.__zerosButton.setText(QCoreApplication.translate("VDLTools", "Remove Zeros"))

    def __changePlotWidget(self):
        """
        When plot widget is change (qwt <-> matplotlib)
        """
        self.__activateMouseTracking(False)
        while self.__frameLayout.count():
            child = self.__frameLayout.takeAt(0)
            child.widget().deleteLater()
        self.__plotWdg = None

        if self.__lib == 'Qwt5':
            self.__plotWdg = QwtPlot(self.__plotFrame)
            sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            sizePolicy.setHorizontalStretch(10)
            sizePolicy.setVerticalStretch(0)
            self.__plotWdg.setSizePolicy(sizePolicy)
            self.__plotWdg.setAutoFillBackground(False)
            # Decoration
            self.__plotWdg.setCanvasBackground(Qt.white)
            self.__plotWdg.plotLayout().setAlignCanvasToScales(False)
            self.__plotWdg.plotLayout().setSpacing(100)
            self.__plotWdg.plotLayout().setCanvasMargin(10, QwtPlot.xBottom)
            self.__plotWdg.plotLayout().setCanvasMargin(10, QwtPlot.yLeft)
            title = QwtText(QCoreApplication.translate("VDLTools", "Distance [m]"))
            title.setFont(QFont("Helvetica", 10))
            self.__plotWdg.setAxisTitle(QwtPlot.xBottom, title)
            title.setText(QCoreApplication.translate("VDLTools", "Elevation [m]"))
            title.setFont(QFont("Helvetica", 10))
            self.__plotWdg.setAxisTitle(QwtPlot.yLeft, title)
            self.__zoomer = QwtPlotZoomer(QwtPlot.xBottom, QwtPlot.yLeft, QwtPicker.DragSelection, QwtPicker.AlwaysOff,
                                          self.__plotWdg.canvas())
            self.__zoomer.setRubberBandPen(QPen(Qt.blue))
            grid = QwtPlotGrid()
            grid.setPen(QPen(QColor('grey'), 0, Qt.DotLine))
            grid.attach(self.__plotWdg)
            self.__frameLayout.addWidget(self.__plotWdg)

        elif self.__lib == 'Matplotlib':
            fig = Figure((1.0, 1.0), linewidth=0.0, subplotpars=SubplotParams(left=0, bottom=0, right=1, top=1,
                                                                              wspace=0, hspace=0))

            font = {'family': 'arial', 'weight': 'normal', 'size': 12}
            rc('font', **font)

            rect = fig.patch
            rect.set_facecolor((0.9, 0.9, 0.9))

            self.__axes = fig.add_axes((0.07, 0.16, 0.92, 0.82))
            self.__axes.set_xbound(0, 1000)
            self.__axes.set_ybound(0, 1000)
            self.__manageMatplotlibAxe(self.__axes)
            self.__plotWdg = FigureCanvasQTAgg(fig)
            sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            self.__plotWdg.setSizePolicy(sizePolicy)
            self.__frameLayout.addWidget(self.__plotWdg)

    def setProfiles(self, profiles, numLines):
        """
        To set the profiles
        :param profiles: profiles : positions with elevations (for line and points)
        :param numLines: number of selected connected lines
        """
        self.__numLines = numLines
        self.__profiles = profiles
        if self.__lib == 'Matplotlib':
            self.__prepare_points()

    def __getLinearPoints(self):
        """
        To extract the linear points of the profile
        """
        profileLen = 0
        self.__profiles[0]['l'] = profileLen
        for i in range(0, len(self.__profiles)-1):
            x1 = float(self.__profiles[i]['x'])
            y1 = float(self.__profiles[i]['y'])
            x2 = float(self.__profiles[i+1]['x'])
            y2 = float(self.__profiles[i+1]['y'])
            profileLen += sqrt(((x2-x1)*(x2-x1)) + ((y2-y1)*(y2-y1)))
            self.__profiles[i+1]['l'] = profileLen

    def __getMnt(self, settings):
        """
        To get the MN data for the profile
        :param settings: settings containing MN url
        """
        if settings is None or settings.mntUrl is None or settings.mntUrl == "None":
            url = 'https://map.lausanne.ch/prod/wsgi/profile.json'
        elif settings.mntUrl == "":
            return
        else:
            url = settings.mntUrl
        names = ['MNT', 'MNS', 'Rocher (approx.)']
        data = "layers=MNT%2CMNS%2CRocher%20(approx.)&geom=%7B%22type%22%3A%22LineString%22%2C%22coordinates%22%3A%5B"

        pos = 0
        for i in range(len(self.__profiles)):
            if pos > 0:
                data += "%2C"
            pos += 1
            data += "%5B" + str(self.__profiles[i]['x']) + "%2C" + str(self.__profiles[i]['y']) + "%5D"
        data += "%5D%7D&nbPoints=" + str(int(self.__profiles[len(self.__profiles)-1]['l']+1))
        try:
            response = requests.post(url, data=data)
            j = response.text
            j_obj = json.loads(j)
            profile = j_obj['profile']
            self.__mntPoints = []
            self.__mntPoints.append(names)
            mnt_l = []
            mnt_z = []
            for p in range(len(names)):
                z = []
                mnt_z.append(z)
            for pt in profile:
                mnt_l.append(float(pt['dist']))
                values = pt['values']
                for p in range(len(names)):
                    if names[p] in values:
                        mnt_z[p].append(float(values[names[p]]))
                    else:
                        mnt_z[p].append(None)
            self.__mntPoints.append(mnt_l)
            self.__mntPoints.append(mnt_z)
        except HTTPError as e:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "HTTP Error"),
                QCoreApplication.translate("VDLTools", "status error") + "[" + str(e.code) + "] : " + e.reason,
                level=QgsMessageBar.CRITICAL, duration=0)
        except URLError as e:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "URL Error"),
                e.reason, level=QgsMessageBar.CRITICAL, duration=0)
        except ValueError as e:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "No MNT values here"),
                level=QgsMessageBar.CRITICAL, duration=0)


    def attachCurves(self, names, settings, usedMnts):
        """
        To attach the curves for the layers to the profile
        :param names: layers names
        """
        if (self.__profiles is None) or (self.__profiles == 0):
            return

        self.__getLinearPoints()
        if usedMnts is not None and (usedMnts[0] or usedMnts[1] or usedMnts[2]):
            self.__getMnt(settings)

        c = 0

        if self.__mntPoints is not None:
                for p in range(len(self.__mntPoints[0])):
                    if usedMnts[p]:
                        legend = QLabel("<font color='" + self.__colors[c] + "'>" + self.__mntPoints[0][p]
                                        + "</font>")
                        self.__legendLayout.addWidget(legend)

                        if self.__lib == 'Qwt5':

                            xx = [list(g) for k, g in itertools.groupby(self.__mntPoints[1],
                                                                        lambda x: x is None) if not k]
                            yy = [list(g) for k, g in itertools.groupby(self.__mntPoints[2][p], lambda x: x is None)
                                  if not k]

                            for j in range(len(xx)):
                                curve = QwtPlotCurve(self.__mntPoints[0][p])
                                curve.setData(xx[j], yy[j])
                                curve.setPen(QPen(QColor(self.__colors[c]), 3))
                                curve.attach(self.__plotWdg)

                        elif self.__lib == 'Matplotlib':
                            qcol = QColor(self.__colors[c])
                            self.__plotWdg.figure.get_axes()[0].plot(self.__mntPoints[1], self.__mntPoints[2][p],
                                                                     gid=self.__mntPoints[0][p], linewidth=3)
                            tmp = self.__plotWdg.figure.get_axes()[0].get_lines()
                            for t in range(len(tmp)):
                                if self.__mntPoints[0][p] == tmp[t].get_gid():
                                    tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0),
                                                      old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0)))
                                    self.__plotWdg.draw()
                                    break
                        c += 1

        if 'z' in self.__profiles[0]:
            for i in range(len(self.__profiles[0]['z'])):
                if i < self.__numLines:
                    v = 0
                else:
                    v = i - self.__numLines + 1
                name = names[v]
                xx = []
                yy = []
                for prof in self.__profiles:
                    xx.append(prof['l'])
                    yy.append(prof['z'][i])

                for j in range(len(yy)):
                    if yy[j] is None:
                        xx[j] = None

                if i == 0 or i > (self.__numLines-1):
                    legend = QLabel("<font color='" + self.__colors[c] + "'>" + name + "</font>")
                    self.__legendLayout.addWidget(legend)

                if self.__lib == 'Qwt5':

                    # Split xx and yy into single lines at None values
                    xx = [list(g) for k, g in itertools.groupby(xx, lambda x: x is None) if not k]
                    yy = [list(g) for k, g in itertools.groupby(yy, lambda x: x is None) if not k]

                    # Create & attach one QwtPlotCurve per one single line
                    for j in range(len(xx)):
                        curve = QwtPlotCurve(name)
                        curve.setData(xx[j], yy[j])
                        curve.setPen(QPen(QColor(self.__colors[c]), 3))
                        if i > (self.__numLines-1):
                            curve.setStyle(QwtPlotCurve.Dots)
                            pen = QPen(QColor(self.__colors[c]), 8)
                            pen.setCapStyle(Qt.RoundCap)
                            curve.setPen(pen)
                        curve.attach(self.__plotWdg)

                elif self.__lib == 'Matplotlib':
                    qcol = QColor(self.__colors[c])
                    if i < self.__numLines:
                        self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=3)
                    else:
                        self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=5, marker='o',
                                                                 linestyle='None')
                    tmp = self.__plotWdg.figure.get_axes()[0].get_lines()
                    for t in range(len(tmp)):
                        if name == tmp[t].get_gid():
                            tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0),
                                              old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0)))
                            self.__plotWdg.draw()
                            break
                c += 1

        # scaling this
        try:
            self.__reScalePlot(None, True)
        except:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "Rescale problem... (trace printed)"),
                level=QgsMessageBar.CRITICAL, duration=0)
            print(sys.exc_info()[0], traceback.format_exc())
        if self.__lib == 'Qwt5':
            self.__plotWdg.replot()
        elif self.__lib == 'Matplotlib':
            self.__plotWdg.figure.get_axes()[0].redraw_in_frame()
            self.__plotWdg.draw()
            self.__activateMouseTracking(True)
            self.__marker.show()

    def __reScalePlot(self, value=None, auto=False):
        """
        To rescale the profile plot depending to the bounds
        :param value: juste because connections give value
        :param auto: if automatic ranges calcul is wanted
        """
        if (self.__profiles is None) or (self.__profiles == 0):
            self.__plotWdg.replot()
            return

        maxi = 0
        for i in range(len(self.__profiles)):
            if (ceil(self.__profiles[i]['l'])) > maxi:
                maxi = ceil(self.__profiles[i]['l'])
        if self.__lib == 'Qwt5':
            self.__plotWdg.setAxisScale(2, 0, maxi, 0)
        elif self.__lib == 'Matplotlib':
            self.__plotWdg.figure.get_axes()[0].set_xbound(0, maxi)

        minimumValue = self.__minSpin.value()
        maximumValue = self.__maxSpin.value()

        # to set max y and min y displayed
        if auto:
            minimumValue = 1000000000
            maximumValue = -1000000000
            for i in range(len(self.__profiles)):
                if 'z' in self.__profiles[i]:
                    mini = self.__minTab(self.__profiles[i]['z'])
                    if (mini > 0 or self.__displayZeros) and mini < minimumValue:
                        minimumValue = ceil(mini) - 1
                    maxi = self.__maxTab(self.__profiles[i]['z'])
                    if maxi > maximumValue:
                        maximumValue = floor(maxi) + 1
                if self.__mntPoints is not None:
                    for pts in self.__mntPoints[2]:
                        miniMnt = self.__minTab(pts)
                        if (miniMnt > 0 or self.__displayZeros) and miniMnt < minimumValue:
                            minimumValue = ceil(miniMnt) - 1
                        maxiMnt = self.__maxTab(pts)
                        if maxiMnt > maximumValue:
                            maximumValue = floor(maxiMnt) + 1
        self.__maxSpin.setValue(maximumValue)
        self.__minSpin.setValue(minimumValue)
        self.__maxSpin.setEnabled(True)
        self.__minSpin.setEnabled(True)

        if self.__lib == 'Qwt5':
            rect = QRectF(0, minimumValue, maxi, maximumValue-minimumValue)
            self.__zoomer.setZoomBase(rect)

        # to draw vertical lines
        for i in range(len(self.__profiles)):
            zz = []
            for j in range(self.__numLines):
                if self.__profiles[i]['z'][j] is not None:
                    zz.append(j)
            color = None
            if len(zz) == 2:
                width = 3
                color = QColor('red')
            else:
                width = 1

            if self.__lib == 'Qwt5':
                vertLine = QwtPlotMarker()
                vertLine.setLineStyle(QwtPlotMarker.VLine)
                pen = vertLine.linePen()
                pen.setWidth(width)
                if color is not None:
                    pen.setColor(color)
                vertLine.setLinePen(pen)
                vertLine.setXValue(self.__profiles[i]['l'])
                label = vertLine.label()
                label.setText(str(i))
                vertLine.setLabel(label)
                vertLine.setLabelAlignment(Qt.AlignLeft)
                vertLine.attach(self.__plotWdg)
            elif self.__lib == 'Matplotlib':
                self.__plotWdg.figure.get_axes()[0].vlines(self.__profiles[i]['l'], minimumValue, maximumValue,
                                                           linewidth=width)

        if minimumValue < maximumValue:
            if self.__lib == 'Qwt5':
                self.__plotWdg.setAxisScale(0, minimumValue, maximumValue, 0)
                self.__plotWdg.replot()
            elif self.__lib == 'Matplotlib':
                self.__plotWdg.figure.get_axes()[0].set_ybound(minimumValue, maximumValue)
                self.__plotWdg.figure.get_axes()[0].redraw_in_frame()
                self.__plotWdg.draw()

    @staticmethod
    def __minTab(tab):
        """
        To get the minimum value in a table
        :param tab: table to scan
        :return: minimum value
        """
        mini = 1000000000
        for t in tab:
            if t is None:
                continue
            if t < mini:
                mini = t
        return mini

    @staticmethod
    def __maxTab(tab):
        """
        To get the maximum value in a table
        :param tab: table to scan
        :return: maximum value
        """
        maxi = -1000000000
        for t in tab:
            if t is None:
                continue
            if t > maxi:
                maxi = t
        return maxi

    def __setLib(self):
        """
        To set the new widget library (qwt <-> matplotlib)
        """
        self.__lib = self.__libs[self.__libCombo.currentIndex()]
        self.__changePlotWidget()

    def __save(self):
        """
        To save the profile in a file, on selected format
        """
        idx = self.__typeCombo.currentIndex()
        if idx == 0:
            self.__outPDF()
        elif idx == 1:
            self.__outPNG()
        else:
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "Invalid index ") + str(idx),
                level=QgsMessageBar.CRITICAL, duration=0)

    def __outPDF(self):
        """
        To save the profile as pdf file
        """
        fileName = QFileDialog.getSaveFileName(
            self.__iface.mainWindow(), QCoreApplication.translate("VDLTools", "Save As"),
            QCoreApplication.translate("VDLTools", "Profile.pdf"),"Portable Document Format (*.pdf)")
        if fileName is not None:
            if self.__lib == 'Qwt5':
                printer = QPrinter()
                printer.setCreator(QCoreApplication.translate("VDLTools", "QGIS Profile Plugin"))
                printer.setOutputFileName(fileName)
                printer.setOutputFormat(QPrinter.PdfFormat)
                printer.setOrientation(QPrinter.Landscape)
                self.__plotWdg.print_(printer)
            elif self.__lib == 'Matplotlib':
                self.__plotWdg.figure.savefig(str(fileName))

    def __outPNG(self):
        """
        To save the profile as png file
        """
        fileName = QFileDialog.getSaveFileName(
            self.__iface.mainWindow(), QCoreApplication.translate("VDLTools", "Save As"),
            QCoreApplication.translate("VDLTools", "Profile.png"),"Portable Network Graphics (*.png)")
        if fileName is not None:
            QPixmap.grabWidget(self.__printWdg).save(fileName, "PNG")

    def clearData(self):
        """
        To clear the displayed data
        """
        if self.__profiles is None:
            return
        if self.__lib == 'Qwt5':
            self.__plotWdg.clear()
            self.__profiles = None
            temp1 = self.__plotWdg.itemList()
            for j in range(len(temp1)):
                if temp1[j].rtti() == QwtPlotItem.Rtti_PlotCurve:
                    temp1[j].detach()
        elif self.__lib == 'Matplotlib':
            self.__plotWdg.figure.get_axes()[0].cla()
            self.__manageMatplotlibAxe(self.__plotWdg.figure.get_axes()[0])
        self.__maxSpin.setEnabled(False)
        self.__minSpin.setEnabled(False)
        self.__maxSpin.setValue(0)
        self.__minSpin.setValue(0)

        # clear legend
        while self.__legendLayout.count():
            child = self.__legendLayout.takeAt(0)
            child.widget().deleteLater()

    def __manageMatplotlibAxe(self, axe):
        """
        To manage the axes for matplotlib library
        :param axe: the axes element
        """
        axe.grid()
        axe.tick_params(axis="both", which="major", direction="out", length=10, width=1, bottom=True, top=False,
                        left=True, right=False)
        axe.minorticks_on()
        axe.tick_params(axis="both", which="minor", direction="out", length=5, width=1, bottom=True, top=False,
                        left=True, right=False)
        axe.set_xlabel(QCoreApplication.translate("VDLTools", "Distance [m]"))
        axe.set_ylabel(QCoreApplication.translate("VDLTools", "Elevation [m]"))

    def __activateMouseTracking(self, activate):
        """
        To (de)activate the mouse tracking on the profile for matplotlib library
        :param activate: true to activate, false to deactivate
        """
        if activate:
            self.__doTracking = True
            self.__loadRubber()
            self.cid = self.__plotWdg.mpl_connect('motion_notify_event', self.__mouseevent_mpl)
        elif self.__doTracking:
            self.__doTracking = False
            self.__plotWdg.mpl_disconnect(self.cid)
            if self.__marker is not None:
                self.__canvas.scene().removeItem(self.__marker)
            try:
                if self.__vline is not None:
                    self.__plotWdg.figure.get_axes()[0].lines.remove(self.__vline)
                    self.__plotWdg.draw()
            except Exception as e:
                self.__iface.messageBar().pushMessage(
                    QCoreApplication.translate("VDLTools", "Tracking exception : ") + str(e),
                    level=QgsMessageBar.CRITICAL, duration=0)

    def __mouseevent_mpl(self, event):
        """
        To manage matplotlib mouse tracking event
        :param event: mouse tracking event
        """
        if event.xdata is not None:
            try:
                if self.__vline is not None:
                    self.__plotWdg.figure.get_axes()[0].lines.remove(self.__vline)
            except Exception as e:
                self.__iface.messageBar().pushMessage(
                    QCoreApplication.translate("VDLTools", "Mouse event exception : ") + str(e),
                    level=QgsMessageBar.CRITICAL, duration=0)
            xdata = float(event.xdata)
            self.__vline = self.__plotWdg.figure.get_axes()[0].axvline(xdata, linewidth=2, color='k')
            self.__plotWdg.draw()
            i = 1
            while i < len(self.__tabmouseevent)-1 and xdata > self.__tabmouseevent[i][0]:
                i += 1
            i -= 1

            x = self.__tabmouseevent[i][1] + (self.__tabmouseevent[i + 1][1] - self.__tabmouseevent[i][1]) / (
            self.__tabmouseevent[i + 1][0] - self.__tabmouseevent[i][0]) * (xdata - self.__tabmouseevent[i][0])
            y = self.__tabmouseevent[i][2] + (self.__tabmouseevent[i + 1][2] - self.__tabmouseevent[i][2]) / (
            self.__tabmouseevent[i + 1][0] - self.__tabmouseevent[i][0]) * (xdata - self.__tabmouseevent[i][0])
            self.__marker.show()
            self.__marker.setCenter(QgsPoint(x, y))

    def __loadRubber(self):
        """
        To load te rubber band for mouse tracking on map
        """
        self.__marker = QgsVertexMarker(self.__canvas)
        self.__marker.setIconSize(5)
        self.__marker.setIconType(QgsVertexMarker.ICON_BOX)
        self.__marker.setPenWidth(3)

    def __prepare_points(self):
        """
        To prepare the points on map for mouse tracking on profile
        """
        self.__tabmouseevent = []
        length = 0
        for i, point in enumerate(self.__profiles):
            if i == 0:
                self.__tabmouseevent.append([0, point['x'], point['y']])
            else:
                length += ((self.__profiles[i]['x'] - self.__profiles[i-1]['x']) ** 2 +
                           (self.__profiles[i]['y'] - self.__profiles[i-1]['y']) ** 2) ** 0.5
                self.__tabmouseevent.append([float(length), float(point['x']), float(point['y'])])

    def closeEvent(self, event):
        """
        When the dock widget is closed
        :param event: close event
        """
        if self.__maxSpin is not None:
            Signal.safelyDisconnect(self.__maxSpin.valueChanged, self.__reScalePlot)
            self.__maxSpin = None
        if self.__minSpin is not None:
            Signal.safelyDisconnect(self.__minSpin.valueChanged, self.__reScalePlot)
            self.__minSpin = None
        if self.__saveButton is not None:
            Signal.safelyDisconnect(self.__saveButton.clicked, self.__save)
            self.__saveButton = None
        if self.__libCombo is not None:
            Signal.safelyDisconnect(self.__libCombo.currentIndexChanged, self.__setLib)
            self.__libCombo = None
        self.closeSignal.emit()
        if self.__marker is not None:
            self.__marker.hide()
        QDockWidget.closeEvent(self, event)