reorder webmap layers with Python?

3691
17
04-07-2020 05:17 PM
davedoesgis
Occasional Contributor III

I'd like to re-order webmap layers with Python. I'm using the arcgis package (the ArcGIS API for Python) to add a layer, but the newest layer just goes to the top of the layer list (table of content), which may not be where I want it. How do I re-order it after I add it? 

I'd also be interested to know if the WebMap.add_layer() function can just put the layer in the right order in the first place.

thanks!

17 Replies
davedoesgis
Occasional Contributor III

Anyone at Esri following the forums? 

0 Kudos
ikatinas
New Contributor

You can change the layers order by changing the order of WebMap object's definition['operationalLayers'] list. 

e.g. to switch the order between 1st and last having 6 layers:

wm = WebMap(wm_item)
tempLayerDefinition = wm.definition['operationalLayers'][5]
wm.definition['operationalLayers'][5] = wm.definition['operationalLayers'][0]
wm.definition['operationalLayers'][0] = tempLayerDefinition
wm.update()

  

0 Kudos
PaulHallett1305
Occasional Contributor

I can't get this to work in anyway shape or form?

 

 

 

web_map = gis.content.get("1852725785754747")
wm = WebMap(web_map)

tmplyrdef = wm.definition.operationalLayers[15]
wm.definition.operationalLayers[15] = wm.definition.operationalLayers[0]
wm.definition.operationalLayers[0] = tmplyrdef

wm.update()
wm

 

 

In the absence of doubt, I also tried it this way

 

web_map = gis.content.get("572727827257578547")
wm = WebMap(web_map)

print(wm.definition.spatialReference)
print(wm.definition['operationalLayers'][15])

tempLayerDefinition = wm.definition['operationalLayers'][15]
wm.definition['operationalLayers'][15] = wm.definition['operationalLayers'][0]
wm.definition['operationalLayers'][0] = tempLayerDefinition


wm.update(item_properties=wip)

wm

 

 

0 Kudos
Clubdebambos
Occasional Contributor III

This works. You need to be aware that the indexing starts at the bottom layer and not the top. The below will switch the bottom layer with the second last layer.

from arcgis import GIS

conn = GIS("home")

item = conn.content.get("wm_item_id")
item_data = item.get_data()

tmp = item_data['operationalLayers'][1]
item_data['operationalLayers'][1] = item_data['operationalLayers'][0]
item_data['operationalLayers'][0] = tmp
item_properties = {"text":item_data}
item.update(item_properties=item_properties)

 

~ learn.finaldraftmapping.com
Clubdebambos
Occasional Contributor III

Just taking this a bit further, I have tens of maps that will eventually be over a couple of hundred +, where I want standard layers in the same order, users have potential to reorder and some older maps do not fit the standard order but the layer naming does. Below is the base script created, I can put the list of webmap ids in a file and iterate through when I want or schedule for intermittent quality control runs. The below is for one run on a single webmap.

 

from arcgis import GIS

## dictionary
## key: standard layer name
## value: list, index of layer (from bottom up), the definition will be added to this list.
lyr_order_dict = {
    "standard_lyr_name_1" : [0],
    "standard_lyr_name_2" : [1],
    "standard_lyr_name_3" : [2],
    "standard_lyr_name_4" : [3],
    "standard_lyr_name_5" : [4],
    "standard_lyr_name_6" : [5],
    "standard_lyr_name_7" : [6],
    "standard_lyr_name_8" : [7],
    "standard_lyr_name_9" : [8],
    "standard_lyr_name_10" : [9],
    "standard_lyr_name_11" : [10],
    "standard_lyr_name_12" : [11],
    "standard_lyr_name_13" : [12],
    "standard_lyr_name_14" : [13]
}

conn = GIS("home")

item = conn.content.get("wm_id")
item_data = item.get_data()

## iterate through the layers
for index, i in enumerate(item_data["operationalLayers"]):
    ## get the name of the layer
    title = item_data["operationalLayers"][index]["title"]
    ## add the definition to the entry in the dictionary
    if title in lyr_order_dict:
        lyr_order_dict[title] = lyr_order_dict[title] + [item_data['operationalLayers'][index]]

## iterate through the dictionary and reorder the layers
for key, value in lyr_order_dict.items():
    item_data['operationalLayers'][value[0]] = value[1]

item_properties = {"text":item_data}
item.update(item_properties=item_properties)

 

~ learn.finaldraftmapping.com
PaulHallett1305
Occasional Contributor

Thanks, will check if this works for me tomorrow; a dict was going to be my next stab. 

0 Kudos
PaulHallett1305
Occasional Contributor

I have tested it, quite a lot, and it doesn't move any of the layers at all.  

I'll work on it again tomorrow, but implementing this, as above, didn't work for me.

0 Kudos
Clubdebambos
Occasional Contributor III

That's interesting, I've ran this a few times now and works perfectly, I wonder what the difference is? 

~ learn.finaldraftmapping.com
0 Kudos
PaulHallett1305
Occasional Contributor

Hi there,

Sorry for the late reply, but I have been ill.

This is the function I have, inside a utilities class and I get list index errors, and when I checkl the contents, it's not being populated.

 

 

 

 

    def reorder_layers(self):
        print("*********Re-ordering layers********** \n\n")
        ## dictionary
        ## key: standard layer name
        ## value: list, index of layer (from bottom up), the definition will be added to this list.
        lyr_order_dict = {
            "Open Work Orders" : [0],
            "Pressure Control Valves" : [1],
            "Others Repairs" : [2],
            "Dry Holes" : [3],
            "Open CSL" : [4],
            "GISID RAG Status" : [5],
            "Secondary Pipe Status" : [6],
            "DMA" : [7],
            "NMA" : [8],
            "FMZ" : [9],
            "Network Operation Valve" : [10],
            "Fire Hydrant" : [11],
            "Hot Spot" : [12],
            "Property Info" : [13]
        }

        web_map = self.gis.content.get(self.web_map_id)
        item_data = web_map.get_data()

        ## iterate through the layers
        for index, i in enumerate(item_data["operationalLayers"]):
            ## get the name of the layer
            title = item_data["operationalLayers"][index]["title"]
            ## add the definition to the entry in the dictionary
            if title in lyr_order_dict:
                print(f"{lyr_order_dict[title]} \n")
                lyr_order_dict[title] = lyr_order_dict[title] + [item_data['operationalLayers'][index]]
                print(f"{lyr_order_dict[title]} \n")
                print(f"{item_data['operationalLayers'][index]} \n")
                

        ## iterate through the dictionary and reorder the layers
        for key, value in lyr_order_dict.items():
            item_data['operationalLayers'][value[0]] = value[1]

        item_properties = {"text":item_data}
        self.wm.update(item_properties=item_properties)   
        

 

 

 

This gives me an indexError: list index out of range, which on investigating, the data in there isn't good.

 

 

IndexError: list index out of range
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<command-2193284686337018> in <module>
     42 
     43 agsutil.get_feature_layer_size()
---> 44 agsutil.reorder_layers()
     45 agsutil is None
     46 print("Finished")

<command-2193284686336187> in reorder_layers(self)
    147         ## iterate through the dictionary and reorder the layers
    148         for key, value in lyr_order_dict.items():
--> 149             item_data['operationalLayers'][value[0]] = value[1]

 

 

0 Kudos