4

I am loading a raster file with many bands to my QGIS project.

layer = self.iface.addRasterLayer(raster_file_path, baseName="foo")

By default, QGIS chooses to set its symbology to "Multiband color" which makes no sense for my purposes. Instead, I would like it to be loaded as "Singleband pseudocolor".

How can I achieve this? Maybe I have to use a QgsRasterLayer and QgsProject.addMapLayer() instead?


Manually writing all the code for a QgsSingleBandPseudoColorRenderer is definitely not what I am looking for nor would setting a previously created style file be a solution. QGIS already has code to automatically style a single band using a pseudocolor style and that is what I would like to trigger.

2
  • Obviously not exactly answering the question, but what about just loading a style file with your preferred saved style? Commented Nov 3, 2023 at 0:09
  • Would that make QGIS still automatically determine the min and max values for the range and calculate classes? I would expect it to use pre-set classes from the style and that is not what I am looking for. Commented Nov 3, 2023 at 7:24

2 Answers 2

3

This is a pretty good tutorial on how to do what you want.

edit: this is also how the pyqgis documentation says it should be done documentation

raster_file_path = "path/to/raster.ext"
name_in_legend = "foo"
band_to_use = 1
color_bottom_of_ramp = QColor(0, 0, 0)  # Black
color_top_of_ramp = QColor(255, 0, 0)  # Red

# Load raster from file
raster_layer = QgsRasterLayer(raster_file_path, baseName=name_in_legend)
dp_raster_layer = raster_layer.dataProvider()

# Gets min/max of a band in raster
stats = dp_raster_layer.bandStatistics(band_to_use, QgsRasterBandStats.All)
min_v = stats.minimumValue
max_v = stats.maximumValue

# Create shader function
fnc = QgsColorRampShader()
fnc.setColorRampType(QgsColorRampShader.Interpolated)

# Set min color and max color for the color ramp
lst = [
    QgsColorRampShader.ColorRampItem(min_v, color_bottom_of_ramp),
    QgsColorRampShader.ColorRampItem(max_v, color_top_of_ramp)
]
fnc.setColorRampItemList(lst)

# Create shader with the configured shader function
shader = QgsRasterShader()
shader.setRasterShaderFunction(fnc)

# Create the renderer with the right symbology
renderer = QgsSingleBandPseudoColorRenderer(dp_raster_layer, band_to_use, shader)
raster_layer.setRenderer(renderer)

# Add raster to legend
QgsProject.instance().addMapLayer(raster_layer)

Edit based on edited post:

I just checked the c++ code for what QGIS does upon changing renderer with the GUI and it does about the same as above except in c++ (and even more complicated).

As for how to trigger it, you just can't it seems according to the pyqgis documentation since there are no Python bindings available for it:

QgsApplication::rasterRendererRegistry() QgsRasterRendererRegistry::defaultRendererForDrawingStyle()

The QgsRasterRendererRegistry class is where the call to create the "default" renderer is made from the gui c++ code.

And trying to follow all the chain of gui calls to trigger it manually (if even possible) would be even more complicated then simply duplicating the creation of the renderer and setting it up as I have done above with the pyqgis calls that are available.

6
  • 1
    Thank you, but I would really like to avoid writing complex code for this. And this code is quite different from what QGIS does by itself when one switches to a pseudocolor symbology. Commented Nov 3, 2023 at 17:30
  • Actually it's pretty much what it is supposed to do I believe: set min/max and set color ramp. You might be able to skip setting the colors and get the default values. BTW I tried just setting the right renderer without setting the rest but it doesn't work you have to open properties of layer and apply the symbology otherwise it doesn't appear
    – Kalak
    Commented Nov 3, 2023 at 23:59
  • Which is not an issue with the multiband color renderer. So it could be a qgis issue.
    – Kalak
    Commented Nov 4, 2023 at 0:01
  • Also, doing a 180 on your question after someone answers the question exactly as it is stated is really not nice and a waste of time for everyone involved.
    – Kalak
    Commented Nov 8, 2023 at 9:04
  • I am really sorry if you perceived it as that. To me my question was clearly not after "here is how you construct all the renderer stuff manually" but after a simple flag or convenience helper function that might be available in QGIS already. Otherwise I would have asked about "styling" such layer, not "loading". I should have been more explicit right away. Commented Nov 8, 2023 at 10:24
2

I found a solution to switch the renderer to a QgsSingleBandPseudoColorRenderer in a single line with default values by using the class widget QgsSingleBandPseudoColorRendererWidget:

raster_layer = QgsRasterLayer("path/to/raster.ext", baseName="foo")

raster_layer.setRenderer(QgsSingleBandPseudoColorRendererWidget(raster_layer).renderer())

QgsProject.instance().addMapLayer(raster_layer)

This basically corresponds to the call made when changing the render type through the properties GUI.

0

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.