Setting the lower limit of graduated color symbols in Python

387
5
03-11-2024 07:12 PM
Status: Under Consideration
Labels (1)
-_-
by
New Contributor III

I can't find a way to do this so I'll post it as an idea.

When setting graduated color symbols, the upper and lower limits are first set by natural classification. At this time, the minimum value is set to the minimum value of the lowest range, but although there was a way to rewrite this in Python in ArcMap, it is no longer available in ArcGIS PRO, which is a problem.

For example, if you import layer A with a symbol with a minimum value of 5 into layer B with a minimum value of 1, features 1 to 4 will no longer be displayed. To avoid this, ArcMap used Python to set the minimum value to "-1000000".

ArcMap has a property called "classBreakValues" that returns all the range values in a list, making it very easy to set the numerical values for the range. However, in ArcGIS PRO, the only way to change the numerical values in the range is to change the upper limit value using the upperBound property of the ClassBreak class, and it is no longer possible to change the minimum value.

Although it is possible to manually rewrite the minimum value one by one, I would be happy if a property such as "MinimumValue" was added so that it can be rewritten in Python as before.

5 Comments
JeffBarrette
Status changed to: Under Consideration

Thank you for your feedback, @-_- 

This can be accomplished via Python CIM access: https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm

In addition to changing the CIM minimumBreak value, you also need to change the label for the first class break to include your modified value.

Here is a code snippet:

#In this example, the first class break range is "62127 - 824344"
#The minimumBreak value is changed to "60000" via Python CIM Access
#BUT ... the label also needs to be updated to "60000 - 824344

p = arcpy.mp.ArcGISProject('current')
m = p.listMaps('Map')[0]
l = m.listLayers('State_Polygons')[0]

#Update mimimumBreak value via Python CIM Access
if hasattr(l.symbology, 'renderer'):
  if l.symbology.renderer.type == 'GraduatedColorsRenderer':
    l_cim = l.getDefinition('V3')
    l_cim.renderer.minimumBreak = 60000 
    l.setDefinition(l_cim)

#Update the label to match the new value is seen via Histogram tab
sym = l.symbology
cb1 = sym.renderer.classBreaks[0]
cb1Lbl = cb1.label
update = cb1Lbl.replace(cb1Lbl.split('-')[0], str(l_cim.renderer.minimumBreak) + ' ' )
cb1.label = update
l.symbology = sym

  

Jeff - Layout (SDK) and arcpy.mp teams

-_-
by

I am very grateful.
I was able to change the lower limit using the method taught by @JeffBarrette.
I was able to change the minimum value of the layer whose minimum value was "5" to "-1000000000", and I was able to confirm that it was "-1000000000" in the "Histogram". If you look at the legend, it has been rewritten as intended.

However, unfortunately, when I imported layer A whose minimum value was set to "-1000000000" to another layer B whose minimum value was "1", the minimum value was changed to "5". , symbols with numbers 1 to 4 are no longer displayed.
Did I do something wrong?

 

postscript:

Now that I know that I can read lyrx files directly, I exported layer A as a lyrx file and opened it, but the value of "minimumBreak" was still "5". The rewritten value is displayed on the "histogram", but it seems that it has not been changed on the lyrx file.

JeffBarrette

@-_- can you please explain how you are importing?  I added the last two lines to the sample code I originally made available to see if writing to LYRX was losing its value.  For me, its working as expected.

#In this example, the first class break range is "62127 - 824344"
#The minimumBreak value is changed to "60000" via Python CIM Access
#BUT ... the label also needs to be updated to "60000 - 824344

p = arcpy.mp.ArcGISProject('current')
m = p.listMaps('Map')[0]
l = m.listLayers('State_Polygons')[0]

#Update mimimumBreak value via Python CIM Access
if hasattr(l.symbology, 'renderer'):
  if l.symbology.renderer.type == 'GraduatedColorsRenderer':
    l_cim = l.getDefinition('V3')
    l_cim.renderer.minimumBreak = 60000 
    l.setDefinition(l_cim)

#Update the label to match the new value is seen via Histogram tab
sym = l.symbology
cb1 = sym.renderer.classBreaks[0]
cb1Lbl = cb1.label
update = cb1Lbl.replace(cb1Lbl.split('-')[0], str(l_cim.renderer.minimumBreak) + ' ' )
cb1.label = update
l.symbology = sym

#Test if values are persisted when saving to a LYRX
l.saveACopy(r'c:\Temp\MinValue.lyrx')
m.addDataFromPath(r'c:\Temp\MinValue.lyrx') #Min value is persisted

Then I ran this as another way to test persistence.

#Test values can be applied to other layers.
l1 = m.listLayers('Original')[0]  #Made a copy prior to running script above
l2 = m.listLayers('State_Polygons')[0]

l1.symbology = l2.symbology

Is it possible it is layer type or data specific?

Jeff

-_-
by

The import method is "arcpy.management.ApplySymbologyFromLayer".
I also tried the two lines "Test if values are persisted when saving to a LYRX", but the lowest value of the added layer remained "5".

-_-
by

@JeffBarrette

I understand the cause. It was my mistake.

Where it should have been

 

if hasattr(l.symbology, 'renderer'):
  if l.symbology.renderer.type == 'GraduatedColorsRenderer':

 

, it was

 

sym=l.symbology
if hasattr(sym,'renderer'):
    if sym.renderer.type=="GraduatedColorsRenderer":

 

 .

Therefore, it seems that "l.symbology=sym" reverted to the original state.
Sorry for the inconvenience.
Once I corrected this, it worked as expected.
Thank you very much.