8

I'm trying to change the color ramp for a raster layer using PyQGIS.

What I have works, but the layer doesn't redraw. However, if I open the layer properties and click "Apply", the map redraws.

I've called both triggerRepaint and iface.mapCanvas().refresh(), both which are not producing the expected result.

plugin

from qgis.PyQt import QtWidgets, QtGui, QtCore

# do this otherwise you have to constantly declare the class you want
# to use
import qgis

class MyTool:

    def __init__(self, iface):
        self.iface = iface

        self.canvas = self.iface.mapCanvas()

    def initGui(self):
        self.action = QtWidgets.QAction("My Tool", self.iface.mainWindow())
        self.action.setObjectName("MyToolAction")
        self.action.setWhatsThis("Configuration for My Tool")
        self.action.setStatusTip("This is status tip")
        self.action.triggered.connect(self.run)

        self.iface.addToolBarIcon(self.action)
        self.iface.addPluginToMenu("&My Tool", self.action)

    def unload(self):
        self.iface.removePluginMenu("&My Tool", self.action)
        self.iface.removeToolBarIcon(self.action)

    def run(self):
        # not my actual file, but one which seems to reproduce the problem
        path = "/vsicurl/http://oin-hotosm.s3.amazonaws.com/59d33df023c8440011d7b26d/0/b378087a-c2a5-43a0-abec-71fcfb051150.tif"
        layer_intensity = self.iface.addRasterLayer(path, 'intensity')

        color_ramp = qgis.core.QgsStyle().defaultStyle().colorRamp('Viridis')
        ramp_shader = qgis.core.QgsColorRampShader(1, 255, color_ramp)

        raster_shader = qgis.core.QgsRasterShader()
        raster_shader.setRasterShaderFunction(ramp_shader)

        renderer = qgis.core.QgsSingleBandPseudoColorRenderer(layer_intensity.dataProvider(), 1, raster_shader)

        layer_intensity.setRenderer(renderer)
        layer_intensity.triggerRepaint()
        self.iface.mapCanvas().refresh()

metadata

[general]
name=My Tool
[email protected]
author=dood
qgisMinimumVersion=3.10
description=My Tool
about=Software for stuff
version=version 0.1
repository=http://www.itopen.it/repo

experimental=True

1 Answer 1

7

I think you are just missing one line needed to create classifications from the color ramp:

ramp_shader.classifyColorRamp()

So, your modified run() method would look like:

def run(self):
    # not my actual file, but one which seems to reproduce the problem
    path = "/vsicurl/http://oin-hotosm.s3.amazonaws.com/59d33df023c8440011d7b26d/0/b378087a-c2a5-43a0-abec-71fcfb051150.tif"
    layer_intensity = self.iface.addRasterLayer(path, 'intensity')

    color_ramp = qgis.core.QgsStyle().defaultStyle().colorRamp('Viridis')
    ramp_shader = qgis.core.QgsColorRampShader(1, 255, color_ramp)
    ramp_shader.classifyColorRamp()# Add this line
    raster_shader = qgis.core.QgsRasterShader()
    raster_shader.setRasterShaderFunction(ramp_shader)

    renderer = qgis.core.QgsSingleBandPseudoColorRenderer(layer_intensity.dataProvider(), 1, raster_shader)

    layer_intensity.setRenderer(renderer)
    layer_intensity.triggerRepaint()

When I copy the logic from the method above and run directly in the QGIS Python console (after removing references to self) I get the following result:

enter image description here

A broader example involves retrieving the actual max and min values from the raster using the bandStatistics() method of QgsRasterDataProvider and passing them to the QgsColorRampShader constructor:

rl = iface.activeLayer()
prov = rl.dataProvider()
stats = prov.bandStatistics(1, QgsRasterBandStats.All, rl.extent(), 0)
min = stats.minimumValue
max = stats.maximumValue
color_ramp = QgsStyle().defaultStyle().colorRamp('Viridis')
ramp_shader = QgsColorRampShader(min, max, color_ramp)
ramp_shader.classifyColorRamp()# Add this line
raster_shader = QgsRasterShader()
raster_shader.setRasterShaderFunction(ramp_shader)
renderer = QgsSingleBandPseudoColorRenderer(rl.dataProvider(), 1, raster_shader)
rl.setRenderer(renderer)
rl.triggerRepaint()

Results on a test DEM layer:

enter image description here

1
  • That indeed works and thank you for that. Any idea why it works? The docs are rather redundant; the classifyColorRamp method classifies the color ramp shader. Commented Oct 21, 2021 at 14:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.