2

In Qgis desktop application there is a button named "Classify" to compute the values in singleband pseudocolor style. Highlighted in yellow in the following image.

layer properties window

How can I get those values using python?

1
  • Welcome to gis.stackexchange! Please note that a good question on this site is expected to show some degree of research on your part, i.e. what you have tried and - if applicable - code so far. For more info, you can check our faq.
    – underdark
    Mar 28, 2017 at 17:51

2 Answers 2

5

I don't know which is color interpolation method of QGIS but, as first approximation, it can be taken advantage of 'defaultStyle' in QgsStyleV2 class for creating a color list for a QgsColorRampShader "defined" by user. For this reason is possible to do that in QGIS 2.x.

In your case, I can observe that default ramp is named 'RdYlGn'. So, in my case, I used a DEM raster for classifying it with 5 classes in this ramp. Max and Min values are taken by using methods of QgsRasterDataProvider class.

Interpolated color for these five classes are in:

>>>QgsStyleV2().defaultStyle().colorRamp('RdYlGn').properties()
{u'color1': u'215,25,28,255', u'discrete': u'0', u'color2': u'26,150,65,255', u'stops': u'0.25;253,174,97,255:0.5;255,255,192,255:0.75;166,217,106,255'}

Complete code to get a QgsSingleBandPseudoColorRenderer with 5 classes in this ramp is:

from qgis.PyQt.QtGui import QColor
import re

layer = iface.activeLayer()
renderer = layer.renderer()
provider = layer.dataProvider()

band = renderer.usesBands()

min = provider.bandStatistics(band[0], QgsRasterBandStats.All).minimumValue
max = provider.bandStatistics(band[0], QgsRasterBandStats.All).maximumValue

print "min: {:.1f}, max: {:.1f}".format(min, max)

myStyle = QgsStyleV2().defaultStyle()

ramp_names = myStyle.colorRampNames()

dict = {}

for i, name in enumerate(ramp_names):
    dict[ramp_names[i]] = i 

print 'RdYlGn ramp is number:', dict['RdYlGn']

ramp = myStyle.colorRamp('RdYlGn')  #RdYlGn ramp
print ramp_names[dict['RdYlGn']]

rp = ramp.properties()
print rp

#To set an interpolated color RdYlGn ramp shader with five classes
number_classes = 5

interval = (max - min)/(number_classes -1 )
print "class interval: ", interval

#classes
sum = min
classes = []

for i in range(number_classes):
    tmp = int(round(sum, 0))
    print 'class {:d}: {:d}'.format(i+1, tmp)
    classes.append(tmp)
    sum += interval

print "classes: ", classes

c1 = [ int(element) for element in rp['color1'].split(',') ]
stops = [ element for element in re.split('[,;:]', rp['stops']) ]
c2 = [ int(element) for element in rp['color2'].split(',') ]

color_list = [ QgsColorRampShader.ColorRampItem(classes[0], QColor(c1[0],c1[1],c1[2], c1[3])),
               QgsColorRampShader.ColorRampItem(classes[1], QColor(int(stops[1]),int(stops[2]),int(stops[3]),int(stops[4]))),
               QgsColorRampShader.ColorRampItem(classes[2], QColor(int(stops[6]),int(stops[7]),int(stops[8]),int(stops[9]))),
               QgsColorRampShader.ColorRampItem(classes[3], QColor(int(stops[11]),int(stops[12]),int(stops[13]),int(stops[14]))),
               QgsColorRampShader.ColorRampItem(classes[4], QColor(c2[0],c2[1],c2[2], c2[3])) ]

myRasterShader = QgsRasterShader()
myColorRamp = QgsColorRampShader()

myColorRamp.setColorRampItemList(color_list)
myColorRamp.setColorRampType(QgsColorRampShader.INTERPOLATED)
myRasterShader.setRasterShaderFunction(myColorRamp)

myPseudoRenderer = QgsSingleBandPseudoColorRenderer(layer.dataProvider(), 1,  myRasterShader)

layer.setRenderer(myPseudoRenderer)

layer.triggerRepaint()

After running the code with next raster (QgsSingleBandGrayRenderer object):

enter image description here

I got:

enter image description here

It works.

Editing Note:

By using linear interpolation or python module colour is possible to get wider ramps and more than 5 classes. So, code is more concise.

from qgis.PyQt.QtGui import QColor
import re
from colour import Color

def linear_color_interpolation(c1, c2, t):

    r = int(c1.red() + (c2.red() - c1.red()) * t)
    g = int(c1.green() + (c2.green() - c1.green()) * t)
    b = int(c1.blue() + (c2.blue() - c1.blue()) * t)

    return QColor(r, g, b)

layer = iface.activeLayer()
renderer = layer.renderer()
provider = layer.dataProvider()

band = renderer.usesBands()

min = provider.bandStatistics(band[0], QgsRasterBandStats.All).minimumValue
max = provider.bandStatistics(band[0], QgsRasterBandStats.All).maximumValue

#To set an interpolated color RdYlGn ramp shader with five classes
number_classes = 10

interval = (max - min)/(number_classes -1 )

#classes
sum = min
classes = []

for i in range(number_classes):
    tmp = int(round(sum, 0))
    classes.append(tmp)
    sum += interval

t_list = []

init = 0

for i in range(number_classes):
    t_list.append(init)
    init += 1./(number_classes-1)

#c1 = QColor(215,25,28,255)
#c2 = QColor(26,150,65,255)

c1 = QColor('blue')
c2 = QColor('yellow')

colors2 = list(Color(c1.name()).range_to(Color(c2.name()), number_classes))
colors3 = [ QColor(element.hex) 
            for element in colors2 ]

colors = [ linear_color_interpolation(c1, c2, t) for t in t_list ]

color_list = [ QgsColorRampShader.ColorRampItem(classes[i], colors3[i])  for i in range(number_classes) ]

myRasterShader = QgsRasterShader()
myColorRamp = QgsColorRampShader()

myColorRamp.setColorRampItemList(color_list)
myColorRamp.setColorRampType(QgsColorRampShader.INTERPOLATED)
myRasterShader.setRasterShaderFunction(myColorRamp)

myPseudoRenderer = QgsSingleBandPseudoColorRenderer(\
    layer.dataProvider(), 1,  myRasterShader)

layer.setRenderer(myPseudoRenderer)

layer.triggerRepaint()

After running it with colour module (c1:blue, c2:yellow) and 10 classes:

enter image description here

and with linear interpolation:

enter image description here

Obviously, colour module doesn't use linear interpolation (simplest interpolation method).

1
  • thanks for answering but I am working on a non gui project and I need values like 0.0341,0.168...which are being calculated by software. Mar 28, 2017 at 11:58
4

It's not possible in QGIS 2.x. That logic is unfortunately tied up in parts of the code which isn't exposed to the Python API.

This has changed in QGIS 3.0, and you can use QgsSingleBandPseudoColorRenderer.createShader:

http://qgis.org/api/classQgsSingleBandPseudoColorRenderer.html#a1778d3596d8d46451fe466bf2b657c60

1
  • How can I get those color values like 0.034,0.168...etc as this method is returning nothing. Mar 28, 2017 at 11:54

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