ArcPro getLayerExtent() using MapView class

3859
8
Jump to solution
07-20-2021 02:31 PM
MaryDuBose
New Contributor III

I am converting our custom Python scripts that were written for ArcGIS 10.x/Python 2 so that we can use them in ArcGIS Pro. Part of the workflow involves selecting one feature from a layer and panning the map to that feature. The old version used a couple of methods which no longer work the same way with Pro: panToExtent() and getSelectedExtent(). I've been researching this and it seems that in Pro, the only way to get an extent or modify the active map's extent is through either the MapFrame or MapView classes (see https://community.esri.com/t5/python-questions/zoom-to-layer-on-the-map-view-arcpy-mp/m-p/1046096#M6...). This map is not meant for publishing so therefore does not have any map frames, so I'm trying to accomplish this through the MapView class, but getting Python errors.

What I've tried so far is creating a MapView object from the map object's defaultView, then trying to call the getLayerExtent() method on that MapView object, passing in a layer as the parameter. It gives me a RuntimeError. Can anyone provide any examples of how to use the getLayerExtent() method, or any more general advice on how to accomplish this task of getting the extent of a selected feature and then panning the map to that feature? Any advice would be much appreciated. Thank you! 

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
MatthewMuehlhauser
New Contributor III

After some testing, below was the only way I could get it to work using a MapView instead of a MapFrame. And, it wouldn't work in the python console, I had to save it in a script tool and run it.

 

import arcpy

roll = arcpy.GetParameterAsText(0)

project = arcpy.mp.ArcGISProject("CURRENT")
mapObject = project.listMaps("Your Map Name")[0]
mapView = project.activeView

parcels = mapObject.listLayers("Parcels")[0]

query = "Roll = '"+ roll +"'"
selection = arcpy.SelectLayerByAttribute_management(parcels, "NEW_SELECTION", query)

mapView.panToExtent(mapView.getLayerExtent(parcels, True))

arcpy.SelectLayerByAttribute_management(parcels, "CLEAR_SELECTION")

 

If I used the path to the project instead of "CURRENT", it would fail. This, I think, makes sense though because you technically wouldn't have an active view if the project wasn't opened by the user. 

If I tried to use the default view of the MapObject instead of the activeVIew of the Project to get around the previous though, it would fail.

 

#This Fails
project = arcpy.mp.ArcGISProject("CURRENT")
mapObject = project.listMaps(layoutTemplate)[0]
mapView = mapObject.defaultView

 

So it seems pretty inflexible to change the extent using this way unless you are using a MapLayout and MapFrame. I haven't tested the camera, so that may be the way to go.

View solution in original post

8 Replies
MatthewMuehlhauser
New Contributor III

Below is how I did the select and pan in Pro. I used a Map Frame, but looking at the documentation / methods, it should work for a Map View as well. 

query = "Roll = '"+ roll +"'"
selection = arcpy.SelectLayerByAttribute_management(parcels, "NEW_SELECTION", query)

mapFrame.panToExtent(mapFrame.getLayerExtent(parcels, True))

arcpy.SelectLayerByAttribute_management(parcels, "CLEAR_SELECTION")

 

 

  That being said, there is a warning, so not sure if that would affect you:

Caution:

Not all MapView methods are available to web app developers. The following methods are not supported in a web map printing application:

  • getLayerExtent
  • panToExtent
  • zoomToAllLayers
  • zoomToBookmark
0 Kudos
MaryDuBose
New Contributor III

Hi Matthew, thanks for the reply! I followed these steps exactly but just replaced the map frame with my map view, and unfortunately it gives me that same (frustratingly non-specific) RuntimeError as before.

 

This is not a web map, just a standalone ArcPro project saved to a network drive with the data sources stored on that same network drive.

0 Kudos
MatthewMuehlhauser
New Contributor III

Hmmm, I just did a test to see, and I got a runtime error as well. It was working before, so I think it's the new update to ArcGIS Pro 3.8. If you ran this in 3.7, I bet it would work fine. It also looks like it's trying to prompt me to use

arcpy.management.SelectLayerByAttribute()

instead of

arcpy.SelectLayerByAttribute_management()

And both are causing a Runtime Error, so definitely something has changed.

 

RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd

(Comment on the above, this RuntimeError was caused because the console in ArcGIS Pro was referencing a wrong version of numpy in a random folder. After fixing that, the error went away, but my next comment still stands, although now it will work in the console as well and not just a script tool)

0 Kudos
MatthewMuehlhauser
New Contributor III

After some testing, below was the only way I could get it to work using a MapView instead of a MapFrame. And, it wouldn't work in the python console, I had to save it in a script tool and run it.

 

import arcpy

roll = arcpy.GetParameterAsText(0)

project = arcpy.mp.ArcGISProject("CURRENT")
mapObject = project.listMaps("Your Map Name")[0]
mapView = project.activeView

parcels = mapObject.listLayers("Parcels")[0]

query = "Roll = '"+ roll +"'"
selection = arcpy.SelectLayerByAttribute_management(parcels, "NEW_SELECTION", query)

mapView.panToExtent(mapView.getLayerExtent(parcels, True))

arcpy.SelectLayerByAttribute_management(parcels, "CLEAR_SELECTION")

 

If I used the path to the project instead of "CURRENT", it would fail. This, I think, makes sense though because you technically wouldn't have an active view if the project wasn't opened by the user. 

If I tried to use the default view of the MapObject instead of the activeVIew of the Project to get around the previous though, it would fail.

 

#This Fails
project = arcpy.mp.ArcGISProject("CURRENT")
mapObject = project.listMaps(layoutTemplate)[0]
mapView = mapObject.defaultView

 

So it seems pretty inflexible to change the extent using this way unless you are using a MapLayout and MapFrame. I haven't tested the camera, so that may be the way to go.

MaryDuBose
New Contributor III

Thank you so much Matthew! This was incredibly helpful. That was the one change I needed to make in my script -- using the project's activeView, rather than the map's defaultView. Once I made that change, the script ran without any errors, and had the expected behavior of panning the map to the selected feature. The use case for this is for technicians to be able to run it as a script tool from a custom toolbox, so no need for me to be able to run this from the Python console.

0 Kudos
MatthewMuehlhauser
New Contributor III

Depending on your use case, this may be something you could add into a task. The Locate / Layer Search command works very similarly to what you were trying to do and seems pretty easily configurable and can be added to a task workflow.

MatthewMuehlhauser_0-1627412234626.png

 

0 Kudos
DanPatterson
MVP Esteemed Contributor

camera class in mp?  it has get and set extent... perhaps an alternative

Camera—ArcGIS Pro | Documentation


... sort of retired...
0 Kudos
MaryDuBose
New Contributor III

Hi Dan, I did look into the Camera class but its getExtent() method does not take any parameters so there doesn't seem to be a way to do anything besides get the current extent of the map, where what I need it to do it get the extent of a selected feature.

0 Kudos