def setSceneRect(self, rect):
     QGraphicsScene.setSceneRect(self, rect)
     h = rect.height() - self.yOffset * 2
     if self.zMax != self.zMin:
         self.zScale = h / (self.zMax - self.zMin)
     else:
         self.zScale = 1.0
    def displayPlot(self):
        QGraphicsScene.clear(self)
        self.sceneRect()
        fm = QFontMetrics(QFont())

        # display lines fitting in sceneRect
        last = None
        for z1, z2, text in self.data:
            brush = QBrush(
                QColor.fromHsl(z2 / (self.zMax - self.zMin) * 360.0, 128, 128)
            )
            self.addRect(
                self.xOffset + self.legendWidth,
                z1 * self.zScale + self.yOffset,
                self.barWidth,
                (z2 - z1) * self.zScale,
                QPen(),
                brush,
            )

            if last is None:
                legend_item = self.addSimpleText("{}".format(z1))
                legend_item.setPos(self.xOffset, z1 * self.zScale + self.yOffset)
            legend_item = self.addSimpleText("{}".format(z2))
            legend_item.setPos(self.xOffset, z2 * self.zScale + self.yOffset)
            last = z2

            text_item = self.addSimpleText(text)
            text_item.setPos(
                self.xOffset * 2 + self.legendWidth + self.barWidth,
                (z1 + z2) / 2.0 * self.zScale - fm.height() / 2.0 + self.yOffset,
            )
 def clear(self):
     QGraphicsScene.clear(self)
     self.data = []
     self.xMin = 0
     self.xMax = 0
     self.yMin = 0
     self.yMax = 0
 def show_image(self, path, flags=Qt.KeepAspectRatioByExpanding):
     pic = QPixmap(path)
     grview = ImageViewClass(origPixmap=pic)
     scene = QGraphicsScene()
     scene.addPixmap(pic)
     grview.setScene(scene)
     self.gridLayout_2.addWidget(grview)
 def clear(self):
     QGraphicsScene.clear(self)
     self.data = []
     self.zMin = 0
     self.zMax = 0
     self.width = 0
     self.zScale = 100.0
     self.legendWidth = 0
     self.xOffset = 5
     self.yOffset = 20
    def __init__(self, parent):
        QGraphicsScene.__init__(self, parent)

        self.zScale = 100.0
        # width (in pixels) of the bar
        self.barWidth = 20
        # offset from the left border
        self.xOffset = 10

        self.clear()
 def setSceneRect(self, rect):
     QGraphicsScene.setSceneRect(self, rect)
     w = rect.width() - self.barWidth
     if self.xMax != self.xMin:
         self.xRatio = w / (self.xMax - self.xMin)
     else:
         self.xRatio = 1.0
     h = rect.height() - self.yOffset * 2
     if self.yMax != self.yMin:
         self.yRatio = h / (self.yMax - self.yMin)
     else:
         self.yRatio = 1.0
Ejemplo n.º 8
0
    def run(self):
        """Run method that loads and starts the plugin"""

        if not self.pluginIsActive:
            self.pluginIsActive = True
            self.scene = QGraphicsScene()
            # Storing the spectra to be able to read out values later on
            # Setting the values storing line and text shown when the mouse button is clicked
            self.scene.crdtext = None
            self.scene.markerline = None
            self.scene.left = None
            # TODO: The four next settings to be user-settable
            self.tickinterval = 100
            s = QgsSettings()
            self.scene.acalib = s.value(self.pluginname + "/defaulta", 1)
            self.scene.bcalib = s.value(self.pluginname + "/defaultb", 0)
            self.scene.unit = s.value(self.pluginname + "/defaultunit", "Ch")
            self.dlg.leA.setText(str(self.scene.acalib))
            self.dlg.leB.setText(str(self.scene.bcalib))
            self.dlg.leUnit.setText(str(self.scene.unit))
            showch = False  # Set to True to show channel values
            if showch:
                self.scene.unit = 'Ch'
                self.scene.acalib = 1
                self.scene.bcalib = 0
            self.view.setScene(self.scene)
            self.scene.setSceneRect(0, 0, 1200, 300)
            # Replotting spectre when a new selection is made
            self.iface.mapCanvas().selectionChanged.connect(self.findselected)
            # Listing layers
            # DONE: Only list vector layers
            # DONE: Repopulate when layers are added or removed
            # DONE both by using qgisWidget
            self.dlg.pBCopy.clicked.connect(self.spectreToClipboard)
            self.dlg.pBUseDefault.clicked.connect(self.usedefault)
            self.dlg.pBSaveCalib.clicked.connect(self.saveCalibration)
            self.dlg.pBSave.clicked.connect(self.view.saveImage)

            # connect to provide cleanup on closing of dockwidget
            self.dlg.closingPlugin.connect(self.onClosePlugin)
            # show the dockwidget
            self.iface.mainWindow().addDockWidget(Qt.BottomDockWidgetArea,
                                                  self.dlg)
            self.dlg.show()
            self.dlg.cbLog.stateChanged.connect(self.findselected)
            self.dlg.cbDefault.stateChanged.connect(self.setdefault)
            self.dlg.qgField.currentIndexChanged['QString'].connect(
                self.prepareplot)
            self.dlg.qgLayer.currentIndexChanged['QString'].connect(
                self.prepareplot)
            self.dlg.leA.textChanged['QString'].connect(self.updatecalib)
            self.dlg.leB.textChanged['QString'].connect(self.updatecalib)
            self.findselected()
    def displayPlot(self):
        QGraphicsScene.clear(self)
        self.marker.clear()
        self.sceneRect()

        # display lines fitting in sceneRect
        poly = QPolygonF()
        for x, y, _ in self.data:
            poly.append(QPointF(self.xToScene(x), self.yToScene(y)))
        # close the polygon
        x2 = self.xToScene(self.xMax)
        y2 = self.sceneRect().height()
        poly.append(QPointF(x2, y2))
        x2 = self.barWidth
        poly.append(QPointF(x2, y2))
        x2 = self.xToScene(self.xMin)
        y2 = self.yToScene(0)
        poly.append(QPointF(x2, y2))
        brush = QBrush(QColor("#DCF1F7"))
        pen = QPen()
        pen.setWidth(0)
        self.addPolygon(poly, pen, brush)

        # horizontal line on ymin and ymax
        self.addLine(
            self.barWidth - 5,
            self.yToScene(self.yMin),
            self.barWidth + 5,
            self.yToScene(self.yMin),
        )
        self.addLine(
            self.barWidth - 5,
            self.yToScene(self.yMax),
            self.barWidth + 5,
            self.yToScene(self.yMax),
        )

        # display scale
        self.addLine(self.barWidth, 0, self.barWidth,
                     self.sceneRect().height())

        font = QFont()
        fm = QFontMetrics(font)
        t1 = self.addText("%.1f" % self.yMin)
        t1.setPos(0, self.yToScene(self.yMin) - fm.ascent())
        t2 = self.addText("%.1f" % self.yMax)
        t2.setPos(0, self.yToScene(self.yMax) - fm.ascent())

        # Z(m)
        t3 = self.addText(self.yTitle)
        t3.setPos(0, 0)
    def __init__(self, yTitle, parent):
        QGraphicsScene.__init__(self, parent)
        # width of the scale bar
        fm = QFontMetrics(QFont())
        # width = size of "100.0" with the default font + 10%
        self.yTitle = yTitle
        self.barWidth = max(fm.width(yTitle), fm.width("000.00"))
        self.xOffset = self.barWidth
        self.yOffset = fm.height() * 2

        # define the transformation between distance, altitude and scene coordinates
        self.xRatio = 1.0
        self.yRatio = 1.0

        self.marker = PointMarker(self)

        self.clear()
Ejemplo n.º 11
0
 def mouseMoveEvent(self, event):
     # pass the event to the underlying item
     for item in list(self.items()):
         r = item.boundingRect()
         r.translate(item.pos())
         if r.contains(event.scenePos()):
             return item.mouseMoveEvent(event)
     return QGraphicsScene.mouseMoveEvent(self, event)
Ejemplo n.º 12
0
    def __init__(self, parent=None):
        super(HelpPage, self).__init__(parent)
        self.setupUi(self)
        if self.parent():
            self.parent().installEventFilter(self)

        self.view = QGraphicsView()
        self.webView = QGraphicsWebView()
        self.scene = QGraphicsScene()
        self.webView.setResizesToContents(True)
        self.view.setScene(self.scene)
        self.scene.addItem(self.webView)

        self.webView.linkClicked.connect(RoamEvents.openurl.emit)
        self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)

        install_touch_scroll(self.view)
        self.layout().addWidget(self.view)
Ejemplo n.º 13
0
class HelpPage(helppage_widget, helppage_base):
    def __init__(self, parent=None):
        super(HelpPage, self).__init__(parent)
        self.setupUi(self)
        if self.parent():
            self.parent().installEventFilter(self)

        self.view = QGraphicsView()
        self.webView = QGraphicsWebView()
        self.scene = QGraphicsScene()
        self.webView.setResizesToContents(True)
        self.view.setScene(self.scene)
        self.scene.addItem(self.webView)

        self.webView.linkClicked.connect(RoamEvents.openurl.emit)
        self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)

        install_touch_scroll(self.view)
        self.layout().addWidget(self.view)

    def eventFilter(self, object, event):
        if event.type() == QEvent.Resize:
            self.setsize()
        elif event.type() == QEvent.MouseButtonPress:
            self.close()
        return object.eventFilter(object, event)

    def setsize(self):
        width = self.parent().width() * 50 / 100
        self.resize(width, self.parent().height())
        self.move(self.parent().width() - self.width() - 1, 1)

    def show(self):
        super(HelpPage, self).show()
        self.setsize()
        self.setFocus(Qt.PopupFocusReason)

    def setHelpPage(self, helppath):
        self.webView.load(QUrl.fromLocalFile(helppath))
Ejemplo n.º 14
0
    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/stripchart/icon.png'
        self.add_action(icon_path,
                        text=self.tr(u'Stripchart'),
                        callback=self.run,
                        parent=self.iface.mainWindow())
        self.dlg = StripChartDockWidget(self.iface.mainWindow())
        self.view.setParent(self.dlg)
        self.dlg.vlMain.addWidget(self.view)
        self.scene = QGraphicsScene()
        self.view.setScene(self.scene)
        self.scene.setSceneRect(0, 0, 300, 2000)
        self.dlg.qgLayer.setFilters(QgsMapLayerProxyModel.VectorLayer)
        self.dlg.qgLayer.setLayer(self.iface.activeLayer())
        self.dlg.qgField.setAllowEmptyFieldName(True)
        self.dlg.qgField.setLayer(self.dlg.qgLayer.currentLayer())
        self.dlg.qgField.setFilters(QgsFieldProxyModel.Numeric)
        self.dlg.qgLayer.layerChanged.connect(self.selectedlayer)
        self.iface.mapCanvas().selectionChanged.connect(self.markselected)
        self.dlg.qgField.currentIndexChanged['QString'].connect(
            self.stripchart)
Ejemplo n.º 15
0
 def altplot(self, dataset, graphicsview):
     w = graphicsview.width()
     h = graphicsview.height()
     air = 39
     #bt=airborne
     plotw = w - air * 2
     ploth = h - air * 2
     scene = QGraphicsScene()
     graphicsview.setScene(scene)
     xspan = [min(dataset[0]), max(dataset[0])]
     yspan = [min(dataset[1]), max(dataset[1])]
     xfact = (xspan[1] - xspan[0]) / plotw
     yfact = (yspan[1] - yspan[0]) / ploth
     rad = 2
     xaxy = float(ploth + rad * 2)
     yaxx = float(air - 1)
     scene.addLine(yaxx, xaxy, yaxx, air / 2)  # Y-axis
     scene.addLine(yaxx, xaxy, float(w - air / 2), xaxy)  # X-axis
     for alt, meas in zip(dataset[0], dataset[1]):
         x = (alt - xspan[0]) / xfact + air
         y = ploth - (meas - yspan[0]) / yfact
         scene.addEllipse(x, y, rad * 2, rad * 2)
Ejemplo n.º 16
0
    def __init__(self, model, parent):
        QGraphicsScene.__init__(self, parent)

        tables_coords = []
        spiral = spiral_iterator()
        min_grid_x = None
        max_grid_x = None
        min_grid_y = None
        max_grid_y = None
        self.table_items = {}
        for table_name, table in model.tables().items():
            # widget, grid_x, grid_y, x, y
            grid_x, grid_y = next(spiral)
            if grid_x > max_grid_x or max_grid_x is None:
                max_grid_x = grid_x
            if grid_x < min_grid_x or min_grid_x is None:
                min_grid_x = grid_x
            if grid_y > max_grid_y or max_grid_y is None:
                max_grid_y = grid_y
            if grid_y < min_grid_y or min_grid_y is None:
                min_grid_y = grid_y
            w = TableWidget(table)
            w.linkActivated.connect(self.tableSelected)
            tw = self.addWidget(w)
            tables_coords.append((tw, grid_x, grid_y, 0, 0, table_name))
            self.table_items[table_name] = tw

        # resolve columns / rows size
        column_width = {}
        row_height = {}
        for table, grid_x, grid_y, x, y, _ in tables_coords:
            wmax = column_width.get(grid_x)
            hmax = row_height.get(grid_y)
            wsize = table.widget().size()
            if wsize.width() > wmax or wmax is None:
                column_width[grid_x] = wsize.width()
            if wsize.height() > hmax or hmax is None:
                row_height[grid_y] = wsize.height()

        # total_width = sum(column_width.values())
        # total_height = sum(row_height.values())

        # resolve coordinates
        column_x = {}
        row_y = {}
        w = 0
        for x in range(min_grid_x, max_grid_x + 1):
            column_x[x] = w
            w += column_width[x]
        h = 0
        for y in range(min_grid_y, max_grid_y + 1):
            row_y[y] = h
            h += row_height[y]

        table_pos = {}
        for i in range(len(tables_coords)):
            table, grid_x, grid_y, _, _, table_name = tables_coords[i]
            wsize = table.widget().size()
            x = column_x[grid_x] + (column_width[grid_x] - wsize.width()) / 2.0
            y = row_y[grid_y] + (row_height[grid_y] - wsize.height()) / 2.0
            tables_coords[i] = (table, x, y)
            table_pos[table_name] = (x, y, wsize.width(), wsize.height(), table)
            table.setPos(x, y)

        def distance(p1, p2):
            l = QLineF(p1, p2)
            return l.length()

        # display links arrows
        def add_link(table_name, table_name2, y_idx):
            tx, ty, tw, th, table = table_pos[table_name]
            tx2, ty2, tw2, th2, _ = table_pos[table_name2]
            (ax, ay, aw, ah) = table.widget().attributeCoords(y_idx)
            l1 = QLineF(ax - 3, ay + ah / 2.0, tx2 + tw2 / 2.0, ty2 + th2 / 2.0)
            l2 = QLineF(ax + aw + 3, ay + ah / 2.0, tx2 + tw2 / 2.0, ty2 + th2 / 2.0)
            if l1.length() < l2.length():
                p1 = l1.p1()
                l = l1
            else:
                p1 = l2.p1()
                l = l2

            # add a diamond
            ds = 6
            dbrush = QBrush(QColor("black"))
            diamond = QPolygonF(
                [
                    p1 + QPointF(0, ds),
                    p1 + QPointF(ds, 0),
                    p1 + QPointF(0, -ds),
                    p1 + QPointF(-ds, 0),
                    p1 + QPointF(0, ds),
                ]
            )
            i1 = self.addPolygon(diamond, QPen(), dbrush)

            # cross with the second table widget
            points = [
                horizontal_intersection(l, ty2, tx2, tx2 + tw2),
                horizontal_intersection(l, ty2 + th2, tx2, tx2 + tw2),
                vertical_intersection(l, tx2, ty2, ty2 + th2),
                vertical_intersection(l, tx2 + tw2, ty2, ty2 + th2),
            ]
            pp = [p for p in points if p is not None]
            p2 = min(pp, key=lambda p: distance(p1, p))
            l = QLineF(p1, p2)
            i2 = self.addLine(l)
            i2.setZValue(1)
            alpha = math.atan2(p2.y() - p1.y(), p2.x() - p1.x())
            alpha1 = alpha + 30.0 / 180.0 * math.pi
            alpha2 = alpha - 30.0 / 180.0 * math.pi
            r = -10
            p3 = QPointF(r * math.cos(alpha1), r * math.sin(alpha1)) + p2
            p4 = QPointF(r * math.cos(alpha2), r * math.sin(alpha2)) + p2
            i3 = self.addLine(QLineF(p2, p3))
            i4 = self.addLine(QLineF(p2, p4))
            return [i1, i2, i3, i4]

        for table_name, table in model.tables().items():
            tw = self.table_items[table_name]
            y = len(table.columns())
            items = [tw]
            for l in table.links():
                if l.max_occurs() != 1:
                    continue
                items += add_link(table_name, l.ref_table().name(), y)
                y += 1
            for l in table.back_links():
                items += add_link(table_name, l.ref_table().name(), y)
                y += 1
            self.table_items[table_name] = items

            # make items invisible for now
            for item in items[1:]:
                disable_link_item(item)
Ejemplo n.º 17
0
 def __init__(self, x, y, w, h):
     QGraphicsScene.__init__(self, x, y, w, h)
Ejemplo n.º 18
0
    def __init__(self, iface, parent=None):
        """Constructor."""
        self.iface = iface
        super(BOSDialog, 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)

        # Some constants for translated text
        self.BOS = self.tr('BOS')
        self.BROWSE = self.tr('Browse')
        self.CANCEL = self.tr('Cancel')
        self.HELP = self.tr('Help')
        self.CLOSE = self.tr('Close')
        self.OK = self.tr('OK')
        #self.NUMBEROFSTEPS = 10  # Number of steps

        self.labelTextSize = 8
        self.titleTextSize = 10

        self.INPUT = 'input'
        self.REF = 'reference'

        okButton = self.button_box.button(QDialogButtonBox.Ok)
        okButton.setText(self.OK)
        cancelButton = self.button_box.button(QDialogButtonBox.Cancel)
        cancelButton.setText(self.CANCEL)
        helpButton = self.helpButton
        helpButton.setText(self.HELP)
        self.BOSscene = QGraphicsScene(self)
        self.BOSGraphicsView.setScene(self.BOSscene)

        # Connect signals
        okButton.clicked.connect(self.startWorker)
        #self.displacementButton.clicked.connect(self.showPlots)
        #self.avgdispButton.clicked.connect(self.showAverageDisplacement)
        #self.oscillationButton.clicked.connect(self.showOscillation)
        #self.complmiscButton.clicked.connect(self.showComplenessMiscoding)
        #self.saveSvgButton.clicked.connect(self.saveAsSVG)
        #self.saveAsPdfButton.clicked.connect(self.saveAsPDF)
        # Global variables with mutexes
        # Dictionary variable for input buffers
        self.inputbuffers = {}
        self.ibmutex = Lock()
        # Dictionary variable for reference buffers
        self.referencebuffers = {}
        self.rbmutex = Lock()
        # Variables for statistics
        # Number of polygons:
        self.polycount = {}
        self.pcmutex = Lock()
        # Complenetess values:
        self.completeness = {}
        self.comutex = Lock()
        # Miscoding values:
        self.miscodings = {}
        self.mimutex = Lock()
        # Other statistics
        self.statistics = {}
        self.stmutex = Lock()

        self.testcounter = 0
        self.tcmutex = Lock()

        self.radiuses = []

        # This one fires "immediately"?
        QgsApplication.taskManager().allTasksFinished.connect(
            self.all_tasks_completed)
    def __init__(self, iface, parent=None):
        """Constructor."""
        self.iface = iface
        self.plugin_dir = dirname(__file__)
        self.THINGREYSCALE = self.tr('ThinGreyscale')
        self.BROWSE = self.tr('Browse')
        self.CANCEL = self.tr('Cancel')
        self.CLOSE = self.tr('Close')
        self.HELP = self.tr('Help')
        self.OK = self.tr('OK')
        self.DEFAULTPROVIDER = 'GTiff'
        self.DEFAULTEXTENSION = '.tif'
        self.EXTRAEXTENSION = ' *.tiff'
        super(ThinGreyscaleDialog, 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)

        self.showInfo("Connecting UI components")
        okButton = self.button_box.button(QDialogButtonBox.Ok)
        okButton.setText(self.OK)
        cancelButton = self.button_box.button(QDialogButtonBox.Cancel)
        cancelButton.setText(self.CANCEL)
        cancelButton.setEnabled(False)
        closeButton = self.button_box.button(QDialogButtonBox.Close)
        closeButton.setText(self.CLOSE)
        browseButton = self.browseButton
        browseButton.setText(self.BROWSE)
        self.calcHistPushButton.setEnabled(False)
        self.listModel = QStandardItemModel(self.levelsListView)
        self.levelsListView.setModel(self.listModel)
        self.levelsListView.sizeHintForColumn(20)
        #self.levelValuesCheckBox.setEnabled(False)
        # Help button
        helpButton = self.helpButton
        helpButton.setText(self.HELP)

        # Connect signals
        self.showInfo("Connecting signals")
        okButton.clicked.connect(self.startWorker)
        cancelButton.clicked.connect(self.killWorker)
        closeButton.clicked.connect(self.reject)
        helpButton.clicked.connect(self.help)
        browseButton.clicked.connect(self.browse)

        inpIndexCh = self.inputRaster.currentIndexChanged['QString']
        inpIndexCh.connect(self.layerchanged)
        bandCh = self.bandComboBox.currentIndexChanged['QString']
        bandCh.connect(self.bandChanged)
        #self.iface.legendInterface().itemAdded.connect(
        #    self.layerlistchanged)
        #self.iface.legendInterface().itemRemoved.connect(
        #    self.layerlistchanged)
        #QObject.disconnect(self.button_box, SIGNAL("rejected()"), self.reject)
        self.button_box.rejected.disconnect(self.reject)
        calchistPr = self.calcHistPushButton.clicked
        calchistPr.connect(self.calculateHistogram)
        sugglevPr = self.suggestlevelsPushButton.clicked
        sugglevPr.connect(self.suggestLevels)
        addlevPr = self.addlevelPushButton.clicked
        addlevPr.connect(self.addLevel)
        dellevPr = self.deletelevelsPushButton.clicked
        dellevPr.connect(self.removeLevel)

        maxvalCh = self.maxValueSpinBox.valueChanged
        maxvalCh.connect(self.minmaxvalueChanged)
        maxvalFi = self.maxValueSpinBox.editingFinished
        maxvalFi.connect(self.minmaxvalueEdFinished)
        minvalCh = self.minValueSpinBox.valueChanged
        minvalCh.connect(self.minmaxvalueChanged)
        minvalFi = self.minValueSpinBox.editingFinished
        minvalFi.connect(self.minmaxvalueEdFinished)

        # Set instance variables
        #self.mem_layer = None
        self.worker = None
        self.inputlayerid = None
        self.inputlayer = None
        self.layerlistchanging = False
        self.minvalue = 1
        self.inputrasterprovider = None
        self.histobins = 50
        self.setupScene = QGraphicsScene(self)
        self.histoGraphicsView.setScene(self.setupScene)
        # Is the layer band of an integer type
        self.intband = False
        self.histogramAvailable = False
        self.histo = None
        self.histopadding = 1
class ThinGreyscaleDialog(QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        self.iface = iface
        self.plugin_dir = dirname(__file__)
        self.THINGREYSCALE = self.tr('ThinGreyscale')
        self.BROWSE = self.tr('Browse')
        self.CANCEL = self.tr('Cancel')
        self.CLOSE = self.tr('Close')
        self.HELP = self.tr('Help')
        self.OK = self.tr('OK')
        self.DEFAULTPROVIDER = 'GTiff'
        self.DEFAULTEXTENSION = '.tif'
        self.EXTRAEXTENSION = ' *.tiff'
        super(ThinGreyscaleDialog, 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)

        self.showInfo("Connecting UI components")
        okButton = self.button_box.button(QDialogButtonBox.Ok)
        okButton.setText(self.OK)
        cancelButton = self.button_box.button(QDialogButtonBox.Cancel)
        cancelButton.setText(self.CANCEL)
        cancelButton.setEnabled(False)
        closeButton = self.button_box.button(QDialogButtonBox.Close)
        closeButton.setText(self.CLOSE)
        browseButton = self.browseButton
        browseButton.setText(self.BROWSE)
        self.calcHistPushButton.setEnabled(False)
        self.listModel = QStandardItemModel(self.levelsListView)
        self.levelsListView.setModel(self.listModel)
        self.levelsListView.sizeHintForColumn(20)
        #self.levelValuesCheckBox.setEnabled(False)
        # Help button
        helpButton = self.helpButton
        helpButton.setText(self.HELP)

        # Connect signals
        self.showInfo("Connecting signals")
        okButton.clicked.connect(self.startWorker)
        cancelButton.clicked.connect(self.killWorker)
        closeButton.clicked.connect(self.reject)
        helpButton.clicked.connect(self.help)
        browseButton.clicked.connect(self.browse)

        inpIndexCh = self.inputRaster.currentIndexChanged['QString']
        inpIndexCh.connect(self.layerchanged)
        bandCh = self.bandComboBox.currentIndexChanged['QString']
        bandCh.connect(self.bandChanged)
        #self.iface.legendInterface().itemAdded.connect(
        #    self.layerlistchanged)
        #self.iface.legendInterface().itemRemoved.connect(
        #    self.layerlistchanged)
        #QObject.disconnect(self.button_box, SIGNAL("rejected()"), self.reject)
        self.button_box.rejected.disconnect(self.reject)
        calchistPr = self.calcHistPushButton.clicked
        calchistPr.connect(self.calculateHistogram)
        sugglevPr = self.suggestlevelsPushButton.clicked
        sugglevPr.connect(self.suggestLevels)
        addlevPr = self.addlevelPushButton.clicked
        addlevPr.connect(self.addLevel)
        dellevPr = self.deletelevelsPushButton.clicked
        dellevPr.connect(self.removeLevel)

        maxvalCh = self.maxValueSpinBox.valueChanged
        maxvalCh.connect(self.minmaxvalueChanged)
        maxvalFi = self.maxValueSpinBox.editingFinished
        maxvalFi.connect(self.minmaxvalueEdFinished)
        minvalCh = self.minValueSpinBox.valueChanged
        minvalCh.connect(self.minmaxvalueChanged)
        minvalFi = self.minValueSpinBox.editingFinished
        minvalFi.connect(self.minmaxvalueEdFinished)

        # Set instance variables
        #self.mem_layer = None
        self.worker = None
        self.inputlayerid = None
        self.inputlayer = None
        self.layerlistchanging = False
        self.minvalue = 1
        self.inputrasterprovider = None
        self.histobins = 50
        self.setupScene = QGraphicsScene(self)
        self.histoGraphicsView.setScene(self.setupScene)
        # Is the layer band of an integer type
        self.intband = False
        self.histogramAvailable = False
        self.histo = None
        self.histopadding = 1

    def startWorker(self):
        """Initialises and starts the worker thread."""
        try:
            layerindex = self.inputRaster.currentIndex()
            layerId = self.inputRaster.itemData(layerindex)
            inputlayer = QgsProject.instance().mapLayer(layerId)
            #inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
            if inputlayer is None:
                self.showError(self.tr('No input layer defined'))
                return
            # create a reference to the layer that is being processed
            # (for use when creating the resulting raster layer)
            self.thinninglayer = inputlayer
            self.levels = []
            #self.levelsListView.selectAll()
            #selected = self.levelsListView.selectedIndexes()
            if self.levelsListView.model().rowCount() == 0:
                self.showInfo("Levels must be specified!")
                return
            for i in range(self.levelsListView.model().rowCount()):
                levelstring = self.levelsListView.model().item(i).text()
            #for i in selected:
            #    levelstring = self.levelsListView.model().itemData(i)[0]
                if self.intband:
                    self.levels.append(int(levelstring))
                else:
                    self.levels.append(float(levelstring))
            #self.levelsListView.clearSelection()
            # create a new worker instance
            worker = Worker(inputlayer, self.levels, self.intband)
            # configure the QgsMessageBar
            msgBar = self.iface.messageBar().createMessage(
                                        self.tr('Skeletonising'), '')
            self.aprogressBar = QProgressBar()
            self.aprogressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
            acancelButton = QPushButton()
            acancelButton.setText(self.CANCEL)
            acancelButton.clicked.connect(self.killWorker)
            msgBar.layout().addWidget(self.aprogressBar)
            msgBar.layout().addWidget(acancelButton)
            # Has to be popped after the thread has finished (in
            # workerFinished).
            self.iface.messageBar().pushWidget(msgBar,
                                        Qgis.Info)
            self.messageBar = msgBar
            # start the worker in a new thread
            thread = QThread(self)
            worker.moveToThread(thread)
            worker.finished.connect(self.workerFinished)
            worker.error.connect(self.workerError)
            worker.status.connect(self.workerInfo)
            worker.progress.connect(self.progressBar.setValue)
            worker.progress.connect(self.aprogressBar.setValue)
            worker.iterprogress.connect(self.iterProgressBar.setValue)
            thread.started.connect(worker.run)
            thread.start()
            self.thread = thread
            self.worker = worker
            self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
            self.button_box.button(QDialogButtonBox.Close).setEnabled(False)
            self.button_box.button(QDialogButtonBox.Cancel).setEnabled(True)
        except:
            import traceback
            self.showError(traceback.format_exc())
        else:
            pass

    def workerFinished(self, ok, ret):
        """Handles the output from the worker and cleans up after the
           worker has finished."""
        # clean up the worker and thread
        self.showInfo("Handling the result")
        self.worker.deleteLater()
        self.thread.quit()
        self.thread.wait()
        self.thread.deleteLater()
        # remove widget from message bar (pop)
        self.iface.messageBar().popWidget(self.messageBar)
        if ok and ret is not None:
            #self.showInfo("Ret: "+str(ret[10,]))
            # Transformation:
            self.minx = self.thinninglayer.extent().xMinimum()
            self.maxx = self.thinninglayer.extent().xMaximum()
            self.miny = self.thinninglayer.extent().yMinimum()
            self.maxy = self.thinninglayer.extent().yMaximum()
            self.rows = self.thinninglayer.height()
            self.cols = self.thinninglayer.width()
            self.xres = (self.maxx - self.minx) / float(self.cols)
            self.yres = (self.maxy - self.miny) / float(self.rows)
            geotransform = (self.minx, self.xres, 0, self.maxy, 0, -self.yres)
            try:
                format = self.DEFAULTPROVIDER
                driver = gdal.GetDriverByName(format)
                NOVALUE = 0
                metadata = driver.GetMetadata()
                fileName = self.outputRaster.text()
                if self.outputRaster.text() == "":
                    self.showInfo("No output file specified, " +
                                         "creating a temporary file")
                    # Get a temporary file
                    fileName = mktemp(prefix='greyskel',
                           suffix=self.DEFAULTEXTENSION)
                fileInfo = QFileInfo(fileName)
                filepath = fileInfo.absolutePath()
                baseName = fileInfo.baseName()
                suffix = fileInfo.suffix()
                thisfilename = filepath + baseName + '.' + suffix
                thisfilename = fileName
                self.showInfo("File name: " + thisfilename)
                gdaldatatype = gdal.GDT_Byte
                skelmatrix = None
                if self.levelValuesCheckBox.isChecked():
                    # Transform the pixel values back to the original
                    # level values
                    my_dict = {}
                    # Add zero to handle the "empty" pixels
                    my_dict[0] = 0
                    for i in range(len(self.levels)):
                        my_dict[i + 1] = self.levels[i]
                    skelmatrix = np.vectorize(my_dict.__getitem__,
                                              otypes=[np.float])(ret)
                    gdaldatatype = gdal.GDT_Int32
                    if not self.intband:
                        gdaldatatype = gdal.GDT_Float32
                else:
                    skelmatrix = ret
                outDataset = driver.Create(thisfilename, self.cols,
                                           self.rows, 1, gdaldatatype)
                if self.thinninglayer.dataProvider().crs() is not None:
                    srs = self.thinninglayer.dataProvider().crs()
                    outDataset.SetProjection(srs.toWkt().encode('ascii',
                                                               'ignore'))
                skeletonband = outDataset.GetRasterBand(1)
                skeletonband.WriteArray(skelmatrix)
                skeletonband.SetNoDataValue(NOVALUE)
                #stats = skeletonband.GetStatistics(False, True)
                #skeletonband.SetStatistics(stats[0], stats[1],
                #                                 stats[2], stats[3])
                outDataset.SetGeoTransform(geotransform)
                outDataset = None  # To close the file
                # report the result
                rlayer = QgsRasterLayer(thisfilename, baseName)
                self.layerlistchanging = True
                #QgsMapLayerRegistry.instance().addMapLayer(rlayer)
                QgsProject.instance().addMapLayer(rlayer)
                self.layerlistchanging = False
            except:
                import traceback
                self.showError("Can't write the skeleton file:  %s" %
                                   self.outputRaster.text() + ' - ' +
                                   traceback.format_exc())
                okb = self.button_box.button(QDialogButtonBox.Ok)
                okb.setEnabled(True)
                closb = self.button_box.button(QDialogButtonBox.Close)
                closb.setEnabled(True)
                cancb = self.button_box.button(QDialogButtonBox.Cancel)
                cancb.setEnabled(False)
                return
            QgsMessageLog.logMessage(self.tr('ThinGreyscale finished'),
                                self.THINGREYSCALE, Qgis.Info)
        else:
            # notify the user that something went wrong
            if not ok:
                self.showError(self.tr('Aborted') + '!')
            else:
                self.showError(self.tr('No skeleton created') + '!')
        self.progressBar.setValue(0.0)
        #self.aprogressBar.setValue(0.0)
        self.iterProgressBar.setValue(0.0)
        self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
        self.button_box.button(QDialogButtonBox.Close).setEnabled(True)
        self.button_box.button(QDialogButtonBox.Cancel).setEnabled(False)

    def workerError(self, exception_string):
        """Report an error from the worker."""
        #QgsMessageLog.logMessage(self.tr('Worker failed - exception') +
        #                         ': ' + str(exception_string),
        #                         self.THINGREYSCALE,
        #                         QgsMessageLog.CRITICAL)
        self.showError(exception_string)

    def workerInfo(self, message_string):
        """Report an info message from the worker."""
        QgsMessageLog.logMessage(self.tr('Worker') + ': ' + message_string,
                                 self.THINGREYSCALE, Qgis.Info)

    def layerchanged(self, number=0):
        """Do the necessary updates after a layer selection has
           been changed."""
        self.showInfo("Layer changed")
        # If the layer list is being updated, don't do anything
        if self.layerlistchanging:
            return
        layerindex = self.inputRaster.currentIndex()
        layerId = self.inputRaster.itemData(layerindex)
        self.inputlayerid = layerId
        #self.inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
        self.inputlayer = QgsProject.instance().mapLayer(layerId)
        if self.inputlayer is not None:
            self.inputrasterprovider = self.inputlayer.dataProvider()
            self.bandComboBox.clear()
            bandcount = self.inputlayer.bandCount()
            #self.showInfo("Layer bandcount: "+str(bandcount))
            for i in range(bandcount):
                self.bandComboBox.addItem(self.inputlayer.bandName(i + 1), i)
                #self.showInfo("Band " + str(i) + ": " +
                #                self.inputlayer.bandName(i+1))
            # Check if the driver supports Create() or CreateCopy()
            #gdalmetadata = self.inputlayer.metadata()
            #self.showInfo("Layer metadata: " +
            #                str(gdalmetadata.encode('utf-8')))
            #provstring = '<p>GDAL provider</p>\n'
            #providerpos = gdalmetadata.find(provstring)
            #brpos = gdalmetadata.find('<br>', providerpos + len(provstring))
            #self.gdalprovider = gdalmetadata[int(providerpos +
            #                             len(provstring)):int(brpos)]
            #self.showInfo('GDAL provider: '+self.gdalprovider)
            #drivername = self.gdalprovider.encode('ascii', 'ignore')
            #theDriver = gdal.GetDriverByName(drivername)
            #if theDriver is None:
            #    self.showInfo("Unable to get the raster driver")
            #else:
            #data    theMetadata = theDriver.GetMetadata()
                #self.showInfo("Driver metadata: "+str(theMetadata))
                #if ((gdal.DCAP_CREATE in theMetadata) and
                #        theMetadata[gdal.DCAP_CREATE] == 'YES'):
                #    self.canCreate = True
                #if (theMetadata.has_key(gdal.DCAP_CREATECOPY) and
                #if ((gdal.DCAP_CREATECOPY in theMetadata) and
                #        theMetadata[gdal.DCAP_CREATECOPY] == 'YES'):
                #    self.canCreateCopy = True
                #self.showInfo('raster provider type: ' +
                #                str(self.inputlayer.providerType()))
                # Determine the file suffix
                #self.gdalext = ""
                #if gdal.DMD_EXTENSION in theMetadata:
                #    self.gdalext = "." + theMetadata[gdal.DMD_EXTENSION]
                #else:
                #    self.showInfo("No extension available in GDAL metadata")
                # by parsing the layer metadata looking for
                #           "Dataset Description"
                #descstring = 'Dataset Description</p>\n<p>'
                #descpos = gdalmetadata.find(descstring)
                #ppos = gdalmetadata.find('</p>',descpos+len(descstring))
                #filename = gdalmetadata[descpos+len(descstring):ppos]
                #self.gdalext = splitext(filename)[1]
                #self.showInfo('GDAL extension: '+self.gdalext)
                # Determine the datatype
                #datatypestring = 'Data Type</p>\n<p>'
                #datatypepos = gdalmetadata.find(datatypestring)
                #ppos = gdalmetadata.find('</p>',
                #                   datatypepos + len(datatypestring))
                #datatypedesc = gdalmetadata[datatypepos +
                #                            len(datatypestring):ppos]
                #shortdesc = datatypedesc.split()[0]
                #self.showInfo('GDAL data type: GDT_'+shortdesc)
                # Call the findGdalDatatype function
                #self.findGdalDatatype(shortdesc)
            #   self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
            self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
            self.calcHistPushButton.setEnabled(True)
            self.suggestlevelsPushButton.setEnabled(True)

    def bandChanged(self):
        band = self.bandComboBox.currentIndex() + 1
        self.showInfo("Band changed: " + str(band))
        statistics = self.inputrasterprovider.bandStatistics(band)
        #self.showInfo("Band statistics: " + str(statistics.minimumValue) +
        #                            " - " + str(statistics.maximumValue) +
        #                            " - " + str(statistics.mean))
        self.bandmin = statistics.minimumValue
        self.bandmax = statistics.maximumValue
        dt = self.inputrasterprovider.dataType(band)
        # Integer data type
        if (dt == Qgis.Byte or dt == Qgis.UInt16 or dt == Qgis.Int16
                            or dt == Qgis.UInt32 or dt == Qgis.Int32):
            self.intband = True
            self.minValueSpinBox.setDecimals(0)
            self.maxValueSpinBox.setDecimals(0)
            self.levelSpinBox.setDecimals(0)
            self.bandMinLabel.setText(str(int(statistics.minimumValue)))
            self.bandMaxLabel.setText(str(int(statistics.maximumValue)))
        else:
            self.intband = False
            self.minValueSpinBox.setDecimals(5)
            self.maxValueSpinBox.setDecimals(5)
            self.levelSpinBox.setDecimals(5)
            minlabtext = "{0:.5f}".format(statistics.minimumValue)
            self.bandMinLabel.setText(minlabtext)
            maxlabtext = "{0:.5f}".format(statistics.maximumValue)
            self.bandMaxLabel.setText(maxlabtext)
        #self.minValueSpinBox.setMinimum(statistics.minimumValue)
        self.maxValueSpinBox.setMinimum(statistics.minimumValue)
        #self.minValueSpinBox.setMaximum(statistics.maximumValue)
        self.maxValueSpinBox.setMaximum(statistics.maximumValue)
        #self.minValueSpinBox.setValue(statistics.minimumValue)
        if not (statistics.statsGathered & statistics.Mean):
            bandmean = (statistics.minimumValue + statistics.maximumValue) / 2
        else:
            #self.showInfo("statsgathered: " + str(statistics.statsGathered))
            bandmean = statistics.mean
        if self.intband:
            self.minValueSpinBox.setValue(int(ceil(bandmean)))
        else:
            self.minValueSpinBox.setValue(bandmean)
        self.maxValueSpinBox.setValue(statistics.maximumValue)
        self.histMinValue.setText(str(statistics.minimumValue))
        self.histMaxValue.setText(str(statistics.maximumValue))
        self.levelSpinBox.setMinimum(statistics.minimumValue)
        self.levelSpinBox.setMaximum(statistics.maximumValue)
        self.histogramAvailable = False
        #if self.inputrasterprovider.hasStatistics(band):
        #if statistics.statsGathered:
            #histogram = statistics.histogramVector
            #self.showInfo("Histogram: " + str(histogram))
            #range = min to max
            #np.histogram(band, 50, range)

    def minmaxvalueChanged(self):
        #if self.minValueSpinBox is None:
        #    return
        minvalue = self.minValueSpinBox.value()
        #if minvalue is None:
        #    return
        #if self.maxValueSpinBox is None:
        #    return
        maxvalue = self.maxValueSpinBox.value()
        #if maxvalue is None:
        #   return
        if isnan(maxvalue) or isnan(minvalue):
            return
        self.showInfo("minvalue: " + str(minvalue) + " Maxvalue: " +
                                                       str(maxvalue))
        #if self.intband:
        #    minvalue = int(minvalue)
        #    maxvalue = int(maxvalue)
        if abs(maxvalue - minvalue) < 0.00001:
        #if maxvalue == maxvalue:
            self.calcHistPushButton.setEnabled(False)
        else:
            self.calcHistPushButton.setEnabled(True)
        # Update the min and max value spinboxes
        self.minValueSpinBox.setMaximum(maxvalue)
        self.maxValueSpinBox.setMinimum(minvalue)
        self.minValueSpinBox.setMinimum(self.bandmin)

    def minmaxvalueEdFinished(self):
        minvalue = self.minValueSpinBox.value()
        maxvalue = self.maxValueSpinBox.value()
        if self.intband:
            minvalue = int(minvalue)
            maxvalue = int(maxvalue)
        self.showInfo("minvalue: " + str(minvalue) + " Maxvalue: " +
                                    str(maxvalue))
        # Update the spin box for adding levels
        self.levelSpinBox.setMinimum(minvalue)
        self.levelSpinBox.setMaximum(maxvalue)
        if self.levelSpinBox.value() < minvalue:
            self.levelSpinBox.setValue(minvalue)
        if self.levelSpinBox.value() > maxvalue:
            self.levelSpinBox.setValue(maxvalue)
        # Update the min and max value spinboxes
        self.minValueSpinBox.setMaximum(maxvalue)
        self.maxValueSpinBox.setMinimum(minvalue)

        # Adjust the levels:
        i = 0
        while self.levelsListView.model().item(i):
        #for i in range(self.levelsListView.model().rowCount()):
            #self.showInfo("Element: " +
            #       str(self.levelsListView.model().item(i).text()))
            #continue
            value = float(self.levelsListView.model().item(i).text())
            if value < minvalue:
                if i == 0:
                    self.levelsListView.model().item(i).setText(str(minvalue))
                    i = i + 1
                else:
                    self.levelsListView.model().removeRow(i)
            elif value > maxvalue:
                if i == self.levelsListView.model().rowCount() - 1:
                    self.levelsListView.model().item(i).setText(str(maxvalue))
                    i = i + 1
                else:
                    self.levelsListView.model().removeRow(i)
            else:
                i = i + 1
        self.drawHistogram()

    def calculateHistogram(self):
        self.showInfo("Calculating histogram...")
        if self.inputlayer is None:
            return
        
        self.showInfo("Calculating histogram...")
        # Check if there is only one value
        myrange = (self.minValueSpinBox.value(),
                   self.maxValueSpinBox.value())
        self.inputextent = self.inputlayer.extent()
        self.inputrdp = self.inputlayer.dataProvider()
        width = self.inputlayer.width()
        height = self.inputlayer.height()
        if width == 0 or height == 0:
            self.showInfo("Image has zero width or height")
            return
        extwidth = self.inputextent.width()
        extheight = self.inputextent.height()
        # Read the raster block and get the maximum value
        rasterblock = self.inputrdp.block(1, self.inputextent,
                                          width, height)
        # Create a numpy array version of the image
        imageMat = np.zeros((height, width), dtype=np.float16)
        # This one takes a lot of time!
        for row in range(height):
            for column in range(width):
                imageMat[row, column] = rasterblock.value(row, column)
                self.showInfo("Image: " + str(height) + ", " + str(width) + " - " + str(imageMat[row, column]))
        self.histo = np.histogram(imageMat, self.histobins, myrange)
        #relevantpixels = imageMat[np.where(imageMat >= bandval)]
        minlevel = float(self.bandMinLabel.text())
        relevantpixels = imageMat[np.where(imageMat >= minlevel)]
        #self.showInfo("Histogram: " + str(self.histo))
        nanpercentage = 100.0 - 100.0 * len(relevantpixels) / (width * height)
        self.bandNANLabel.setText("{0:.1f}".format(nanpercentage))
        #self.showInfo("Percentage NAN: " + str(100.0 - 100.0 *
        #                    len(relevantpixels) / (width * height)))
        #self.showInfo("First element: " + str(self.histo[0]))
        #self.showInfo("First element, first: " + str(self.histo[0][0]))
        #self.showInfo("First element, second: " + str(self.histo[0][1]))
        self.histMinValue.setText(str(self.minValueSpinBox.value()))
        self.histMaxValue.setText(str(self.maxValueSpinBox.value()))
        if self.intband:
            self.histMinValue.setText(str(int(self.minValueSpinBox.value())))
            self.histMaxValue.setText(str(int(self.maxValueSpinBox.value())))
        self.histogramAvailable = True
        self.drawHistogram()

    def drawHistogram(self):
        #if self.inputlayer is None:
        #    return
        self.showInfo("Drawing histogram...")
        viewprect = QRectF(self.histoGraphicsView.viewport().rect())
        self.histoGraphicsView.setSceneRect(viewprect)
        self.setupScene.clear()
        self.setupScene.update()
        histbottom = self.histoGraphicsView.sceneRect().bottom()
        histtop = self.histoGraphicsView.sceneRect().top()
        left = self.histoGraphicsView.sceneRect().left() + self.histopadding
        right = self.histoGraphicsView.sceneRect().right() - self.histopadding
        histheight = histbottom - histtop
        histwidth = right - left
        step = 1.0 * histwidth / self.histobins
        maxlength = histheight
        padding = 1
        ll = QPoint(self.histopadding - 1, histheight - padding)
        start = QPointF(self.histoGraphicsView.mapToScene(ll))

        # Check if there is only one value
        #myrange = (self.minValueSpinBox.value(),self.maxValueSpinBox.value())
        if self.histogramAvailable:
            maxvalue = 0.0
            for i in range(len(self.histo[0])):
                if self.histo[0][i] > maxvalue:
                    maxvalue = self.histo[0][i]
            if maxvalue == 0:
                return
            self.maxBinNumber.setText(str(maxvalue))
            # Create the histogram:
            #self.showInfo("maxvalue: " + str(maxvalue))
            #self.showInfo("maxlength: " + str(maxlength))
            #self.showInfo("step: " + str(step))
            for i in range(self.histobins):
                binnumber = self.histo[0][i]
                if binnumber == 0:
                    continue
                height = (1.0 * self.histo[0][i] / maxvalue *
                                          (maxlength - padding))
                rectangle = QGraphicsRectItem(start.x() + step * i,
                                          start.y(),
                                          step,
                                          -height)
                rectangle.setPen(QPen(QColor(102, 102, 102)))
                rectangle.setBrush(QBrush(QColor(240, 240, 240)))
                self.setupScene.addItem(rectangle)
                #self.showInfo(str(i) + ": " + str(height))
            #if self.levelsListView.model().rowCount() > 0:
        # Add lines for the levels
        minvalue = float(self.histMinValue.text())
        maxvalue = float(self.histMaxValue.text())
        datarange = maxvalue - minvalue
        if datarange == 0:
            return
        i = 0
        while self.levelsListView.model().item(i):
            #self.showInfo("Element: " +
            #       str(self.levelsListView.model().item(i).text()))
            #continue
            value = float(self.levelsListView.model().item(i).text())
            xvalue = start.x() + histwidth * (value - minvalue) / datarange
            line = QGraphicsLineItem(xvalue, 0, xvalue, histheight)
            if i == 0 or i == (self.levelsListView.model().rowCount() - 1):
                line.setPen(QPen(QColor(204, 0, 0)))
            else:
                line.setPen(QPen(QColor(0, 204, 0)))
            self.setupScene.addItem(line)
            i = i + 1

    def suggestLevels(self):
        self.listModel.clear()
        self.showInfo("Suggesting levels")
        levels = self.levelsSpinBox.value()
        startvalue = self.minValueSpinBox.value()
        endvalue = self.maxValueSpinBox.value()
        increment = (endvalue - startvalue) / levels
        for i in range(levels + 1):
            value = startvalue + increment * i
            if self.intband:
                value = int(value)
            item = QStandardItem(str(value))
            self.listModel.appendRow(item)
        self.drawHistogram()

    def addLevel(self):
        newvalue = self.levelSpinBox.value()
        if self.intband:
            newvalue = int(newvalue)
        for i in range(self.listModel.rowCount()):
            # Check if the value is already in the list
            if self.listModel.item(i).text() == str(newvalue):
                return
            else:
                # Maintain a sorted list of distances
                if (float(self.listModel.item(i).text()) >
                                 float(str(newvalue))):
                    item = QStandardItem(str(newvalue))
                    self.listModel.insertRow(i, item)
                    self.drawHistogram()
                    return
        item = QStandardItem(str(newvalue))
        self.listModel.appendRow(item)
        #if self.histogramAvailable:
        #    addLevelsToHistogram()
        self.drawHistogram()

    def removeLevel(self):
        self.levelsListView.setUpdatesEnabled(False)
        indexes = self.levelsListView.selectedIndexes()
        indexes.sort()
        for i in range(len(indexes) - 1, -1, -1):
            self.listModel.removeRow(indexes[i].row())
        self.levelsListView.setUpdatesEnabled(True)
        #if self.histogramAvailable:
        #    removeLevelFromHistogram()
        self.drawHistogram()

    def layerlistchanged(self):
        self.layerlistchanging = True
        self.showInfo("Layer list changed")
        # Repopulate the input layer combo box
        # Save the currently selected input layer
        inputlayerid = self.inputlayerid
        self.inputRaster.clear()
        for alayer in self.iface.legendInterface().layers():
            if alayer.type() == QgsMapLayer.RasterLayer:
                gdalmetadata = alayer.metadata()
                # Skip WMS layers
                WMSstring = 'Web Map Service'
                wmspos = gdalmetadata.find(WMSstring)
                if wmspos != -1:
                    continue
                self.inputRaster.addItem(alayer.name(), alayer.id())
        # Set the previous selection
        for i in range(self.inputRaster.count()):
            if self.inputRaster.itemData(i) == inputlayerid:
                self.inputRaster.setCurrentIndex(i)
        self.layerlistchanging = False
        #self.updateui()

    def updateui(self):
        """Do the necessary updates after a layer selection has
           been changed."""
        #if self.layerlistchanged:
        #    return
        #self.outputRaster.setText(self.inputRaster.currentText() +
        #                           '_' + 'thinned')
        layerindex = self.inputRaster.currentIndex()
        layerId = self.inputRaster.itemData(layerindex)
        #inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
        inputlayer = QgsProject.instance().mapLayer(layerId)
        if inputlayer is not None:
            pass
        else:
            pass

    def findGdalDatatype(self, shortdesc):
            gdaldatatype = None
            # // Unknown or unspecified type
            # GDT_Unknown = GDALDataType(C.GDT_Unknown)
            if shortdesc == 'Unknown':
                gdaldatatype = gdal.GDT_Unknown
            # // Eight bit unsigned integer
            # GDT_Byte = GDALDataType(C.GDT_Byte)
            elif shortdesc == 'Byte':
                gdaldatatype = gdal.GDT_Byte
            # // Sixteen bit unsigned integer
            # GDT_UInt16 = GDALDataType(C.GDT_UInt16)
            elif shortdesc == 'UInt16':
                gdaldatatype = gdal.GDT_UInt16
            # // Sixteen bit signed integer
            # GDT_Int16 = GDALDataType(C.GDT_Int16)
            elif shortdesc == 'Int16':
                gdaldatatype = gdal.GDT_Int16
            # // Thirty two bit unsigned integer
            # GDT_UInt32 = GDALDataType(C.GDT_UInt32)
            elif shortdesc == 'UInt32':
                gdaldatatype = gdal.GDT_UInt32
            # // Thirty two bit signed integer
            # GDT_Int32 = GDALDataType(C.GDT_Int32)
            elif shortdesc == 'Int32':
                gdaldatatype = gdal.GDT_Int32
            # // Thirty two bit floating point
            # GDT_Float32 = GDALDataType(C.GDT_Float32)
            elif shortdesc == 'Float32':
                gdaldatatype = gdal.GDT_Float32
            # // Sixty four bit floating point
            # GDT_Float64 = GDALDataType(C.GDT_Float64)
            elif shortdesc == 'Float64':
                gdaldatatype = gdal.GDT_Float64
            # // Complex Int16
            # GDT_CInt16 = GDALDataType(C.GDT_CInt16)
            elif shortdesc == 'CInt16':
                gdaldatatype = gdal.CInt16
            # // Complex Int32
            # GDT_CInt32 = GDALDataType(C.GDT_CInt32)
            elif shortdesc == 'CInt32':
                gdaldatatype = gdal.CInt32
            # // Complex Float32
            # GDT_CFloat32 = GDALDataType(C.GDT_CFloat32)
            elif shortdesc == 'CFloat32':
                gdaldatatype = gdal.CFloat32
            # // Complex Float64
            # GDT_CFloat64 = GDALDataType(C.GDT_CFloat64)
            elif shortdesc == 'CFloat64':
                gdaldatatype = gdal.CFloat64
            # // maximum type # + 1
            # GDT_TypeCount = GDALDataType(C.GDT_TypeCount)
            elif shortdesc == 'TypeCount':
                gdaldatatype = gdal.TypeCount
            self.gdaldatatype = gdaldatatype

    def killWorker(self):
        """Kill the worker thread."""
        if self.worker is not None:
            QgsMessageLog.logMessage(self.tr('Killing worker'),
                                     self.THINGREYSCALE, Qgis.Info)
            self.worker.kill()

    def showError(self, text):
        """Show an error."""
        self.iface.messageBar().pushMessage(self.tr('Error'), text,
                                            level=QgsMessageBar.CRITICAL,
                                            duration=3)
        QgsMessageLog.logMessage('Error: ' + text, self.THINGREYSCALE,
                                 QgsMessageLog.CRITICAL)

    def showWarning(self, text):
        """Show a warning."""
        self.iface.messageBar().pushMessage(self.tr('Warning'), text,
                                            level=QgsMessageBar.WARNING,
                                            duration=2)
        QgsMessageLog.logMessage('Warning: ' + text, self.THINGREYSCALE,
                                 QgsMessageLog.WARNING)

    def showInfo(self, text):
        """Show info."""
        self.iface.messageBar().pushMessage(self.tr('Info'), text,
                                            level=Qgis.Info,
                                            duration=2)
        QgsMessageLog.logMessage('Info: ' + text, self.THINGREYSCALE,
                                 Qgis.Info)

    # def help(self):
        # #QDesktopServices.openUrl(QUrl.fromLocalFile(self.plugin_dir +
        #                                 "/help/build/html/index.html"))
        # QDesktopServices.openUrl(QUrl.fromLocalFile(self.plugin_dir +
        #                                            "/help/index.html"))
        # #showPluginHelp()

    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        return QCoreApplication.translate('ThinGreyScaleDialog', message)

    def browse(self):
        settings = QSettings()
        key = '/UI/lastShapefileDir'
        outDir = settings.value(key)
        home = outDir
        #outDir = expanduser("~")
        #filter = (self.DEFAULTPROVIDER + " (*" +
        #             self.DEFAULTEXTENSION + ");;All files (*)")
        filter = (self.DEFAULTPROVIDER + " (*" +
                     self.DEFAULTEXTENSION + self.EXTRAEXTENSION + ")")
        #if (self.gdalprovider != self.DEFAULTPROVIDER and
        #                                     (self.canCreateCopy or
        #                                           self.canCreate)):
        #    filter = (self.gdalprovider + " (*" + self.gdalext +
        #                                          ");;" + filter)
        outFilePath = QFileDialog.getSaveFileName(self,
                                   'Specify file name for skeleton',
                                                     outDir, filter)
        outFilePath = unicode(outFilePath)
        if outFilePath:
            root, ext = splitext(outFilePath)
            if ext.lower() != '.tif' and ext.lower() != '.tiff':
                outFilePath = '%s.tif' % outFilePath
            outDir = dirname(outFilePath)
            settings.setValue(key, outDir)
        #        (self.canCreateCopy or self.canCreate):
        #    fileName = splitext(str(fileName))[0]+self.gdalext
        self.outputRaster.setText(outFilePath)

    # Overriding
    def resizeEvent(self, event):
        #self.showInfo("resizeEvent")
        self.calculateHistogram()

    def help(self):
        #QDesktopServices.openUrl(QUrl.fromLocalFile(
        #                 self.plugin_dir + "/help/html/index.html"))
        showPluginHelp(None, "help/html/index")

    # Implement the accept method to avoid exiting the dialog when
    # starting the work
    def accept(self):
        """Accept override."""
        pass

    # Implement the reject method to have the possibility to avoid
    # exiting the dialog when cancelling
    def reject(self):
        """Reject override."""
        # exit the dialog
        QDialog.reject(self)
Ejemplo n.º 21
0
class StripChart:
    """QGIS Plugin Implementation."""
    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface

        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   'StripChart_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'Spectral data')
        self.toolbar = self.iface.addToolBar(u'Stripchart')
        self.toolbar.setObjectName(u'Stripchart')

        #QgsMessageLog.logMessage(message, tag, level)("** INITIALIZING StripChart")
        self.view = MouseReadGraphicsView(self.iface)
        self.view.layer = None
        self.pluginIsActive = False
        self.view.parent = self
        # self.dockwidget = None

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('Stripchart', message)

    def add_action(self,
                   icon_path,
                   text,
                   callback,
                   enabled_flag=True,
                   add_to_menu=True,
                   add_to_toolbar=True,
                   status_tip=None,
                   whats_this=None,
                   parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToVectorMenu(self.menu, action)

        self.actions.append(action)

        return action

    def selectedlayer(self):
        if self.dlg.qgLayer.currentLayer() == None:
            return
        self.dlg.qgField.setLayer(self.dlg.qgLayer.currentLayer())
        self.dlg.qgField.setField(None)
        self.clearscene()

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/stripchart/icon.png'
        self.add_action(icon_path,
                        text=self.tr(u'Stripchart'),
                        callback=self.run,
                        parent=self.iface.mainWindow())
        self.dlg = StripChartDockWidget(self.iface.mainWindow())
        self.view.setParent(self.dlg)
        self.dlg.vlMain.addWidget(self.view)
        self.scene = QGraphicsScene()
        self.view.setScene(self.scene)
        self.scene.setSceneRect(0, 0, 300, 2000)
        self.dlg.qgLayer.setFilters(QgsMapLayerProxyModel.VectorLayer)
        self.dlg.qgLayer.setLayer(self.iface.activeLayer())
        self.dlg.qgField.setAllowEmptyFieldName(True)
        self.dlg.qgField.setLayer(self.dlg.qgLayer.currentLayer())
        self.dlg.qgField.setFilters(QgsFieldProxyModel.Numeric)
        self.dlg.qgLayer.layerChanged.connect(self.selectedlayer)
        self.iface.mapCanvas().selectionChanged.connect(self.markselected)
        self.dlg.qgField.currentIndexChanged['QString'].connect(
            self.stripchart)

    #--------------------------------------------------------------------------

    def onClosePlugin(self):
        """Cleanup necessary items here when plugin dockwidget is closed"""

        # disconnects
        self.dlg.closingPlugin.disconnect(self.onClosePlugin)

        self.pluginIsActive = False

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""

        #print "** UNLOAD StripChart"

        for action in self.actions:
            self.iface.removePluginVectorMenu(self.tr(u'Spectral data'),
                                              action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        del self.toolbar

    #--------------------------------------------------------------------------

    def clearscene(self):
        self.scene.clear()
        self.view.selectlines = []
        self.scene.values = []
        self.view.ids = []  # Keeps the ids .

    def stripchart(self):
        """
        Draws a stripchart based on a dataset
        """
        self.view.layer = self.dlg.qgLayer.currentLayer()
        if self.view.layer == None or self.dlg.isHidden():
            return
        if self.view.layer.featureCount() == 0:
            self.iface.messageBar().pushMessage(
                "Stripchart",
                "No data in table, cannot draw stripchart",
                level=Qgis.Critical,
                duration=3)  # Info, Warning, Critical, Success
            return
        QgsMessageLog.logMessage("Stripchart starting", "Messages", 0)
        self.clearscene()
        idfields = self.view.layer.dataProvider().pkAttributeIndexes(
        )  # These are the fields that build up the primary key
        if len(idfields) == 0:
            try:
                self.view.idfield = self.view.layer.fields()[0].name()
                self.iface.messageBar().pushMessage(
                    "Warning",
                    "No primary key for {}, sorting on {}, - selection may not be possible"
                    .format(self.view.layer.name(), self.view.idfield),
                    level=Qgis.Warning)  # Info, Warning, Critical, Success
            except IndexError as e:
                # Probably undefined layer, just return
                # This happens some times when exiting QGIS
                QgsMessageLog.logMessage(
                    "Could not draw stripchart - IndexError", "Messages",
                    Qgis.Warning)
                return
        else:
            #idfield=idfields[0]
            self.view.idfield = self.view.layer.fields()[idfields[0]].name()
            self.iface.messageBar().pushMessage(
                "Info",
                "Sorting on  {}".format(self.view.idfield),
                level=Qgis.Info,
                duration=3)  # Info, Warning, Critical, Success
        fieldname = self.dlg.qgField.currentText()
        if fieldname == '' or fieldname is None:
            return
        request = QgsFeatureRequest().addOrderBy(self.view.idfield).setFlags(
            QgsFeatureRequest.NoGeometry).setSubsetOfAttributes(
                [self.view.idfield, fieldname], self.view.layer.fields())
        iter = self.view.layer.getFeatures(request)
        for feature in iter:
            if isinstance(feature[fieldname], list):
                self.iface.messageBar().pushMessage(
                    "Error",
                    "Invalid field type : {}".format(fieldname),
                    level=Qgis.Warning,
                    duration=3)  # Info, Warning, Critical, Success
                return
            self.scene.values.append(feature[fieldname])
            self.view.ids.append(feature[self.view.idfield])
            # QgsMessageLog.logMessage("Added id {}".format(feature[self.view.idfield]), "Messages", Qgis.Info)
        self.scene.setSceneRect(0, 0, self.view.width, len(self.scene.values))
        airfact = 0.02
        maxval = max(self.scene.values)
        minval = min(self.scene.values)
        print(maxval, minval)
        if maxval == None:
            # Field with only "None" values
            return
        air = (maxval - minval) * airfact
        if maxval > 0:
            maxval += air
        else:
            maxval -= air
        if minval > 0:
            minval -= air
        else:
            minval += air
        if maxval - minval == 0:
            scale = self.view.width / maxval  # Could just as well return since this will plot a straight line...
        else:
            scale = self.view.width / (maxval - minval)
        n = 0
        for v in self.scene.values:
            v -= minval
            self.scene.addLine(0, n, v * scale, n)
            n += 1
        self.markselected(
        )  # In case something is already selected when the layer is plotted

    def run(self):
        """Run method that loads and starts the plugin"""
        self.init = True
        if not self.pluginIsActive:
            self.pluginIsActive = True

            # connect to provide cleanup on closing of dockwidget
            self.dlg.closingPlugin.connect(self.onClosePlugin)

            # show the dockwidget
            self.iface.mainWindow().addDockWidget(Qt.RightDockWidgetArea,
                                                  self.dlg)
            self.dlg.show()

    def markselected(self):
        """Marks in the stripchart which elements that are selected"""
        try:
            if self.view.layer == None:
                return
            QgsMessageLog.logMessage("Going to look into selection",
                                     "Messages", Qgis.Info)
            sels = self.view.layer.selectedFeatures(
            )  # The selected features in the active (from this plugin's point of view) layer
            n = len(sels)
            QgsMessageLog.logMessage("Selected {}".format(n), "Messages",
                                     Qgis.Info)

            self.view.clearselection()
            QgsMessageLog.logMessage("Selection cleared", "Messages",
                                     Qgis.Info)

            if n > 0:
                self.view.markselection(sels)
        except:
            try:
                self.iface.messageBar().pushMessage(
                    "Stripchart",
                    "Error during selection from {}".format(
                        self.view.layer.name()),
                    level=Qgis.Warning,
                    duration=3)  # Info, Warning, Critical, Success
            except RuntimeError:
                print("Error in markselected:")
                print(e)
            except Exception as e:
                self.iface.messageBar().pushMessage(
                    "Stripchart",
                    "Error during selection ",
                    level=Qgis.Warning,
                    duration=3)  # Info, Warning, Critical, Success
                print(e)
                print(self.view.layer.name())
    def __init__(self, iface, parent=None):
        """Constructor."""
        self.iface = iface
        self.plugin_dir = dirname(__file__)
        self.THINGREYSCALE = self.tr('ThinGreyscale')
        self.BROWSE = self.tr('Browse')
        self.CANCEL = self.tr('Cancel')
        self.CLOSE = self.tr('Close')
        self.HELP = self.tr('Help')
        self.OK = self.tr('OK')
        self.DEFAULTPROVIDER = 'GTiff'
        self.DEFAULTEXTENSION = '.tif'
        self.EXTRAEXTENSION = ' *.tiff'
        super(ThinGreyscaleDialog, 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)

        self.showInfo("Connecting UI components")
        okButton = self.button_box.button(QDialogButtonBox.Ok)
        okButton.setText(self.OK)
        cancelButton = self.button_box.button(QDialogButtonBox.Cancel)
        cancelButton.setText(self.CANCEL)
        cancelButton.setEnabled(False)
        closeButton = self.button_box.button(QDialogButtonBox.Close)
        closeButton.setText(self.CLOSE)
        browseButton = self.browseButton
        browseButton.setText(self.BROWSE)
        self.calcHistPushButton.setEnabled(False)
        self.listModel = QStandardItemModel(self.levelsListView)
        self.levelsListView.setModel(self.listModel)
        self.levelsListView.sizeHintForColumn(20)
        #self.levelValuesCheckBox.setEnabled(False)
        # Help button
        helpButton = self.helpButton
        helpButton.setText(self.HELP)

        # Connect signals
        self.showInfo("Connecting signals")
        okButton.clicked.connect(self.startWorker)
        cancelButton.clicked.connect(self.killWorker)
        closeButton.clicked.connect(self.reject)
        helpButton.clicked.connect(self.help)
        browseButton.clicked.connect(self.browse)

        inpIndexCh = self.inputRaster.currentIndexChanged['QString']
        inpIndexCh.connect(self.layerchanged)
        bandCh = self.bandComboBox.currentIndexChanged['QString']
        bandCh.connect(self.bandChanged)
        #self.iface.legendInterface().itemAdded.connect(
        #    self.layerlistchanged)
        #self.iface.legendInterface().itemRemoved.connect(
        #    self.layerlistchanged)
        #QObject.disconnect(self.button_box, SIGNAL("rejected()"), self.reject)
        self.button_box.rejected.disconnect(self.reject)
        calchistPr = self.calcHistPushButton.clicked
        calchistPr.connect(self.calculateHistogram)
        sugglevPr = self.suggestlevelsPushButton.clicked
        sugglevPr.connect(self.suggestLevels)
        addlevPr = self.addlevelPushButton.clicked
        addlevPr.connect(self.addLevel)
        dellevPr = self.deletelevelsPushButton.clicked
        dellevPr.connect(self.removeLevel)

        maxvalCh = self.maxValueSpinBox.valueChanged
        maxvalCh.connect(self.minmaxvalueChanged)
        maxvalFi = self.maxValueSpinBox.editingFinished
        maxvalFi.connect(self.minmaxvalueEdFinished)
        minvalCh = self.minValueSpinBox.valueChanged
        minvalCh.connect(self.minmaxvalueChanged)
        minvalFi = self.minValueSpinBox.editingFinished
        minvalFi.connect(self.minmaxvalueEdFinished)

        # Set instance variables
        #self.mem_layer = None
        self.worker = None
        self.inputlayerid = None
        self.inputlayer = None
        self.layerlistchanging = False
        self.minvalue = 1
        self.inputrasterprovider = None
        self.histobins = 50
        self.setupScene = QGraphicsScene(self)
        self.histoGraphicsView.setScene(self.setupScene)
        # Is the layer band of an integer type
        self.intband = False
        self.histogramAvailable = False
        self.histo = None
        self.histopadding = 1
class ThinGreyscaleDialog(QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        self.iface = iface
        self.plugin_dir = dirname(__file__)
        self.THINGREYSCALE = self.tr('ThinGreyscale')
        self.BROWSE = self.tr('Browse')
        self.CANCEL = self.tr('Cancel')
        self.CLOSE = self.tr('Close')
        self.HELP = self.tr('Help')
        self.OK = self.tr('OK')
        self.DEFAULTPROVIDER = 'GTiff'
        self.DEFAULTEXTENSION = '.tif'
        self.EXTRAEXTENSION = ' *.tiff'
        super(ThinGreyscaleDialog, 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)

        self.showInfo("Connecting UI components")
        okButton = self.button_box.button(QDialogButtonBox.Ok)
        okButton.setText(self.OK)
        cancelButton = self.button_box.button(QDialogButtonBox.Cancel)
        cancelButton.setText(self.CANCEL)
        cancelButton.setEnabled(False)
        closeButton = self.button_box.button(QDialogButtonBox.Close)
        closeButton.setText(self.CLOSE)
        browseButton = self.browseButton
        browseButton.setText(self.BROWSE)
        self.calcHistPushButton.setEnabled(False)
        self.listModel = QStandardItemModel(self.levelsListView)
        self.levelsListView.setModel(self.listModel)
        self.levelsListView.sizeHintForColumn(20)
        #self.levelValuesCheckBox.setEnabled(False)
        # Help button
        helpButton = self.helpButton
        helpButton.setText(self.HELP)

        # Connect signals
        self.showInfo("Connecting signals")
        okButton.clicked.connect(self.startWorker)
        cancelButton.clicked.connect(self.killWorker)
        closeButton.clicked.connect(self.reject)
        helpButton.clicked.connect(self.help)
        browseButton.clicked.connect(self.browse)

        inpIndexCh = self.inputRaster.currentIndexChanged['QString']
        inpIndexCh.connect(self.layerchanged)
        bandCh = self.bandComboBox.currentIndexChanged['QString']
        bandCh.connect(self.bandChanged)
        #self.iface.legendInterface().itemAdded.connect(
        #    self.layerlistchanged)
        #self.iface.legendInterface().itemRemoved.connect(
        #    self.layerlistchanged)
        #QObject.disconnect(self.button_box, SIGNAL("rejected()"), self.reject)
        self.button_box.rejected.disconnect(self.reject)
        calchistPr = self.calcHistPushButton.clicked
        calchistPr.connect(self.calculateHistogram)
        sugglevPr = self.suggestlevelsPushButton.clicked
        sugglevPr.connect(self.suggestLevels)
        addlevPr = self.addlevelPushButton.clicked
        addlevPr.connect(self.addLevel)
        dellevPr = self.deletelevelsPushButton.clicked
        dellevPr.connect(self.removeLevel)

        maxvalCh = self.maxValueSpinBox.valueChanged
        maxvalCh.connect(self.minmaxvalueChanged)
        maxvalFi = self.maxValueSpinBox.editingFinished
        maxvalFi.connect(self.minmaxvalueEdFinished)
        minvalCh = self.minValueSpinBox.valueChanged
        minvalCh.connect(self.minmaxvalueChanged)
        minvalFi = self.minValueSpinBox.editingFinished
        minvalFi.connect(self.minmaxvalueEdFinished)

        # Set instance variables
        #self.mem_layer = None
        self.worker = None
        self.inputlayerid = None
        self.inputlayer = None
        self.layerlistchanging = False
        self.minvalue = 1
        self.inputrasterprovider = None
        self.histobins = 50
        self.setupScene = QGraphicsScene(self)
        self.histoGraphicsView.setScene(self.setupScene)
        # Is the layer band of an integer type
        self.intband = False
        self.histogramAvailable = False
        self.histo = None
        self.histopadding = 1

    def startWorker(self):
        """Initialises and starts the worker thread."""
        try:
            layerindex = self.inputRaster.currentIndex()
            layerId = self.inputRaster.itemData(layerindex)
            inputlayer = QgsProject.instance().mapLayer(layerId)
            #inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
            if inputlayer is None:
                self.showError(self.tr('No input layer defined'))
                return
            # create a reference to the layer that is being processed
            # (for use when creating the resulting raster layer)
            self.thinninglayer = inputlayer
            self.levels = []
            #self.levelsListView.selectAll()
            #selected = self.levelsListView.selectedIndexes()
            if self.levelsListView.model().rowCount() == 0:
                self.showInfo("Levels must be specified!")
                return
            for i in range(self.levelsListView.model().rowCount()):
                levelstring = self.levelsListView.model().item(i).text()
                #for i in selected:
                #    levelstring = self.levelsListView.model().itemData(i)[0]
                if self.intband:
                    self.levels.append(int(levelstring))
                else:
                    self.levels.append(float(levelstring))
            #self.levelsListView.clearSelection()
            # create a new worker instance
            worker = Worker(inputlayer, self.levels, self.intband)
            # configure the QgsMessageBar
            msgBar = self.iface.messageBar().createMessage(
                self.tr('Skeletonising'), '')
            self.aprogressBar = QProgressBar()
            self.aprogressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
            acancelButton = QPushButton()
            acancelButton.setText(self.CANCEL)
            acancelButton.clicked.connect(self.killWorker)
            msgBar.layout().addWidget(self.aprogressBar)
            msgBar.layout().addWidget(acancelButton)
            # Has to be popped after the thread has finished (in
            # workerFinished).
            self.iface.messageBar().pushWidget(msgBar, Qgis.Info)
            self.messageBar = msgBar
            # start the worker in a new thread
            thread = QThread(self)
            worker.moveToThread(thread)
            worker.finished.connect(self.workerFinished)
            worker.error.connect(self.workerError)
            worker.status.connect(self.workerInfo)
            worker.progress.connect(self.progressBar.setValue)
            worker.progress.connect(self.aprogressBar.setValue)
            worker.iterprogress.connect(self.iterProgressBar.setValue)
            thread.started.connect(worker.run)
            thread.start()
            self.thread = thread
            self.worker = worker
            self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
            self.button_box.button(QDialogButtonBox.Close).setEnabled(False)
            self.button_box.button(QDialogButtonBox.Cancel).setEnabled(True)
        except:
            import traceback
            self.showError(traceback.format_exc())
        else:
            pass

    def workerFinished(self, ok, ret):
        """Handles the output from the worker and cleans up after the
           worker has finished."""
        # clean up the worker and thread
        self.showInfo("Handling the result")
        self.worker.deleteLater()
        self.thread.quit()
        self.thread.wait()
        self.thread.deleteLater()
        # remove widget from message bar (pop)
        self.iface.messageBar().popWidget(self.messageBar)
        if ok and ret is not None:
            #self.showInfo("Ret: "+str(ret[10,]))
            # Transformation:
            self.minx = self.thinninglayer.extent().xMinimum()
            self.maxx = self.thinninglayer.extent().xMaximum()
            self.miny = self.thinninglayer.extent().yMinimum()
            self.maxy = self.thinninglayer.extent().yMaximum()
            self.rows = self.thinninglayer.height()
            self.cols = self.thinninglayer.width()
            self.xres = (self.maxx - self.minx) / float(self.cols)
            self.yres = (self.maxy - self.miny) / float(self.rows)
            geotransform = (self.minx, self.xres, 0, self.maxy, 0, -self.yres)
            try:
                format = self.DEFAULTPROVIDER
                driver = gdal.GetDriverByName(format)
                NOVALUE = 0
                metadata = driver.GetMetadata()
                fileName = self.outputRaster.text()
                if self.outputRaster.text() == "":
                    self.showInfo("No output file specified, " +
                                  "creating a temporary file")
                    # Get a temporary file
                    fileName = mktemp(prefix='greyskel',
                                      suffix=self.DEFAULTEXTENSION)
                fileInfo = QFileInfo(fileName)
                filepath = fileInfo.absolutePath()
                baseName = fileInfo.baseName()
                suffix = fileInfo.suffix()
                thisfilename = filepath + baseName + '.' + suffix
                thisfilename = fileName
                self.showInfo("File name: " + thisfilename)
                gdaldatatype = gdal.GDT_Byte
                skelmatrix = None
                if self.levelValuesCheckBox.isChecked():
                    # Transform the pixel values back to the original
                    # level values
                    my_dict = {}
                    # Add zero to handle the "empty" pixels
                    my_dict[0] = 0
                    for i in range(len(self.levels)):
                        my_dict[i + 1] = self.levels[i]
                    skelmatrix = np.vectorize(my_dict.__getitem__,
                                              otypes=[np.float])(ret)
                    gdaldatatype = gdal.GDT_Int32
                    if not self.intband:
                        gdaldatatype = gdal.GDT_Float32
                else:
                    skelmatrix = ret
                outDataset = driver.Create(thisfilename, self.cols, self.rows,
                                           1, gdaldatatype)
                if self.thinninglayer.dataProvider().crs() is not None:
                    srs = self.thinninglayer.dataProvider().crs()
                    outDataset.SetProjection(srs.toWkt().encode(
                        'ascii', 'ignore'))
                skeletonband = outDataset.GetRasterBand(1)
                skeletonband.WriteArray(skelmatrix)
                skeletonband.SetNoDataValue(NOVALUE)
                #stats = skeletonband.GetStatistics(False, True)
                #skeletonband.SetStatistics(stats[0], stats[1],
                #                                 stats[2], stats[3])
                outDataset.SetGeoTransform(geotransform)
                outDataset = None  # To close the file
                # report the result
                rlayer = QgsRasterLayer(thisfilename, baseName)
                self.layerlistchanging = True
                #QgsMapLayerRegistry.instance().addMapLayer(rlayer)
                QgsProject.instance().addMapLayer(rlayer)
                self.layerlistchanging = False
            except:
                import traceback
                self.showError("Can't write the skeleton file:  %s" %
                               self.outputRaster.text() + ' - ' +
                               traceback.format_exc())
                okb = self.button_box.button(QDialogButtonBox.Ok)
                okb.setEnabled(True)
                closb = self.button_box.button(QDialogButtonBox.Close)
                closb.setEnabled(True)
                cancb = self.button_box.button(QDialogButtonBox.Cancel)
                cancb.setEnabled(False)
                return
            QgsMessageLog.logMessage(self.tr('ThinGreyscale finished'),
                                     self.THINGREYSCALE, Qgis.Info)
        else:
            # notify the user that something went wrong
            if not ok:
                self.showError(self.tr('Aborted') + '!')
            else:
                self.showError(self.tr('No skeleton created') + '!')
        self.progressBar.setValue(0.0)
        #self.aprogressBar.setValue(0.0)
        self.iterProgressBar.setValue(0.0)
        self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
        self.button_box.button(QDialogButtonBox.Close).setEnabled(True)
        self.button_box.button(QDialogButtonBox.Cancel).setEnabled(False)

    def workerError(self, exception_string):
        """Report an error from the worker."""
        #QgsMessageLog.logMessage(self.tr('Worker failed - exception') +
        #                         ': ' + str(exception_string),
        #                         self.THINGREYSCALE,
        #                         QgsMessageLog.CRITICAL)
        self.showError(exception_string)

    def workerInfo(self, message_string):
        """Report an info message from the worker."""
        QgsMessageLog.logMessage(
            self.tr('Worker') + ': ' + message_string, self.THINGREYSCALE,
            Qgis.Info)

    def layerchanged(self, number=0):
        """Do the necessary updates after a layer selection has
           been changed."""
        self.showInfo("Layer changed")
        # If the layer list is being updated, don't do anything
        if self.layerlistchanging:
            return
        layerindex = self.inputRaster.currentIndex()
        layerId = self.inputRaster.itemData(layerindex)
        self.inputlayerid = layerId
        #self.inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
        self.inputlayer = QgsProject.instance().mapLayer(layerId)
        if self.inputlayer is not None:
            self.inputrasterprovider = self.inputlayer.dataProvider()
            self.bandComboBox.clear()
            bandcount = self.inputlayer.bandCount()
            #self.showInfo("Layer bandcount: "+str(bandcount))
            for i in range(bandcount):
                self.bandComboBox.addItem(self.inputlayer.bandName(i + 1), i)
                #self.showInfo("Band " + str(i) + ": " +
                #                self.inputlayer.bandName(i+1))
            # Check if the driver supports Create() or CreateCopy()
            #gdalmetadata = self.inputlayer.metadata()
            #self.showInfo("Layer metadata: " +
            #                str(gdalmetadata.encode('utf-8')))
            #provstring = '<p>GDAL provider</p>\n'
            #providerpos = gdalmetadata.find(provstring)
            #brpos = gdalmetadata.find('<br>', providerpos + len(provstring))
            #self.gdalprovider = gdalmetadata[int(providerpos +
            #                             len(provstring)):int(brpos)]
            #self.showInfo('GDAL provider: '+self.gdalprovider)
            #drivername = self.gdalprovider.encode('ascii', 'ignore')
            #theDriver = gdal.GetDriverByName(drivername)
            #if theDriver is None:
            #    self.showInfo("Unable to get the raster driver")
            #else:
            #data    theMetadata = theDriver.GetMetadata()
            #self.showInfo("Driver metadata: "+str(theMetadata))
            #if ((gdal.DCAP_CREATE in theMetadata) and
            #        theMetadata[gdal.DCAP_CREATE] == 'YES'):
            #    self.canCreate = True
            #if (theMetadata.has_key(gdal.DCAP_CREATECOPY) and
            #if ((gdal.DCAP_CREATECOPY in theMetadata) and
            #        theMetadata[gdal.DCAP_CREATECOPY] == 'YES'):
            #    self.canCreateCopy = True
            #self.showInfo('raster provider type: ' +
            #                str(self.inputlayer.providerType()))
            # Determine the file suffix
            #self.gdalext = ""
            #if gdal.DMD_EXTENSION in theMetadata:
            #    self.gdalext = "." + theMetadata[gdal.DMD_EXTENSION]
            #else:
            #    self.showInfo("No extension available in GDAL metadata")
            # by parsing the layer metadata looking for
            #           "Dataset Description"
            #descstring = 'Dataset Description</p>\n<p>'
            #descpos = gdalmetadata.find(descstring)
            #ppos = gdalmetadata.find('</p>',descpos+len(descstring))
            #filename = gdalmetadata[descpos+len(descstring):ppos]
            #self.gdalext = splitext(filename)[1]
            #self.showInfo('GDAL extension: '+self.gdalext)
            # Determine the datatype
            #datatypestring = 'Data Type</p>\n<p>'
            #datatypepos = gdalmetadata.find(datatypestring)
            #ppos = gdalmetadata.find('</p>',
            #                   datatypepos + len(datatypestring))
            #datatypedesc = gdalmetadata[datatypepos +
            #                            len(datatypestring):ppos]
            #shortdesc = datatypedesc.split()[0]
            #self.showInfo('GDAL data type: GDT_'+shortdesc)
            # Call the findGdalDatatype function
            #self.findGdalDatatype(shortdesc)
            #   self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
            self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
            self.calcHistPushButton.setEnabled(True)
            self.suggestlevelsPushButton.setEnabled(True)

    def bandChanged(self):
        band = self.bandComboBox.currentIndex() + 1
        self.showInfo("Band changed: " + str(band))
        statistics = self.inputrasterprovider.bandStatistics(band)
        #self.showInfo("Band statistics: " + str(statistics.minimumValue) +
        #                            " - " + str(statistics.maximumValue) +
        #                            " - " + str(statistics.mean))
        self.bandmin = statistics.minimumValue
        self.bandmax = statistics.maximumValue
        dt = self.inputrasterprovider.dataType(band)
        # Integer data type
        if (dt == Qgis.Byte or dt == Qgis.UInt16 or dt == Qgis.Int16
                or dt == Qgis.UInt32 or dt == Qgis.Int32):
            self.intband = True
            self.minValueSpinBox.setDecimals(0)
            self.maxValueSpinBox.setDecimals(0)
            self.levelSpinBox.setDecimals(0)
            self.bandMinLabel.setText(str(int(statistics.minimumValue)))
            self.bandMaxLabel.setText(str(int(statistics.maximumValue)))
        else:
            self.intband = False
            self.minValueSpinBox.setDecimals(5)
            self.maxValueSpinBox.setDecimals(5)
            self.levelSpinBox.setDecimals(5)
            minlabtext = "{0:.5f}".format(statistics.minimumValue)
            self.bandMinLabel.setText(minlabtext)
            maxlabtext = "{0:.5f}".format(statistics.maximumValue)
            self.bandMaxLabel.setText(maxlabtext)
        #self.minValueSpinBox.setMinimum(statistics.minimumValue)
        self.maxValueSpinBox.setMinimum(statistics.minimumValue)
        #self.minValueSpinBox.setMaximum(statistics.maximumValue)
        self.maxValueSpinBox.setMaximum(statistics.maximumValue)
        #self.minValueSpinBox.setValue(statistics.minimumValue)
        if not (statistics.statsGathered & statistics.Mean):
            bandmean = (statistics.minimumValue + statistics.maximumValue) / 2
        else:
            #self.showInfo("statsgathered: " + str(statistics.statsGathered))
            bandmean = statistics.mean
        if self.intband:
            self.minValueSpinBox.setValue(int(ceil(bandmean)))
        else:
            self.minValueSpinBox.setValue(bandmean)
        self.maxValueSpinBox.setValue(statistics.maximumValue)
        self.histMinValue.setText(str(statistics.minimumValue))
        self.histMaxValue.setText(str(statistics.maximumValue))
        self.levelSpinBox.setMinimum(statistics.minimumValue)
        self.levelSpinBox.setMaximum(statistics.maximumValue)
        self.histogramAvailable = False
        #if self.inputrasterprovider.hasStatistics(band):
        #if statistics.statsGathered:
        #histogram = statistics.histogramVector
        #self.showInfo("Histogram: " + str(histogram))
        #range = min to max
        #np.histogram(band, 50, range)

    def minmaxvalueChanged(self):
        #if self.minValueSpinBox is None:
        #    return
        minvalue = self.minValueSpinBox.value()
        #if minvalue is None:
        #    return
        #if self.maxValueSpinBox is None:
        #    return
        maxvalue = self.maxValueSpinBox.value()
        #if maxvalue is None:
        #   return
        if isnan(maxvalue) or isnan(minvalue):
            return
        self.showInfo("minvalue: " + str(minvalue) + " Maxvalue: " +
                      str(maxvalue))
        #if self.intband:
        #    minvalue = int(minvalue)
        #    maxvalue = int(maxvalue)
        if abs(maxvalue - minvalue) < 0.00001:
            #if maxvalue == maxvalue:
            self.calcHistPushButton.setEnabled(False)
        else:
            self.calcHistPushButton.setEnabled(True)
        # Update the min and max value spinboxes
        self.minValueSpinBox.setMaximum(maxvalue)
        self.maxValueSpinBox.setMinimum(minvalue)
        self.minValueSpinBox.setMinimum(self.bandmin)

    def minmaxvalueEdFinished(self):
        minvalue = self.minValueSpinBox.value()
        maxvalue = self.maxValueSpinBox.value()
        if self.intband:
            minvalue = int(minvalue)
            maxvalue = int(maxvalue)
        self.showInfo("minvalue: " + str(minvalue) + " Maxvalue: " +
                      str(maxvalue))
        # Update the spin box for adding levels
        self.levelSpinBox.setMinimum(minvalue)
        self.levelSpinBox.setMaximum(maxvalue)
        if self.levelSpinBox.value() < minvalue:
            self.levelSpinBox.setValue(minvalue)
        if self.levelSpinBox.value() > maxvalue:
            self.levelSpinBox.setValue(maxvalue)
        # Update the min and max value spinboxes
        self.minValueSpinBox.setMaximum(maxvalue)
        self.maxValueSpinBox.setMinimum(minvalue)

        # Adjust the levels:
        i = 0
        while self.levelsListView.model().item(i):
            #for i in range(self.levelsListView.model().rowCount()):
            #self.showInfo("Element: " +
            #       str(self.levelsListView.model().item(i).text()))
            #continue
            value = float(self.levelsListView.model().item(i).text())
            if value < minvalue:
                if i == 0:
                    self.levelsListView.model().item(i).setText(str(minvalue))
                    i = i + 1
                else:
                    self.levelsListView.model().removeRow(i)
            elif value > maxvalue:
                if i == self.levelsListView.model().rowCount() - 1:
                    self.levelsListView.model().item(i).setText(str(maxvalue))
                    i = i + 1
                else:
                    self.levelsListView.model().removeRow(i)
            else:
                i = i + 1
        self.drawHistogram()

    def calculateHistogram(self):
        self.showInfo("Calculating histogram...")
        if self.inputlayer is None:
            return

        self.showInfo("Calculating histogram...")
        # Check if there is only one value
        myrange = (self.minValueSpinBox.value(), self.maxValueSpinBox.value())
        self.inputextent = self.inputlayer.extent()
        self.inputrdp = self.inputlayer.dataProvider()
        width = self.inputlayer.width()
        height = self.inputlayer.height()
        if width == 0 or height == 0:
            self.showInfo("Image has zero width or height")
            return
        extwidth = self.inputextent.width()
        extheight = self.inputextent.height()
        # Read the raster block and get the maximum value
        rasterblock = self.inputrdp.block(1, self.inputextent, width, height)
        # Create a numpy array version of the image
        imageMat = np.zeros((height, width), dtype=np.float16)
        # This one takes a lot of time!
        for row in range(height):
            for column in range(width):
                imageMat[row, column] = rasterblock.value(row, column)
                self.showInfo("Image: " + str(height) + ", " + str(width) +
                              " - " + str(imageMat[row, column]))
        self.histo = np.histogram(imageMat, self.histobins, myrange)
        #relevantpixels = imageMat[np.where(imageMat >= bandval)]
        minlevel = float(self.bandMinLabel.text())
        relevantpixels = imageMat[np.where(imageMat >= minlevel)]
        #self.showInfo("Histogram: " + str(self.histo))
        nanpercentage = 100.0 - 100.0 * len(relevantpixels) / (width * height)
        self.bandNANLabel.setText("{0:.1f}".format(nanpercentage))
        #self.showInfo("Percentage NAN: " + str(100.0 - 100.0 *
        #                    len(relevantpixels) / (width * height)))
        #self.showInfo("First element: " + str(self.histo[0]))
        #self.showInfo("First element, first: " + str(self.histo[0][0]))
        #self.showInfo("First element, second: " + str(self.histo[0][1]))
        self.histMinValue.setText(str(self.minValueSpinBox.value()))
        self.histMaxValue.setText(str(self.maxValueSpinBox.value()))
        if self.intband:
            self.histMinValue.setText(str(int(self.minValueSpinBox.value())))
            self.histMaxValue.setText(str(int(self.maxValueSpinBox.value())))
        self.histogramAvailable = True
        self.drawHistogram()

    def drawHistogram(self):
        #if self.inputlayer is None:
        #    return
        self.showInfo("Drawing histogram...")
        viewprect = QRectF(self.histoGraphicsView.viewport().rect())
        self.histoGraphicsView.setSceneRect(viewprect)
        self.setupScene.clear()
        self.setupScene.update()
        histbottom = self.histoGraphicsView.sceneRect().bottom()
        histtop = self.histoGraphicsView.sceneRect().top()
        left = self.histoGraphicsView.sceneRect().left() + self.histopadding
        right = self.histoGraphicsView.sceneRect().right() - self.histopadding
        histheight = histbottom - histtop
        histwidth = right - left
        step = 1.0 * histwidth / self.histobins
        maxlength = histheight
        padding = 1
        ll = QPoint(self.histopadding - 1, histheight - padding)
        start = QPointF(self.histoGraphicsView.mapToScene(ll))

        # Check if there is only one value
        #myrange = (self.minValueSpinBox.value(),self.maxValueSpinBox.value())
        if self.histogramAvailable:
            maxvalue = 0.0
            for i in range(len(self.histo[0])):
                if self.histo[0][i] > maxvalue:
                    maxvalue = self.histo[0][i]
            if maxvalue == 0:
                return
            self.maxBinNumber.setText(str(maxvalue))
            # Create the histogram:
            #self.showInfo("maxvalue: " + str(maxvalue))
            #self.showInfo("maxlength: " + str(maxlength))
            #self.showInfo("step: " + str(step))
            for i in range(self.histobins):
                binnumber = self.histo[0][i]
                if binnumber == 0:
                    continue
                height = (1.0 * self.histo[0][i] / maxvalue *
                          (maxlength - padding))
                rectangle = QGraphicsRectItem(start.x() + step * i, start.y(),
                                              step, -height)
                rectangle.setPen(QPen(QColor(102, 102, 102)))
                rectangle.setBrush(QBrush(QColor(240, 240, 240)))
                self.setupScene.addItem(rectangle)
                #self.showInfo(str(i) + ": " + str(height))
            #if self.levelsListView.model().rowCount() > 0:
        # Add lines for the levels
        minvalue = float(self.histMinValue.text())
        maxvalue = float(self.histMaxValue.text())
        datarange = maxvalue - minvalue
        if datarange == 0:
            return
        i = 0
        while self.levelsListView.model().item(i):
            #self.showInfo("Element: " +
            #       str(self.levelsListView.model().item(i).text()))
            #continue
            value = float(self.levelsListView.model().item(i).text())
            xvalue = start.x() + histwidth * (value - minvalue) / datarange
            line = QGraphicsLineItem(xvalue, 0, xvalue, histheight)
            if i == 0 or i == (self.levelsListView.model().rowCount() - 1):
                line.setPen(QPen(QColor(204, 0, 0)))
            else:
                line.setPen(QPen(QColor(0, 204, 0)))
            self.setupScene.addItem(line)
            i = i + 1

    def suggestLevels(self):
        self.listModel.clear()
        self.showInfo("Suggesting levels")
        levels = self.levelsSpinBox.value()
        startvalue = self.minValueSpinBox.value()
        endvalue = self.maxValueSpinBox.value()
        increment = (endvalue - startvalue) / levels
        for i in range(levels + 1):
            value = startvalue + increment * i
            if self.intband:
                value = int(value)
            item = QStandardItem(str(value))
            self.listModel.appendRow(item)
        self.drawHistogram()

    def addLevel(self):
        newvalue = self.levelSpinBox.value()
        if self.intband:
            newvalue = int(newvalue)
        for i in range(self.listModel.rowCount()):
            # Check if the value is already in the list
            if self.listModel.item(i).text() == str(newvalue):
                return
            else:
                # Maintain a sorted list of distances
                if (float(self.listModel.item(i).text()) > float(
                        str(newvalue))):
                    item = QStandardItem(str(newvalue))
                    self.listModel.insertRow(i, item)
                    self.drawHistogram()
                    return
        item = QStandardItem(str(newvalue))
        self.listModel.appendRow(item)
        #if self.histogramAvailable:
        #    addLevelsToHistogram()
        self.drawHistogram()

    def removeLevel(self):
        self.levelsListView.setUpdatesEnabled(False)
        indexes = self.levelsListView.selectedIndexes()
        indexes.sort()
        for i in range(len(indexes) - 1, -1, -1):
            self.listModel.removeRow(indexes[i].row())
        self.levelsListView.setUpdatesEnabled(True)
        #if self.histogramAvailable:
        #    removeLevelFromHistogram()
        self.drawHistogram()

    def layerlistchanged(self):
        self.layerlistchanging = True
        self.showInfo("Layer list changed")
        # Repopulate the input layer combo box
        # Save the currently selected input layer
        inputlayerid = self.inputlayerid
        self.inputRaster.clear()
        for alayer in self.iface.legendInterface().layers():
            if alayer.type() == QgsMapLayer.RasterLayer:
                gdalmetadata = alayer.metadata()
                # Skip WMS layers
                WMSstring = 'Web Map Service'
                wmspos = gdalmetadata.find(WMSstring)
                if wmspos != -1:
                    continue
                self.inputRaster.addItem(alayer.name(), alayer.id())
        # Set the previous selection
        for i in range(self.inputRaster.count()):
            if self.inputRaster.itemData(i) == inputlayerid:
                self.inputRaster.setCurrentIndex(i)
        self.layerlistchanging = False
        #self.updateui()

    def updateui(self):
        """Do the necessary updates after a layer selection has
           been changed."""
        #if self.layerlistchanged:
        #    return
        #self.outputRaster.setText(self.inputRaster.currentText() +
        #                           '_' + 'thinned')
        layerindex = self.inputRaster.currentIndex()
        layerId = self.inputRaster.itemData(layerindex)
        #inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
        inputlayer = QgsProject.instance().mapLayer(layerId)
        if inputlayer is not None:
            pass
        else:
            pass

    def findGdalDatatype(self, shortdesc):
        gdaldatatype = None
        # // Unknown or unspecified type
        # GDT_Unknown = GDALDataType(C.GDT_Unknown)
        if shortdesc == 'Unknown':
            gdaldatatype = gdal.GDT_Unknown
        # // Eight bit unsigned integer
        # GDT_Byte = GDALDataType(C.GDT_Byte)
        elif shortdesc == 'Byte':
            gdaldatatype = gdal.GDT_Byte
        # // Sixteen bit unsigned integer
        # GDT_UInt16 = GDALDataType(C.GDT_UInt16)
        elif shortdesc == 'UInt16':
            gdaldatatype = gdal.GDT_UInt16
        # // Sixteen bit signed integer
        # GDT_Int16 = GDALDataType(C.GDT_Int16)
        elif shortdesc == 'Int16':
            gdaldatatype = gdal.GDT_Int16
        # // Thirty two bit unsigned integer
        # GDT_UInt32 = GDALDataType(C.GDT_UInt32)
        elif shortdesc == 'UInt32':
            gdaldatatype = gdal.GDT_UInt32
        # // Thirty two bit signed integer
        # GDT_Int32 = GDALDataType(C.GDT_Int32)
        elif shortdesc == 'Int32':
            gdaldatatype = gdal.GDT_Int32
        # // Thirty two bit floating point
        # GDT_Float32 = GDALDataType(C.GDT_Float32)
        elif shortdesc == 'Float32':
            gdaldatatype = gdal.GDT_Float32
        # // Sixty four bit floating point
        # GDT_Float64 = GDALDataType(C.GDT_Float64)
        elif shortdesc == 'Float64':
            gdaldatatype = gdal.GDT_Float64
        # // Complex Int16
        # GDT_CInt16 = GDALDataType(C.GDT_CInt16)
        elif shortdesc == 'CInt16':
            gdaldatatype = gdal.CInt16
        # // Complex Int32
        # GDT_CInt32 = GDALDataType(C.GDT_CInt32)
        elif shortdesc == 'CInt32':
            gdaldatatype = gdal.CInt32
        # // Complex Float32
        # GDT_CFloat32 = GDALDataType(C.GDT_CFloat32)
        elif shortdesc == 'CFloat32':
            gdaldatatype = gdal.CFloat32
        # // Complex Float64
        # GDT_CFloat64 = GDALDataType(C.GDT_CFloat64)
        elif shortdesc == 'CFloat64':
            gdaldatatype = gdal.CFloat64
        # // maximum type # + 1
        # GDT_TypeCount = GDALDataType(C.GDT_TypeCount)
        elif shortdesc == 'TypeCount':
            gdaldatatype = gdal.TypeCount
        self.gdaldatatype = gdaldatatype

    def killWorker(self):
        """Kill the worker thread."""
        if self.worker is not None:
            QgsMessageLog.logMessage(self.tr('Killing worker'),
                                     self.THINGREYSCALE, Qgis.Info)
            self.worker.kill()

    def showError(self, text):
        """Show an error."""
        self.iface.messageBar().pushMessage(self.tr('Error'),
                                            text,
                                            level=QgsMessageBar.CRITICAL,
                                            duration=3)
        QgsMessageLog.logMessage('Error: ' + text, self.THINGREYSCALE,
                                 QgsMessageLog.CRITICAL)

    def showWarning(self, text):
        """Show a warning."""
        self.iface.messageBar().pushMessage(self.tr('Warning'),
                                            text,
                                            level=QgsMessageBar.WARNING,
                                            duration=2)
        QgsMessageLog.logMessage('Warning: ' + text, self.THINGREYSCALE,
                                 QgsMessageLog.WARNING)

    def showInfo(self, text):
        """Show info."""
        self.iface.messageBar().pushMessage(self.tr('Info'),
                                            text,
                                            level=Qgis.Info,
                                            duration=2)
        QgsMessageLog.logMessage('Info: ' + text, self.THINGREYSCALE,
                                 Qgis.Info)

    # def help(self):
    # #QDesktopServices.openUrl(QUrl.fromLocalFile(self.plugin_dir +
    #                                 "/help/build/html/index.html"))
    # QDesktopServices.openUrl(QUrl.fromLocalFile(self.plugin_dir +
    #                                            "/help/index.html"))
    # #showPluginHelp()

    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        return QCoreApplication.translate('ThinGreyScaleDialog', message)

    def browse(self):
        settings = QSettings()
        key = '/UI/lastShapefileDir'
        outDir = settings.value(key)
        home = outDir
        #outDir = expanduser("~")
        #filter = (self.DEFAULTPROVIDER + " (*" +
        #             self.DEFAULTEXTENSION + ");;All files (*)")
        filter = (self.DEFAULTPROVIDER + " (*" + self.DEFAULTEXTENSION +
                  self.EXTRAEXTENSION + ")")
        #if (self.gdalprovider != self.DEFAULTPROVIDER and
        #                                     (self.canCreateCopy or
        #                                           self.canCreate)):
        #    filter = (self.gdalprovider + " (*" + self.gdalext +
        #                                          ");;" + filter)
        outFilePath = QFileDialog.getSaveFileName(
            self, 'Specify file name for skeleton', outDir, filter)
        outFilePath = unicode(outFilePath)
        if outFilePath:
            root, ext = splitext(outFilePath)
            if ext.lower() != '.tif' and ext.lower() != '.tiff':
                outFilePath = '%s.tif' % outFilePath
            outDir = dirname(outFilePath)
            settings.setValue(key, outDir)
        #        (self.canCreateCopy or self.canCreate):
        #    fileName = splitext(str(fileName))[0]+self.gdalext
        self.outputRaster.setText(outFilePath)

    # Overriding
    def resizeEvent(self, event):
        #self.showInfo("resizeEvent")
        self.calculateHistogram()

    def help(self):
        #QDesktopServices.openUrl(QUrl.fromLocalFile(
        #                 self.plugin_dir + "/help/html/index.html"))
        showPluginHelp(None, "help/html/index")

    # Implement the accept method to avoid exiting the dialog when
    # starting the work
    def accept(self):
        """Accept override."""
        pass

    # Implement the reject method to have the possibility to avoid
    # exiting the dialog when cancelling
    def reject(self):
        """Reject override."""
        # exit the dialog
        QDialog.reject(self)
Ejemplo n.º 24
0
class qgisSpectre:
    """QGIS Plugin Implementation."""
    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)

        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   'qgisSpectre_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&Spectre Viewer')
        self.toolbar = self.iface.addToolBar(u'Spectre viewer')
        self.toolbar.setObjectName(u'Spectre viewer')
        self.pluginname = "mortensickel_Spectrumviewer"

        self.view = MouseReadGraphicsView(self.iface)
        self.pluginIsActive = False

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('qgisSpectre', message)

    def add_action(self,
                   icon_path,
                   text,
                   callback,
                   enabled_flag=True,
                   add_to_menu=True,
                   add_to_toolbar=True,
                   status_tip=None,
                   whats_this=None,
                   parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToDatabaseMenu(self.menu, action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/qgisSpectre/icon.png'
        self.add_action(icon_path,
                        text=self.tr(u'View Spectra'),
                        callback=self.run,
                        parent=self.iface.mainWindow())
        self.dlg = qgisSpectreDockWidget(self.iface.mainWindow())
        self.view.setParent(self.dlg)
        self.dlg.hlMain.addWidget(self.view)
        #self.dlg.cbLayer.currentIndexChanged['QString'].connect(self.listfields)
        self.dlg.qgLayer.setFilters(QgsMapLayerProxyModel.VectorLayer)
        self.dlg.qgField.setLayer(self.dlg.qgLayer.currentLayer())
        # self.dlg.qgField.setFilters(QgsFieldProxyModel.Numeric)
        self.dlg.qgLayer.layerChanged.connect(
            lambda: self.dlg.qgField.setLayer(self.dlg.qgLayer.currentLayer()))

    #--------------------------------------------------------------------------

    def onClosePlugin(self):
        """Cleanup necessary items here when plugin dockwidget is closed"""

        #print "** CLOSING qgisSpectre"

        # disconnects
        self.dlg.closingPlugin.disconnect(self.onClosePlugin)

        # remove this statement if dockwidget is to remain
        # for reuse if plugin is reopened
        # Commented next statement since it causes QGIS crashe
        # when closing the docked window:
        # self.dockwidget = None

        self.pluginIsActive = False

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""

        #print "** UNLOAD qgisSpectre"

        for action in self.actions:
            self.iface.removePluginDatabaseMenu(self.tr(u'&Spectre Viewer'),
                                                action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        del self.toolbar

    def drawspectra(self):
        """ Drawing the spectra on the graphicsstage """
        layername = self.dlg.qgLayer.currentText()
        fieldname = self.dlg.qgField.currentText()
        layer = self.dlg.qgLayer.currentLayer()
        if layer == None:
            return  # Happens some times, just as well to return
        self.scene.acalib = float(self.dlg.leA.text())
        self.scene.bcalib = float(self.dlg.leB.text())
        self.scene.unit = self.dlg.leUnit.text()
        logscale = self.dlg.cbLog.isChecked()
        if logscale:
            dataset = []
            for n in self.view.spectreval:
                if n == 0:
                    n = 0.9
                dataset.append(math.log(n) - math.log(0.9))
                # 0.9 offset and back to be able to plot zero-values
        else:
            dataset = self.view.spectreval

        #DONE: Add x and y axis
        #DONE: Add scale factors to scale x axis from channel number to keV
        #DONE: Add settings to have custom unit
        #TODO: Custom scales
        #TODO: Keep spectra to compare
        #DONE: Draw spectra as line, not "line-histogram"
        #TODO: Select different drawing styles
        #DONE: Save as file
        #DONE: export data to clipboard
        #TODO: export image to clipboard
        #TODO: Peak detection
        #TODO: Save different set of calibration values

        self.scene.h = 300  # Height of stage
        self.scene.clear()
        self.scene.crdtext = None
        self.scene.markerline = None
        backgroundbrush = QBrush(Qt.white)
        outlinepen = QPen(Qt.white)
        # Needs this when saving as png, or background from map will shine through
        self.scene.addRect(0, 0, 1200, 300, outlinepen, backgroundbrush)
        self.scene.bottom = 20  # Bottom clearing (for x tick marks and labels)
        self.scene.left = self.scene.bottom  # Left clearing (for y tick marks and labels)
        n = self.scene.left
        bt = self.scene.bottom
        h = self.scene.h
        self.scene.addLine(float(n - 1), float(h - bt), float(n - 1),
                           10.0)  # Y-axis
        self.scene.addLine(float(n - 1), float(h - bt - 1),
                           float(len(dataset) + 10),
                           float(h - bt - 1))  # X-axis
        # Scales the spectra to fit with the size of the graphicsview
        fact = 1.0
        fact = (h - bt - 10) / max(dataset)
        prevch = 0
        for ch in dataset:
            # TODO: User selectable type of plot
            #     self.scene.addLine(float(n),float(h-bt),float(n),(h-bt-fact*ch))
            #     self.scene.addLine(float(n),float(h-(bt+4)-fact*ch),float(n),(h-bt-fact*ch))
            self.scene.addLine(float(n), float(h - bt - fact * prevch),
                               float(n + 1), (h - bt - fact * ch))
            prevch = ch
            n += 1
        self.scene.end = n - 1
        tickval = self.tickinterval
        s = QgsSettings()
        layername = self.dlg.qgLayer.currentText()
        fieldname = self.dlg.qgField.currentText()
        # This is already read in from the fields
        #acalib=s.value(self.pluginname+"/"+layername+"_"+fieldname+"_a",s.value(self.pluginname+"/defaulta", 1))
        #bcalib=s.value(self.pluginname+"/"+layername+"_"+fieldname+"_b",s.value(self.pluginname+"/defaultb", 0))
        #self.scene.unit=s.value(self.pluginname+"/"+layername+"_"+fieldname+"_unit",s.value(self.pluginname+"/defaultunit", 0))
        acalib = self.scene.acalib
        bcalib = self.scene.bcalib
        maxval = acalib * n + bcalib
        tickdist = tickval
        #if maxval/n > 5:             # Avoids to tight numbering.
        #    tickdist*=2 # Needs some better vay of doing this -
        left = self.scene.left
        while tickval < maxval:
            tickch = (tickval - bcalib) / acalib + left
            self.scene.addLine(float(tickch), float(h - bt), float(tickch),
                               float(h - bt + 5))  # Ticklines
            text = self.scene.addText(str(tickval))
            text.setPos(tickch + left - 40, 280)
            tickval += tickdist
        text = self.scene.addText(self.scene.unit)
        text.setPos(self.scene.end + 15, 280)
        ntext = self.scene.addText("n = {}".format(str(self.view.n)))
        ntext.setPos(self.scene.end + 50, 1)

    def updatecalib(self):
        """ Prepares newly typed in  calibration values for use """
        self.dlg.cbDefault.setChecked(False)
        layername = self.dlg.qgLayer.currentText()
        fieldname = self.dlg.qgField.currentText()
        try:
            self.scene.acalib = float(self.dlg.leA.text())
            self.scene.bcalib = float(self.dlg.leB.text())
        except ValueError:
            if self.dlg.leA.text() == '-' or self.dlg.leB.text(
            ) == '-' or self.dlg.leA.text() == '' or self.dlg.leB.text() == '':
                pass
            else:
                self.iface.messageBar().pushMessage("Calibrating",
                                                    "Invalid value(s)",
                                                    level=Qgis.Warning,
                                                    duration=3)

    def setdefault(self):
        """ Stores actual values as defaults """
        s = QgsSettings()
        if self.dlg.cbDefault.isChecked():
            s.setValue(self.pluginname + "/defaulta", self.scene.acalib)
            s.setValue(self.pluginname + "/defaultb", self.scene.bcalib)
            s.setValue(self.pluginname + "/defaultunit", self.scene.unit)

    def usedefault(self):
        """Fetches default values for the plot """
        s = QgsSettings()
        self.scene.bcalib = s.value(self.pluginname + "/defaultb", 0)
        self.scene.acalib = s.value(self.pluginname + "/defaulta", 1)
        self.scene.unit = s.value(self.pluginname + "/defaultunit", 'Ch')
        self.dlg.leA.setText(str(self.scene.acalib))
        self.dlg.leB.setText(str(self.scene.bcalib))
        self.dlg.leUnit.setText(str(self.scene.unit))

    def prepareplot(self):
        """ Reads in default values for selected layer before plotting"""
        layername = self.dlg.qgLayer.currentText()
        fieldname = self.dlg.qgField.currentText()
        s = QgsSettings()
        self.scene.acalib = float(
            s.value(self.pluginname + "/" + layername + "_" + fieldname + "_a",
                    s.value(self.pluginname + "/defaulta", 1)))
        self.scene.bcalib = float(
            s.value(self.pluginname + "/" + layername + "_" + fieldname + "_b",
                    s.value(self.pluginname + "/defaultb", 0)))
        self.scene.unit = s.value(
            self.pluginname + "/" + layername + "_" + fieldname + "_unit",
            s.value(self.pluginname + "/defaultunit", 'Ch'))

        self.dlg.leA.setText(str(self.scene.acalib))
        self.dlg.leB.setText(str(self.scene.bcalib))
        self.dlg.leUnit.setText(str(self.scene.unit))
        self.findselected()

    def findselected(self):
        """ Is being run when points have been selected. Makes a sum spectra from selected points"""
        layer = self.dlg.qgLayer.currentLayer()
        if layer == None:
            return
        sels = layer.selectedFeatures(
        )  # The selected features in the active (from this plugin's point of view) layer
        n = len(sels)
        if n > 0:
            #self.iface.messageBar().pushMessage(
            #        "Drawing spectra", "Integrated over {} measurements".format(str(n)),
            #        level=Qgis.Success, duration=3)
            fieldname = self.dlg.qgField.currentText()
            # DONE: Rewrite to make it possible to read in a spectra as a string of comma-separated numbers
            if fieldname == '' or fieldname == None:
                return  # Invalid fieldname, probably not selected yet
            stringspec = isinstance(sels[0][fieldname], str)
            stringspec = stringspec and (sels[0][fieldname].find(',') != -1)
            if isinstance(sels[0][fieldname], list) or stringspec:
                # Only draw if a list field is selected
                sumspectre = None
                for sel in sels:
                    spectre = sel[fieldname]
                    if stringspec:
                        vals = spectre.split(',')
                        spectre = list(map(int, vals))
                    del spectre[
                        -1]  # To get rid of last channel i.e. cosmic from RSI-spectra
                    # TODO: customable removal of channels at top and/or bottom
                    if sumspectre == None:
                        sumspectre = spectre
                    else:
                        sumspectre = list(map(add, spectre, sumspectre))
                self.view.spectreval = sumspectre
                self.view.n = n
                self.drawspectra()
            else:
                self.iface.messageBar().pushMessage(
                    "Error",
                    "Use an array field or a comma separated string",
                    level=Qgis.Warning,
                    duration=3)

    def spectreToClipboard(self):
        """ Copies the channel values to the clipboard as a comma separated string"""
        clipboard = QApplication.clipboard()
        text = ",".join(str(x) for x in self.view.spectreval)
        clipboard.setText(text)

        # TODO: Make a graphical copy

    def saveCalibration(self):
        """ Saves the calibration data """
        layername = self.dlg.qgLayer.currentText()
        fieldname = self.dlg.qgField.currentText()
        s = QgsSettings()
        s.setValue(self.pluginname + "/" + layername + "_" + fieldname + "_a",
                   self.scene.acalib)
        s.setValue(self.pluginname + "/" + layername + "_" + fieldname + "_b",
                   self.scene.bcalib)
        s.setValue(
            self.pluginname + "/" + layername + "_" + fieldname + "_unit",
            self.scene.unit)

    def run(self):
        """Run method that loads and starts the plugin"""

        if not self.pluginIsActive:
            self.pluginIsActive = True
            self.scene = QGraphicsScene()
            # Storing the spectra to be able to read out values later on
            # Setting the values storing line and text shown when the mouse button is clicked
            self.scene.crdtext = None
            self.scene.markerline = None
            self.scene.left = None
            # TODO: The four next settings to be user-settable
            self.tickinterval = 100
            s = QgsSettings()
            self.scene.acalib = s.value(self.pluginname + "/defaulta", 1)
            self.scene.bcalib = s.value(self.pluginname + "/defaultb", 0)
            self.scene.unit = s.value(self.pluginname + "/defaultunit", "Ch")
            self.dlg.leA.setText(str(self.scene.acalib))
            self.dlg.leB.setText(str(self.scene.bcalib))
            self.dlg.leUnit.setText(str(self.scene.unit))
            showch = False  # Set to True to show channel values
            if showch:
                self.scene.unit = 'Ch'
                self.scene.acalib = 1
                self.scene.bcalib = 0
            self.view.setScene(self.scene)
            self.scene.setSceneRect(0, 0, 1200, 300)
            # Replotting spectre when a new selection is made
            self.iface.mapCanvas().selectionChanged.connect(self.findselected)
            # Listing layers
            # DONE: Only list vector layers
            # DONE: Repopulate when layers are added or removed
            # DONE both by using qgisWidget
            self.dlg.pBCopy.clicked.connect(self.spectreToClipboard)
            self.dlg.pBUseDefault.clicked.connect(self.usedefault)
            self.dlg.pBSaveCalib.clicked.connect(self.saveCalibration)
            self.dlg.pBSave.clicked.connect(self.view.saveImage)

            # connect to provide cleanup on closing of dockwidget
            self.dlg.closingPlugin.connect(self.onClosePlugin)
            # show the dockwidget
            self.iface.mainWindow().addDockWidget(Qt.BottomDockWidgetArea,
                                                  self.dlg)
            self.dlg.show()
            self.dlg.cbLog.stateChanged.connect(self.findselected)
            self.dlg.cbDefault.stateChanged.connect(self.setdefault)
            self.dlg.qgField.currentIndexChanged['QString'].connect(
                self.prepareplot)
            self.dlg.qgLayer.currentIndexChanged['QString'].connect(
                self.prepareplot)
            self.dlg.leA.textChanged['QString'].connect(self.updatecalib)
            self.dlg.leB.textChanged['QString'].connect(self.updatecalib)
            self.findselected()
Ejemplo n.º 25
0
    def drawForeground(self, painter, rect):
        #print "BoreHoleScene.drawForeground"
        if self.__redraw:
            with self.__project.connect() as con:
                cur = con.cursor()
                self.__redraw = False
                self.clear()
                fm = painter.fontMetrics()

                if self.__id is None:
                    QGraphicsScene.drawForeground(self, painter, rect)
                    return

                cur.execute(
                    "SELECT geom FROM albion.hole WHERE id='{}'".format(
                        self.__id))
                res = cur.fetchone()

                if not res:
                    QGraphicsScene.drawForeground(self, painter, rect)
                    return

                hole = wkb.loads(bytes.fromhex(res[0]))
                line = [p[2] for p in hole.coords]
                tick_width = 20
                spacing = 5
                tick_text_offset = -10
                tabs = [50, 75, 150, 250, 350, 400, 500]
                zmin, zmax = min(line), max(line)
                zpmin, zpmax = 0, ((zmin - zmax) - 5) / self.m_per_pixel

                text = self.addText(self.__id)
                text.setPos(tabs[1], -5 * fm.height())

                label = 'Depth [m]'
                text = self.addText(label)
                text.setRotation(-90)
                text.setPos(0, 0)
                text = self.addText('Formation')
                text.setPos(tabs[1], -3 * fm.height())
                text = self.addText('Radiometry')
                text.setPos(tabs[2], -3 * fm.height())
                text = self.addText('Resistivity')
                text.setPos(tabs[3], -3 * fm.height())
                text = self.addText('Mineralization')
                text.setPos(tabs[4], -3 * fm.height())

                top = zpmin - 3 * fm.height()
                pen = QPen()
                pen.setWidth(3)
                for tab in [tabs[1], tabs[2], tabs[3], tabs[4], tabs[6]]:
                    self.addLine(tab, top, tab, zpmax, pen)
                self.addLine(tabs[1], zpmin, tabs[-1], zpmin, pen)
                self.addLine(tabs[1], zpmax, tabs[-1], zpmax, pen)
                self.addLine(tabs[1], top, tabs[-1], top, pen)

                # depth ticks
                for z in range(0, int(-(zmax - zmin) - 5), -10):
                    text = "% 4.0f" % (max(line) + z)
                    z /= self.m_per_pixel
                    width = fm.width(text)
                    text = self.addText(text)
                    text.setPos(tabs[0] - width - spacing,
                                tick_text_offset + int(z))
                    self.addLine(tabs[0], z, tabs[1], z)
                    self.addLine(tabs[2], z, tabs[4], z)

                #res = cur.execute("SELECT AsText(GEOMETRY), code FROM lithologies WHERE forage={}".format(self.__id)).fetchall()

                ## litho image
                #for geom, code in res:
                #    line = [(float(pt.split()[2])-z_tube+h_tube_sol)
                #            for pt in geom.replace('LINESTRING Z(','').replace(')','').split(',')]
                #    z_start = line[0]/self.m_per_pixel
                #    z_end = line[-1]/self.m_per_pixel
                #    brush = QBrush()
                #    brush.setTextureImage(self.texture(code))
                #    self.addRect(tabs[1], z_start, tabs[2]-tabs[1], z_end-z_start, brush=brush)

                ## bar diagram grid
                #for i in range(1, 10):
                #    pen.setWidth(1 if i != 5 else 2)
                #    x = tabs[3]+(tabs[4]-tabs[3])*float(i)/10
                #    self.addLine(x, zmin, x, zmax, pen)

                # formation color
                cur.execute(
                    "SELECT geom, code FROM albion.formation WHERE hole_id='{}'"
                    .format(self.__id))

                for geom, code in cur.fetchall():
                    line = [
                        p[2] for p in wkb.loads(bytes.fromhex(geom)).coords
                    ]
                    z_start = (line[0] - zmax) / self.m_per_pixel
                    z_end = (line[-1] - zmax) / self.m_per_pixel
                    brush = QBrush()
                    brush.setStyle(Qt.SolidPattern)
                    brush.setColor(self.formation_color(code))
                    self.addRect(tabs[1],
                                 z_start,
                                 tabs[2] - tabs[1],
                                 z_end - z_start,
                                 brush=brush)
                    #width = fm.width(code);
                    #text = self.addText(code)
                    #text.setPos(tabs[2]+spacing, tick_text_offset+int(.5*(z_start+z_end)))
                    self.addLine(tabs[2], z_start, tabs[2], z_start)
                    self.addLine(tabs[2], z_end, tabs[2], z_end)

                # radiometry diagram
                cur.execute(
                    "SELECT max(gamma) FROM albion.radiometry WHERE hole_id='{}'"
                    .format(self.__id))
                gamma_max = cur.fetchone()[0]
                cur.execute(
                    "SELECT geom, gamma FROM albion.radiometry WHERE hole_id='{}' AND gamma>=0"
                    .format(self.__id))
                for geom, gamma in cur.fetchall():
                    line = [
                        p[2] for p in wkb.loads(bytes.fromhex(geom)).coords
                    ]
                    z_start = (line[0] - zmax) / self.m_per_pixel
                    z_end = (line[-1] - zmax) / self.m_per_pixel
                    brush = QBrush()
                    brush.setStyle(Qt.SolidPattern)
                    brush.setColor(QColor(55, 51, 149))
                    self.addRect(tabs[2],
                                 z_start,
                                 (tabs[3] - tabs[2]) * gamma / gamma_max,
                                 z_end - z_start,
                                 pen=QPen(Qt.NoPen),
                                 brush=brush)

                # resistivity diagram
                cur.execute(
                    "SELECT max(rho) FROM albion.resistivity WHERE hole_id='{}'"
                    .format(self.__id))
                rho_max = cur.fetchone()[0]
                cur.execute(
                    "SELECT geom, rho FROM albion.resistivity WHERE hole_id='{}' AND rho>=0"
                    .format(self.__id))
                for geom, rho in cur.fetchall():
                    line = [
                        p[2] for p in wkb.loads(bytes.fromhex(geom)).coords
                    ]
                    z_start = (line[0] - zmax) / self.m_per_pixel
                    z_end = (line[-1] - zmax) / self.m_per_pixel
                    brush = QBrush()
                    brush.setStyle(Qt.SolidPattern)
                    brush.setColor(QColor(155, 51, 49))
                    self.addRect(tabs[3],
                                 z_start, (tabs[4] - tabs[3]) * rho / rho_max,
                                 z_end - z_start,
                                 pen=QPen(Qt.NoPen),
                                 brush=brush)

                # mineralization
                cur.execute(
                    "SELECT geom, oc, accu, grade FROM albion.mineralization WHERE hole_id='{}'"
                    .format(self.__id))

                for geom, oc, accu, grade in cur.fetchall():
                    line = [
                        p[2] for p in wkb.loads(bytes.fromhex(geom)).coords
                    ]
                    z_start = (line[0] - zmax) / self.m_per_pixel
                    z_end = (line[-1] - zmax) / self.m_per_pixel
                    brush = QBrush()
                    brush.setStyle(Qt.SolidPattern)
                    brush.setColor(QColor(250, 250, 50))
                    self.addRect(tabs[4],
                                 z_start,
                                 tabs[5] - tabs[4],
                                 z_end - z_start,
                                 brush=brush)
                    txt = "oc=" + str(oc) + "\naccu=" + str(
                        accu) + "\ngrade=" + str(grade)
                    width = fm.width(txt)
                    text = self.addText(txt)
                    text.setPos(
                        tabs[5] + spacing,
                        -int(1.5 * fm.height()) + int(.5 * (z_start + z_end)))
                    self.addLine(tabs[4], z_start, tabs[6], z_start)
                    self.addLine(tabs[4], z_end, tabs[6], z_end)

                self.setSceneRect(self.itemsBoundingRect())

        QGraphicsScene.drawForeground(self, painter, rect)