arcpy update raster layer symbology using RasterClassifyColorizer

576
2
Jump to solution
04-30-2023 11:45 PM
NickAtEsriAU
New Contributor II

Hello all,

I am trying to add a raster layer to a map in Pro (3.1) and then update the renderer to be RasterClassifyColorizer.  Once that is done, I then try to add a number breaks, update the upper bounds values of the breaks, labels and colors for the breaks.  Once done the legend for the raster looks right (right number of classes, right labels and colors) but the raster values seem to be allocated to the wrong classes.

The data is a floating point raster stored in a TIFF representing wind speed in meters per second.  

I am doing this via a cell in a Notebook.

The image below shows the rater added manually from the catalog, with a data range of 6.1 to 10.1

MicrosoftTeams-image.png

The following image shows the same raster added via the code, showing a large area under 2 meters a second wind speed, which shouldn't be possible:

MicrosoftTeams-image (1).png

Included is the code from the cell.  The pathway to the TIFF is stored in the variable "rdSaWSatX"

# Access the Project and Map objects to add the layers to
p = arcpy.mp.ArcGISProject("CURRENT")
m = p.listMaps("Map")[0]

# Study Area (AOI) Wind Speed raster and
# 1. Give it a "layer name" for display in the map
# 2. Make a raster layer with name
# 3. Access the layer object
# 4. Access the symbology object
# 5. Modify the symbology breaks, lables, and colors
# 6. Apply the modified symbology

# Layer name text
lyrnSaWSatX = f"Study area Wind Speed at {fltHubHeight}m"
# Create Raster Layer
lyrSaWSatX = arcpy.MakeRasterLayer_management(rdSaWSatX, lyrnSaWSatX)
# Add raster layer to the map
m.addLayer(lyrSaWSatX[0], "TOP")
# Access the layer object in the map
lmSaWSatX = m.listLayers(lyrnSaWSatX)[0]
# Access the symbology object
symSaWSatX = lmSaWSatX.symbology
# Update the colorizer to be a classifed one
symSaWSatX.updateColorizer('RasterClassifyColorizer')
symSaWSatX.colorizer.classificationField = "Value"
# Create lists for break values, labels, and colors
lsWSBreakValues = [2,4,6,8,10,12,14,16,18,20,26]
lsWSBreakLabels = []
for ws in lsWSBreakValues:
    label = "<= " + str(ws) + "m/s"
    lsWSBreakLabels.append(label)
    del label
lsWSBreakColours = [[190,232,255,100],
                  [175,245,177,100],
                  [171,253,102,100],
                    [212,243,38,100],
                    [241,222,0,100],
                    [251,185,0,100],
                    [255,113,0,100],
                    [255,19,0,100],
                    [255,0,88,100],
                    [255,0,197,100],
                    [168,0,132,100]]

# Create breaks in map layer
symSaWSatX.colorizer.breakCount = len(lsWSBreakValues)
symCounter = 0
# for each break get values from lists to allocate break value, label and color
for brk in symSaWSatX.colorizer.classBreaks:
    brk.upperBound = lsWSBreakValues[symCounter]
    brk.label = lsWSBreakLabels[symCounter]
    brk.color = {'RGB' : lsWSBreakColours[symCounter]}
    symCounter += 1
# Apply the updated symbology to the map layer
lmSaWSatX.symbology = symSaWSatX

 and I have arcpy, os and math  packages imported.

 

Any help would be greatly appreciated,

Nick

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
by Anonymous User
Not applicable

Doing a test on a raster, it seems to work ok for me.  One thing I'd suggest is to be more explicit with the upper boundary, label, and color by using a dictionary. This method prevents a list index being off and reduces some looping.

breaks = {0: {'upper': 2, 'color': [190, 232, 255, 100]},
          1: {'upper': 4, 'color': [175, 245, 177, 100]},
          2: {'upper': 6, 'color': [171, 253, 102, 100]},
          3: {'upper': 8, 'color': [212, 243, 38, 100]},
          4: {'upper': 10, 'color': [241, 222, 0, 100]},
          5: {'upper': 12, 'color': [251, 185, 0, 100]},
          6: {'upper': 14, 'color': [255, 113, 0, 100]},
          7: {'upper': 16, 'color': [255, 19, 0, 100]},
          8: {'upper': 18, 'color': [255, 0, 88, 100]},
          9: {'upper': 20, 'color': [255, 0, 197, 100]},
          10: {'upper': 26, 'color': [168, 0, 132, 100]}
          }

# Create breaks in map layer
symSaWSatX.colorizer.breakCount = len(breaks)

# for each break get values from lists to allocate break value, label and color
for i, brk in enumerate(symSaWSatX.colorizer.classBreaks):
    brk.upperBound = breaks[i]['upper']
    brk.label = label = "<= " + str(breaks[i]['upper']) + "m/s"
    brk.color = {'RGB': breaks[i]['color']}

# Apply the updated symbology to the map layer
lmSaWSatX.symbology = symSaWSatX

p.save()

 

View solution in original post

2 Replies
by Anonymous User
Not applicable

Doing a test on a raster, it seems to work ok for me.  One thing I'd suggest is to be more explicit with the upper boundary, label, and color by using a dictionary. This method prevents a list index being off and reduces some looping.

breaks = {0: {'upper': 2, 'color': [190, 232, 255, 100]},
          1: {'upper': 4, 'color': [175, 245, 177, 100]},
          2: {'upper': 6, 'color': [171, 253, 102, 100]},
          3: {'upper': 8, 'color': [212, 243, 38, 100]},
          4: {'upper': 10, 'color': [241, 222, 0, 100]},
          5: {'upper': 12, 'color': [251, 185, 0, 100]},
          6: {'upper': 14, 'color': [255, 113, 0, 100]},
          7: {'upper': 16, 'color': [255, 19, 0, 100]},
          8: {'upper': 18, 'color': [255, 0, 88, 100]},
          9: {'upper': 20, 'color': [255, 0, 197, 100]},
          10: {'upper': 26, 'color': [168, 0, 132, 100]}
          }

# Create breaks in map layer
symSaWSatX.colorizer.breakCount = len(breaks)

# for each break get values from lists to allocate break value, label and color
for i, brk in enumerate(symSaWSatX.colorizer.classBreaks):
    brk.upperBound = breaks[i]['upper']
    brk.label = label = "<= " + str(breaks[i]['upper']) + "m/s"
    brk.color = {'RGB': breaks[i]['color']}

# Apply the updated symbology to the map layer
lmSaWSatX.symbology = symSaWSatX

p.save()

 

NickAtEsriAU
New Contributor II

Many thanks Jeff.  I applied your structure and had success.  interestingly, I am using your structure  for another script but for a GraduatedColorsRenderer on a polygon layer and I am still having issues where some classes aren't shown.  I am going to this another post though as it is off topic.

 

Many Thanks,

Nick

0 Kudos