reading a user text file to zoom to a particular area

1091
10
03-08-2011 11:59 AM
MikePowell
New Contributor II
I am having a hard time trying to figure out this. I have a .txt file with township/range/sections that I need to read and than zoom to the section, refresh the map and export files from it and than go to the next one. Here is the code:

import arcpy

mxd = arcpy.mapping.MapDocument("M:\\par-prod\\checking\\bookmaps.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Legal")[0]
lyr = arcpy.mapping.ListLayers(mxd, "GCDB*", df)[0]
data_file = open('todo.txt', 'r')
for item in data_file:
    print item
    rows = arcpy.SearchCursor(lyr)
    row = rows.next()
    while row:
        trs = row.getValue("TOWN")
        if trs == item:
            print "Township Range Section is "+trs
        row = rows.next()
   
    del rows

I know it reads the list (with the first print) but it only gets to the next print for the last item in the list. No matter how many are in the list it only seems to do the last item. What am I not seeing?
Tags (2)
0 Kudos
10 Replies
ChrisMathers
Occasional Contributor III
Well you are only getting the last page because the cursor is going to the end and then stoping. To do it this way you will need to create a new cursor and then delete it for each item in the list. You could use the list to create a selection and then open the cursor. If you do that, the only objects the cursor will use are the selected ones. You can then just zoom from extent to extent with df.extent=extent. Or if you want to have a constant scale (and probably do since townships are all the same size) you can use df.panToExtent(extent)

mxd = arcpy.mapping.MapDocument("M:\\par-prod\\checking\\bookmaps.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Legal")[0]
make query from list
select by attribute(query)
for row in cursor:
    shape=row.shape
    extent=shape.extent
    df.extent=extent
    export
0 Kudos
MikePowell
New Contributor II
Thanks for the reply. Sorry, I'm still a little new to python. First, I am sorry for my copying of the script and not replacing the indentation. Here is how it should look:
import arcpy

mxd = arcpy.mapping.MapDocument("M:\\par-prod\\checking\\bookmaps.mxd")
df = arcpy.mapping.ListDataFrames(mxd, "Legal")[0]
lyr = arcpy.mapping.ListLayers(mxd, "GCDB*", df)[0]
data_file = open('todo.txt', 'r')
for item in data_file:
     print item
     rows = arcpy.SearchCursor(lyr)
     row = rows.next()
     while row:
         trs = row.getValue("TOWN")
         if trs == item:
             print "Township Range Section is "+trs
         row = rows.next()

    del rows

I guess I am still a little confused on why the cursor is going to the end of the list and than running. I like the idea of using the list to create a selection. That would eliminate trying to compare what is in the list and what is in the field "TOWN", I think. I am confused though by your code example though. I am assuming "make query from List" and "select by attribute" are comments. I am not sure how to that. Isn't reading the list and than going through each item in the list, with the "for" statement, considered making a query from the list. I am still a little confused.
0 Kudos
ChrisMathers
Occasional Contributor III
What is the format of the text document? If you can give me a couple sample lines from it I can write up a script to show you. The 'make query from list' line would just be some simple string construction. 'select by attribute(query)' is
arcpy.SelectLayerByAttribute_management (in_layer_or_view, {selection_type}, {where_clause}).
For this it would be:
arcpy.SelectLayerByAttribute_management (lyr, 'NEW_SELECTION',query).

oh and the way to preserve indents is the use (CODE) (/CODE) but with [] instead of ()
0 Kudos
MikePowell
New Contributor II
I certainly apprecite the help. After writting the last message I figured out some of what you were referring to. This is what I have now:

(Code)[import arcpy

mxd = arcpy.mapping.MapDocument("M:\\par-prod\\checking\\legal.mxd")
dfmain = arcpy.mapping.ListDataFrames(mxd, "Legal")[0]
dfsec = arcpy.mapping.ListDataFrames(mxd, "section")[0]
dftown = arcpy.mapping.ListDataFrames(mxd, "township")[0]
lyrmain = arcpy.mapping.ListLayers(mxd, "GCDB*", dfmain)[0]
lyrsec = arcpy.mapping.ListLayers(mxd, "GCDB*", dfsec)[0]
lyrtown = arcpy.mapping.ListLayers(mxd, "GCDB*", dftown)[0]
data_file = open('todo.txt', 'r')
for item in data_file:
    arcpy.SelectLayerByAttribute_management(lyrsec, "NEW_SELECTION", "TOWN like '"+item[:5]+"'")
    dfsec.zoomToSelectedFeatures()
    arcpy.SelectLayerByAttribute_management(lyrsec, "CLEAR_SELECTION")
    arcpy.SelectLayerByAttribute_management(lyrsec, "NEW_SELECTION", "TOWN = '"+item+"'")

    arcpy.SelectLayerByAttribute_management(lyrtown, "NEW_SELECTION", "TOWN = '"+item+"'") 
   
    arcpy.SelectLayerByAttribute_management(lyrmain, "NEW_SELECTION", "TOWN = '"+item+"'")                   
    dfmain.zoomToSelectedFeatures()
    arcpy.SelectLayerByAttribute_management(lyrmain, "CLEAR_SELECTION")
    arcpy.RefreshActiveView()
    for elm in arcpy.mapping.ListLayoutElements(mxd, "Text_Element"):      
        if elm.name == "Date":
            elm.text = 'Date: <dyn type="date" format="short"/>'
        if elm.name == "Location":
            elm.text = "SEC "+item[5:7]+", T"+item[:2]+"R"+item[2:5]
    mxd.save
    arcpy.mapping.PrintMap(mxd)]

That seems to work, but I am still having a problem. The map that I am setting up has 3 dataframes. One showing the county and a selected section showing where in the county, the second showing the township and the selected section highlighted and the third is the the main map showing that section. For the some reason the selection for the first 2 is not working because they are not highlighted (it did zoom to the correct township for the second dataframe). Also, if my list has more than one item in it (example 3) it will print 3 maps, but the first 2 maps will be the full extents of the county and not zoomed in to the correct section, but the third one prints fine. I don't understand why it is doing that. The todo.txt looks like this:

2S24E16
1N26E16
1S25E12

I am getting it but It just takes me some time. I appreciate the help that you are providing.
0 Kudos
MikePowell
New Contributor II
Sorry for the indenting thing. I guess I didn't quite understand the use of Code(). I think you still can understand it. Thanks again

I should mention that I am running this in PythonWIN. I prefer that over running it in ArcMap.
0 Kudos
ChrisMathers
Occasional Contributor III
In dfCounty the extent is constant correct? It is the whole county Im assuming. To show the extent of other data frames you can just use an extent indicator. Go to the dftown properties and turn on an extent indicator for dfTownship. Then in dfTownship turn on an extent indicator for dfSection. Also, easier than making a selection and clearing it just for symbology reasons, in the layer properties you can change the selection symbol color. Just make it no color and save a step in the code. I renamed some variables just to make it clear in my head and added some inline comments.

import arcpy, re
mxd = arcpy.mapping.MapDocument("M:\\par-prod\\checking\\legal.mxd")
dfSection = arcpy.mapping.ListDataFrames(mxd, "Legal")[0]#Shows one section
dfTownship = arcpy.mapping.ListDataFrames(mxd, "section")[0]#Shows one township
dfCounty = arcpy.mapping.ListDataFrames(mxd, "township")[0] #Shows whole county
lyrSection = arcpy.mapping.ListLayers(mxd, "GCDB*", dfSection)[0]#For showing one section
lyrTownship = arcpy.mapping.ListLayers(mxd, "GCDB*", dfTownship)[0]#For showing one township
data_file = open('todo.txt', 'r')
for item in data_file:
    match=re.search(r'(\d*\D)(\d*\D)(\d*)',item) #splits 2S24E16 into '2S' '24E' '16' in a match object to use
    Town,Range,Sec=match.group(1),match.group(2),match.group(3) #sets the three parts just collected to variables
    arcpy.SelectLayerByAttribute_management(lyrTownship, "NEW_SELECTION", "TOWN LIKE '%s%s'"%(Town,Range))
    dfTownship.zoomToSelectedFeatures()
    arcpy.SelectLayerByAttribute_management(lyrSection, "NEW_SELECTION", "TOWN = '%s%s%s'"%(Town,Range,Sec))
    dfSection.zoomToSelectedFeatures()
    arcpy.RefreshActiveView()
    for elm in arcpy.mapping.ListLayoutElements(mxd, "Text_Element"): 
        if elm.name == "Date":
        elm.text = 'Date: <dyn type="date" format="short"/>'
        if elm.name == "Location":
        elm.text = "SEC %s, T%sR%s"%(Sec,Town,Range)
    arcpy.mapping.PrintMap(mxd)
mxd.save


When pasting code hit that little # in the second line under the post title to add the code tags automatically.
0 Kudos
MikePowell
New Contributor II
Well, at least I can say that I was getting there. Works great. I never heard about that "re" module before. I am also aware of the Extent Indicator, but for some reason, it will not highlight the appropriate section on the printed maps. I can't figure out why. If I do everything manually (setting up the indicator, zooming to another section) in ArcMap, it works fine and highlights the section just by zooming to the dfSection. It just won't highlight in the script. Everything in your script works though, and I am very happy that it is printing every map in the list correctly now. Do you have a reason why it was only printing the last item on the list correctly? I guess, I still don't see why it is working versus before. Is is because of that "re" module. Thanks for the help. I really appreciate it.
0 Kudos
ChrisMathers
Occasional Contributor III
RE is regular expression. It is a module with syntax common to many languages that is for parsing text. The problem with slicing strings like you were doing is that in a case like this you may have 2S24E16, but the next line is 1S5E1. This would break your indexes and the selection wouldnt work. With re you can search for text that matches a format that you define. r'(\d*\D)(\d*\D)(\d*)' searches for any number of digits followed by a letter, any number of digits followed by a letter, and then a any number of digits. By using () I tell re that I want the match object to break it into the pieces that I want. So 2S24E16 into '2S' '24E' '16' in a match object to use.
0 Kudos
KellyLarvie
New Contributor
Well, at least I can say that I was getting there. Works great. I never heard about that "re" module before. I am also aware of the Extent Indicator, but for some reason, it will not highlight the appropriate section on the printed maps. I can't figure out why. If I do everything manually (setting up the indicator, zooming to another section) in ArcMap, it works fine and highlights the section just by zooming to the dfSection. It just won't highlight in the script. Everything in your script works though, and I am very happy that it is printing every map in the list correctly now. Do you have a reason why it was only printing the last item on the list correctly? I guess, I still don't see why it is working versus before. Is is because of that "re" module. Thanks for the help. I really appreciate it.


Do you think you could package this up as a tool and share it?  I would really love to have some way to zoom to TRS, but I have NO scripting ability. I would be so thankful!
0 Kudos