Python Blog

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Other Boards in This Place


Latest Activity

(198 Posts)
Samy_BoumaNgock
Emerging Contributor

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.

SamyBouma_Ngock_0-1748357457635.gif

Why This Matters

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.

 

Use Case

  • Feature class type: Point (e.g., country centroids)
  • Field used for symbology: Country_Flag
    • Must use the internal field name, not the alias
    • Field name is case-sensitive
  • Unique values: 238 (each representing a country)
  • Goal: Assign a Picture Marker Symbol (flag image) to each point based on the Country_Flag field

 

Implementation Steps

  • Set a default UniqueValueRenderer using a basic shape marker, keyed on the Country_Flag field.
  • Iterate through each unique value and assign a Picture Marker Symbol using images stored in a local folder.
    • Each image filename matches a value in the Country_Flag field exactly (e.g., France.png, Brazil.png).

 

Key Challenges

  • CIM complexity: The structure of CIM symbol layers is not always intuitive.
  • Field name sensitivity: Using the alias or incorrect casing can silently fail.
  • Lack of consistent examples: Many developers report inconsistent behavior or undocumented quirks when applying symbology programmatically.

 

Why I’m Posting

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.")

 

more
0 0 322
DanPatterson
MVP Esteemed Contributor

Text data is a bother because of its variable length.  NumPy provides a path forward.

Read more...

more
4 0 236
DanPatterson
MVP Esteemed Contributor

worth reading, particularly with the new additions to specifying tool outputs in 3.5

Read more...

more
2 1 246
DanPatterson
MVP Esteemed Contributor

It is springtime, so don't neglect your boundaries.  They may have redundant points, segments that overlap and a variety of other mishaps.

Read more...

more
2 0 264
DanPatterson
MVP Esteemed Contributor

A common activity, buffering is.  Understanding the pitfalls is not on the radar for most.

Read more...

more
3 0 237
ShareUser
Esri Community Manager

A better way of managing Attribute Rules using git and plaintext

Read more...

more
2 6 416
DanPatterson
MVP Esteemed Contributor

Have you had one?  A field that contains strings that were nested lists or something similar?

Read more...

more
3 13 876
mfcallahan
Frequent Contributor

I recently started exploring the Flask web application framework for Python, but I ran into an issue when trying to deploy the application to Windows Server. My Flask application had a dependency on arcpy, which was available on my local development environment, but not on my server. As you are likely aware, the arcpy package is not available outside of the ArcGIS Pro Python environment, and I ran into quite a few issues with not being able to import and use these libraries. After some some googling, lots of trial and error, and a little help from Esri support, I was able to accomplish this task!

https://mfcallahan.com/2025/02/17/deploying-a-python-flask-application-which-can-import-arcpy-and-th...

Above is the link to my blog post which goes into deep detail on how to accomplish this, but at a high level, the steps needed to accomplish this are:

  • Copy app code to server
  • Clone the default "arcgispro-py3" environment
  • Activate your cloned ArcGIS Pro Python environment in Conda
  • Install the flask and wfastcgi dependencies
  • Copy file "wfastcgi.py" to the root app folder from the Python site-packages folder
  • Create a new application pool
  • Set app folder ownership to IIS AppPool
  • Add app to FastCGI Server Settings, using the cloned Python env
  • Set <handlers> in web.config file

more
4 4 834
DanPatterson
MVP Esteemed Contributor

Easy!  Or so I thought.  The lead up to when things go wrong.

Read more...

more
5 0 277
DanPatterson
MVP Esteemed Contributor

Left, right straight.  All directional.  Kindred folk.

Read more...

more
5 0 217
229 Subscribers
Labels