Hi everyone,
I’m sharing a working Python script that applies a UniqueValueRenderer symbology to a point feature class in ArcGIS Pro using arcpy. This implementation uses Picture Marker Symbols to represent each unique value in a field—specifically, country flags. The shared code is part of a broader implementation.
Many of us have faced challenges when working with CIM-based symbology in ArcGIS Pro. The documentation around the Cartographic Information Model (CIM) can be sparse or unclear, and issues often arise regardless of the programming language used.
This post aims to provide a working example that others can adapt and build upon.
I’ve seen many threads where people are stuck on similar issues, so I wanted to contribute a working reference. If you're trying to automate symbology in ArcGIS Pro using arcpy, this might save you some time.
In the code below, read "data:image" in its HTML version data+colon symbol+image
Cheers,
def set_defaultuniquevaluesrenderer(featurelayer=None, fieldname=None):
"""Set a default unique values renderer for the specified field in the feature layer."""
if featurelayer is None:
arcpy.AddError("Layer not found. Symbology not updated.")
sym = featurelayer.symbology
sym.updateRenderer('UniqueValueRenderer')
sym.renderer.fields = [fieldname]
featurelayer.symbology = sym
arcpy.AddMessage(f"Symbology updated to UniqueValueRenderer on field: {fieldname}")
def set_updatesymbology(featurelayer=None, fieldname=None, imagefolder=None):
"""Update only the point symbols as picture markers with corresponding images."""
if featurelayer is None:
arcpy.AddError("Layer not found. Symbology not updated.")
# Get the CIM (Cartographic Information Model) definition of the layer
cim = featurelayer.getDefinition('V3')
renderer = cim.renderer
# Iterate through each class in the renderer's first group
for classDef in renderer.groups[0].classes:
# Get the value for the symbol (usually the flag image filename)
try:
value = classDef.values[0].fieldValues[0]
except (AttributeError, IndexError, TypeError):
arcpy.AddWarning(f"Skipping class with no valid value for symbol: {classDef.name}")
continue
# Build the full path to the image file
imagePath = os.path.join(imagefolder, value)
if arcpy.Exists(imagePath):
# Read and encode the image as base64
with open(imagePath, "rb") as imgFile:
encoded = base64.b64encode(imgFile.read()).decode("utf-8")
# Define a CIMPictureMarker using the encoded image
pictureMarker = {
"type": "CIMPictureMarker",
"enable": True,
"size": 10,
"url": f"data:image/png;base64,{encoded}",
}
# Create a CIMPointSymbol with the picture marker
pointSymbol = {
"type": "CIMPointSymbol",
"symbolLayers": [pictureMarker]
}
# Create a CIMSymbolReference for the class symbol
symbolRef = {
"type": "CIMSymbolReference",
"symbol": pointSymbol
}
# Assign the new symbol to the class definition
classDef.symbol = symbolRef
# Apply the updated CIM definition back to the feature layer
featurelayer.setDefinition(cim)
arcpy.AddMessage("Point symbols updated with corresponding flag images.")
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.