def _test(is_sidecar):

            QgsProject.instance().removeAllMapLayers()

            tmp_dir = QTemporaryDir()
            shutil.copy(os.path.join(os.path.dirname(
                __file__), 'data', 'raster-palette.tif'), tmp_dir.path())

            rat_path = os.path.join(
                tmp_dir.path(), 'raster-palette.tif' + ('.vat.dbf' if is_sidecar else '.aux.xml'))
            self.assertFalse(os.path.exists(rat_path))

            raster_layer = QgsRasterLayer(os.path.join(tmp_dir.path(), 'raster-palette.tif'), 'rat_test', 'gdal')
            QgsProject.instance().addMapLayer(raster_layer)

            self.assertTrue(raster_layer.isValid())
            self.assertFalse(can_create_rat(raster_layer))
            self.assertFalse(has_rat(raster_layer))

            band = 1

            # Set renderer
            ramp = QgsRandomColorRamp()
            renderer = QgsPalettedRasterRenderer(
                raster_layer.dataProvider(), 1, QgsPalettedRasterRenderer.classDataFromRaster(raster_layer.dataProvider(), band, ramp))
            raster_layer.setRenderer(renderer)
            self.assertTrue(can_create_rat(raster_layer))

            rat = create_rat_from_raster(raster_layer, is_sidecar, rat_path)
            self.assertTrue(rat.isValid())

            self.assertEqual(rat.data['Count'], [78, 176, 52])
            self.assertEqual(rat.data['Value'], [
                            2.257495271713565, 7.037407804695962, 270.4551067154352])
            self.assertEqual(rat.data['A'], [255, 255, 255])
            self.assertNotEqual(rat.data['R'], [0, 0, 0])

            self.assertTrue(rat.save(band))
            self.assertTrue(os.path.exists(rat_path))

            QgsProject.instance().removeMapLayers([raster_layer.id()])
            del (raster_layer)

            self.assertTrue(os.path.exists(rat_path))
            QgsApplication.processEvents()

            # Reload and check
            raster_layer = QgsRasterLayer(os.path.join(
                tmp_dir.path(), 'raster-palette.tif'), 'rat_test', 'gdal')
            self.assertTrue(raster_layer.isValid())
            self.assertFalse(can_create_rat(raster_layer))
            self.assertTrue(has_rat(raster_layer), rat_path)

            os.unlink(rat_path)
Exemplo n.º 2
0
def mkRendererPalettedGnYlRd(layer):
    pr = layer.dataProvider()
    # colorRamp = getColorBrewColorRampGnYlRd()
    # colorRamp = getPresetGnYlRd()
    # colorRamp = QgsGradientColorRamp(color1=redCol,color2=greenCol)
    # colorRamp = QgsCptCityColorRamp(schemeName='cb/div/GnYlRd_',variantName='11')
    colorRamp = getGradientColorRampRdYlGn()
    classData = QgsPalettedRasterRenderer.classDataFromRaster(pr,
                                                              1,
                                                              ramp=colorRamp)
    renderer = QgsPalettedRasterRenderer(pr, 1, classes=classData)
    return renderer
Exemplo n.º 3
0
def raster_apply_unique_value_renderer(raster_layer,
                                       band_num=1,
                                       n_decimals=0,
                                       color_ramp='',
                                       invert=False):
    """
    Apply a random colour to each each unique value for a raster band.

    In some case the unique values are floating, n_decimals allows these to be rounded for display

    Args:
        raster_layer (QgsRasterLayer): input raster layer
        band_num (int):    the band number used to determine unique values
        n_decimals (int):  number of decimals to round values to
        invert (bool) : Invert the color ramp before applying - Not implemented
    """
    qgsStyles = QgsStyle().defaultStyle()
    # check to see if the colour ramp is installed
    if color_ramp != '' and color_ramp not in qgsStyles.colorRampNames():
        raise ValueError(
            'PAT symbology does not exist. See user manual for install instructions'
        )

    if color_ramp == '':
        ramp = QgsRandomColorRamp()
    else:
        # get an existing color ramp
        ramp = qgsStyles.colorRamp(color_ramp)

    # generate a list of unique values and their colours.
    uniq_classes = QgsPalettedRasterRenderer.classDataFromRaster(
        raster_layer.dataProvider(), band_num, ramp)

    # Create the renderer
    renderer = QgsPalettedRasterRenderer(raster_layer.dataProvider(), band_num,
                                         uniq_classes)

    # assign the renderer to the raster layer:
    raster_layer.setRenderer(renderer)

    # refresh
    raster_layer.triggerRepaint()
Exemplo n.º 4
0
    def testPalettedClassDataFromLayer(self):
        # no layer
        classes = QgsPalettedRasterRenderer.classDataFromRaster(None, 1)
        self.assertFalse(classes)

        # 10 class layer
        path = os.path.join(unitTestDataPath('raster'),
                            'with_color_table.tif')
        info = QFileInfo(path)
        base_name = info.baseName()
        layer10 = QgsRasterLayer(path, base_name)
        classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1)
        self.assertEqual(len(classes), 10)
        self.assertEqual(classes[0].value, 1)
        self.assertEqual(classes[0].label, '1')
        self.assertEqual(classes[1].value, 2)
        self.assertEqual(classes[1].label, '2')
        self.assertEqual(classes[2].value, 3)
        self.assertEqual(classes[2].label, '3')
        self.assertEqual(classes[3].value, 4)
        self.assertEqual(classes[3].label, '4')
        self.assertEqual(classes[4].value, 5)
        self.assertEqual(classes[4].label, '5')
        self.assertEqual(classes[5].value, 6)
        self.assertEqual(classes[5].label, '6')
        self.assertEqual(classes[6].value, 7)
        self.assertEqual(classes[6].label, '7')
        self.assertEqual(classes[7].value, 8)
        self.assertEqual(classes[7].label, '8')
        self.assertEqual(classes[8].value, 9)
        self.assertEqual(classes[8].label, '9')
        self.assertEqual(classes[9].value, 10)
        self.assertEqual(classes[9].label, '10')

        # bad band
        self.assertFalse(QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 10101010))

        # with ramp
        r = QgsGradientColorRamp(QColor(200, 0, 0, 100), QColor(0, 200, 0, 200))
        classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1, r)
        self.assertEqual(len(classes), 10)
        self.assertEqual(classes[0].color.name(), '#c80000')
        self.assertEqual(classes[1].color.name(), '#b21600')
        self.assertEqual(classes[2].color.name(), '#9c2c00')
        self.assertEqual(classes[3].color.name(), '#854200')
        self.assertEqual(classes[4].color.name(), '#6f5900')
        self.assertEqual(classes[5].color.name(), '#596f00')
        self.assertEqual(classes[6].color.name(), '#428500')
        self.assertEqual(classes[7].color.name(), '#2c9c00')
        self.assertEqual(classes[8].color.name(), '#16b200')
        self.assertEqual(classes[9].color.name(), '#00c800')

        # 30 class layer
        path = os.path.join(unitTestDataPath('raster'),
                            'unique_1.tif')
        info = QFileInfo(path)
        base_name = info.baseName()
        layer10 = QgsRasterLayer(path, base_name)
        classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1)
        self.assertEqual(len(classes), 30)
        expected = [11, 21, 22, 24, 31, 82, 2002, 2004, 2014, 2019, 2027, 2029, 2030, 2080, 2081, 2082, 2088, 2092, 2097, 2098, 2099, 2105, 2108, 2110, 2114, 2118, 2126, 2152, 2184, 2220]
        self.assertEqual([c.value for c in classes], expected)

        # bad layer
        path = os.path.join(unitTestDataPath('raster'),
                            'hub13263.vrt')
        info = QFileInfo(path)
        base_name = info.baseName()
        layer = QgsRasterLayer(path, base_name)
        classes = QgsPalettedRasterRenderer.classDataFromRaster(layer.dataProvider(), 1)
        self.assertFalse(classes)
Exemplo n.º 5
0
    def testPalettedClassDataFromLayer(self):
        # no layer
        classes = QgsPalettedRasterRenderer.classDataFromRaster(None, 1)
        self.assertFalse(classes)

        # 10 class layer
        path = os.path.join(unitTestDataPath('raster'),
                            'with_color_table.tif')
        info = QFileInfo(path)
        base_name = info.baseName()
        layer10 = QgsRasterLayer(path, base_name)
        classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1)
        self.assertEqual(len(classes), 10)
        self.assertEqual(classes[0].value, 1)
        self.assertEqual(classes[0].label, '1')
        self.assertEqual(classes[1].value, 2)
        self.assertEqual(classes[1].label, '2')
        self.assertEqual(classes[2].value, 3)
        self.assertEqual(classes[2].label, '3')
        self.assertEqual(classes[3].value, 4)
        self.assertEqual(classes[3].label, '4')
        self.assertEqual(classes[4].value, 5)
        self.assertEqual(classes[4].label, '5')
        self.assertEqual(classes[5].value, 6)
        self.assertEqual(classes[5].label, '6')
        self.assertEqual(classes[6].value, 7)
        self.assertEqual(classes[6].label, '7')
        self.assertEqual(classes[7].value, 8)
        self.assertEqual(classes[7].label, '8')
        self.assertEqual(classes[8].value, 9)
        self.assertEqual(classes[8].label, '9')
        self.assertEqual(classes[9].value, 10)
        self.assertEqual(classes[9].label, '10')

        # bad band
        self.assertFalse(QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 10101010))

        # with ramp
        r = QgsGradientColorRamp(QColor(200, 0, 0, 100), QColor(0, 200, 0, 200))
        classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1, r)
        self.assertEqual(len(classes), 10)
        self.assertEqual(classes[0].color.name(), '#c80000')
        self.assertEqual(classes[1].color.name(), '#b21600')
        self.assertEqual(classes[2].color.name(), '#9c2c00')
        self.assertEqual(classes[3].color.name(), '#854200')
        self.assertEqual(classes[4].color.name(), '#6f5900')
        self.assertEqual(classes[5].color.name(), '#596f00')
        self.assertEqual(classes[6].color.name(), '#428500')
        self.assertEqual(classes[7].color.name(), '#2c9c00')
        self.assertEqual(classes[8].color.name(), '#16b200')
        self.assertEqual(classes[9].color.name(), '#00c800')

        # 30 class layer
        path = os.path.join(unitTestDataPath('raster'),
                            'unique_1.tif')
        info = QFileInfo(path)
        base_name = info.baseName()
        layer10 = QgsRasterLayer(path, base_name)
        classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1)
        self.assertEqual(len(classes), 30)
        expected = [11, 21, 22, 24, 31, 82, 2002, 2004, 2014, 2019, 2027, 2029, 2030, 2080, 2081, 2082, 2088, 2092, 2097, 2098, 2099, 2105, 2108, 2110, 2114, 2118, 2126, 2152, 2184, 2220]
        self.assertEqual([c.value for c in classes], expected)

        # bad layer
        path = os.path.join(unitTestDataPath('raster'),
                            'hub13263.vrt')
        info = QFileInfo(path)
        base_name = info.baseName()
        layer = QgsRasterLayer(path, base_name)
        classes = QgsPalettedRasterRenderer.classDataFromRaster(layer.dataProvider(), 1)
        self.assertFalse(classes)
Exemplo n.º 6
0
def rat_classify(raster_layer, band, rat, criteria, ramp=None, feedback=QgsRasterBlockFeedback()) -> list:
    """Classify a raster.

    Note: cannot use a custom shader function QgsColorRampShader subclass because it's lost in
          the clone stage of the renderer.

    :param raster_layer: the raster layer to classify
    :type raster_layer: QgsRasterLayer
    :param band: band number (1-based)
    :type band: int
    :param rat: the RAT data
    :type rat: dict
    :param criteria: key of the RAT to be used for labels
    :type criteria: str
    :param ramp: optional color ramp, defaults to QgsRandomColorRamp()
    :type ramp: QgsColorRamp, optional
    :param feedback: QGIS feedback object, defaults to QgsRasterBlockFeedback()
    :type feedback: QgsRasterBlockFeedback, optional
    :return: unique row indexes for legend items (1-based)
    :rtype: list
    """

    has_color = rat.has_color
    labels = rat.data[criteria]
    label_colors = {}
    unique_indexes = []

    # QGIS >= 3.18 for first element label
    if Qgis.QGIS_VERSION_INT >= 31800:
        base_legend_row_index = 1
    else:
        base_legend_row_index = 0

    if rat.thematic_type == gdal.GRTT_THEMATIC:

        # Use paletted
        rat_log('Using paletted renderer')

        value_column_name = rat.field_name(gdal.GFU_MinMax)
        values = rat.data[value_column_name]
        is_integer = isinstance(values[0], int)

        if ramp is None:
            ramp = QgsRandomColorRamp()
        classes = QgsPalettedRasterRenderer.classDataFromRaster(
            raster_layer.dataProvider(), band, ramp, feedback)

        row_index = base_legend_row_index
        for klass in classes:
            value = int(klass.value) if is_integer else klass.value
            try:
                index = values.index(value)
            except ValueError:   # NODATA
                rat_log(
                    f'Value {value} not found in RAT, assuming NODATA', Qgis.Warning)
                data_provider = raster_layer.dataProvider()
                if not data_provider.userNoDataValuesContains(band, value):
                    nodata = data_provider.userNoDataValues(band)
                    nodata_value = QgsRasterRange(value, value)
                    nodata.append(nodata_value)
                    data_provider.setUserNoDataValue(band, nodata)
                continue
            klass.label = str(labels[index])
            if klass.label not in label_colors:
                unique_indexes.append(row_index)
                if has_color:
                    label_colors[klass.label] = rat.data[RAT_COLOR_HEADER_NAME][index]
                else:
                    label_colors[klass.label] = klass.color
            klass.color = label_colors[klass.label]
            row_index += 1

        renderer = QgsPalettedRasterRenderer(
            raster_layer.dataProvider(), band, classes)

    else:  # ranges

        rat_log('Using singleband pseudocolor renderer')

        min_value_column = rat.field_name(gdal.GFU_Min)
        max_value_column = rat.field_name(gdal.GFU_Max)

        # Collect unique values and colors from criteria
        row_index = base_legend_row_index
        unique_labels = []
        for index in range(len(labels)):
            label = labels[index]
            if label not in unique_labels:
                unique_labels.append(label)
                unique_indexes.append(row_index)
                # Collect color
                if has_color:
                    label_colors[label] = rat.data[RAT_COLOR_HEADER_NAME][index]
            row_index += 1

        # Assign colors from random ramp
        if not has_color:
            ramp = QgsRandomColorRamp()
            ramp.setTotalColorCount(len(unique_labels))
            i = 0
            for index in unique_indexes:
                label_colors[labels[index]] = ramp.color(ramp.value(i))
                i += 1

        # Create values for the ramp
        # Collect colors for all classes
        colors = []
        for label in labels:
            colors.append(label_colors[label])

        ramp = QgsPresetSchemeColorRamp(colors)
        minValue = min(rat.data[min_value_column])
        maxValue = max(rat.data[max_value_column])

        assert minValue < maxValue, "Min Value must be lower than Max Value"

        shader = QgsRasterShader(minValue, maxValue)

        colorRampShaderFcn = QgsColorRampShader(
            minValue, maxValue, ramp)
        colorRampShaderFcn.setClip(True)
        colorRampShaderFcn.setColorRampType(QgsColorRampShader.Discrete)

        items = []
        row = 0
        for label in labels:
            items.append(QgsColorRampShader.ColorRampItem(
                rat.data[max_value_column][row], label_colors[label], label))
            row += 1

        colorRampShaderFcn.setColorRampItemList(items)
        try:  # for older QGIS
            colorRampShaderFcn.legendSettings().setUseContinuousLegend(False)
        except AttributeError:
            rat_log(
                'QgsColorRampShader.legendSettings().setUseContinuousLegend() is not supported on ths QGIS version.', Qgis.Warning)
        shader.setRasterShaderFunction(colorRampShaderFcn)
        renderer = QgsSingleBandPseudoColorRenderer(
            raster_layer.dataProvider(), band, shader)

    raster_layer.setRenderer(renderer)
    raster_layer.triggerRepaint()

    return unique_indexes