get CIM layer object type

1694
5
Jump to solution
09-01-2020 12:38 PM
danashney
New Contributor III

I am working with CIM layer definitions a bit. For a layer, I am wanting to get the field that the symbol thematic is based on (layerDefinitions.renderer.fields). However, some renderer types have the fields property while some don't. CIMUniqueValueRenderer has the fields property while CIMSimpleRenderer does not. If I try to access fields on a feature class that uses CIMSimpleRenderer I get an error. However, I cannot access the type property that I can plainly see in the json through the python therefore I cannot create logic around renderer type. 

aprx = arcpy.mp.ArcGISProject("CURRENT")
for map in aprx.listMaps():
   for layer in map.listLayers():
      cim_lyr = layer.getDefinition('V2')
      if cim_lyr.renderer.fields is not None:  # this is obviously not working

      #if cim_lyr.renderer.type == blah:  # this is what I would think I should be able to do
         print("--- ---Thematic Field: " + str(cim_lyr.renderer.fields[0]))

Error if I plug in a feature class with the wrong type:

AttributeError: 'CIMSimpleRenderer' object has no attribute 'fields'

 

So, the object obviously knows its type per the error and per the json entry but does not offer me any good way of accessing its type through the CIM object model that I have found. How would I go about this?

 

1 Solution

Accepted Solutions
DanPatterson
MVP Esteemed Contributor

if you do a 'dir' on cim_lyr what attributes does it show for one with a table and one without.

I am thinking along the lines of

if hasattr(cim_lyr, 'fields'):
    do something
else:
    something else

... sort of retired...

View solution in original post

5 Replies
DanPatterson
MVP Esteemed Contributor

if you do a 'dir' on cim_lyr what attributes does it show for one with a table and one without.

I am thinking along the lines of

if hasattr(cim_lyr, 'fields'):
    do something
else:
    something else

... sort of retired...
danashney
New Contributor III

This did the trick. Thank you. It is still odd to me that 'type' is an available property if I look at the lyrx (ie json) file in a text editor but is not exposed in the CIM model. Oh well. 

This is what finally worked such that it prints the thematic field only if the appropriate renderer type is being used (your suggestion with slight modification):

aprx = arcpy.mp.ArcGISProject("CURRENT")
for map in aprx.listMaps():
   for layer in map.listLayers():
      cim_lyr = layer.getDefinition('V2')
      if hasattr(cim_lyr.renderer, 'fields'):
         print("--- ---Thematic Field: " + str(cim_lyr.renderer.fields[0])) 

andrew_k_barker
New Contributor

Use the built-in type() function.  I presume because type() is a built-in function you can't use it to access CIM properties, to avoid confusion.  

E.g. to do something with only point, line or polygon geometry:

 

for lyr in map.listLayers():
  lyrCIM = lyr.getDefinition('V2')
  if type(lyrCIM) is arcpy.cim.CIMVectorLayers.CIMFeatureLayer:
    geomType = type(lyrCIM.renderer.symbol.symbol)

    if geomType is arcpy.cim.CIMSymbols.CIMPointSymbol:
      doSomething()

    elif geomType is arcpy.cim.CIMSymbols.CIMLineSymbol:
      doSomethingElse()

    elif geomType is arcpy.cim.CIMSymbols.CIMPolygonSymbol:
      doAnotherThing()

0 Kudos
AlderMaps
Occasional Contributor

I tried this to begin with but it returns a class rather than just a string for easy comparison; I had to do just a tiny bit more work to get this method to work as well, e.g.: 

aprx = arcpy.mp.ArcGISProject("CURRENT")
my_map = aprx.listMaps("CA Landslide Data")[0]

for lyr in my_map.listLayers():
    ciml = lyr.getDefinition("V3")
    if type(ciml).__name__ == "CIMTiledServiceLayer":
        #Do stuff      

 

0 Kudos
AlderMaps
Occasional Contributor

This was just the question I had and the answer worked for me. Problem solved in 5 min. Kudos to Esri Community!

0 Kudos