In class
In class-- Preface
Simple buffer
To practice using sample data and sample scripts, try this simple example of calling an ArcGIS buffer tool, which generates buffers around the input features by following these steps:
- If you don't have a C:/gispy directory, follow the instructions in the book to create it.
- Confirm that C:\gispy\data\ch01\park.shp exists.
- Launch ArcMap. Open the ArcGIS Python Window as shown in Figure 1.
Figure 1: The ArcGIS Python window embedded in ArcMap.
- Take a moment to become familiar with the Python prompt. Type each of the following lines of code at the Python prompt and observe the result:
print 'Hello'
5 + 6
x = 5
print x
x
- Copy the following line of code into the ArcGIS Python Window:
arcpy.env.workspace = 'C:/gispy/data/ch01/'
- Get a snack.
- Copy these lines of code into the ArcGIS Python Window. Be sure to copy the entirety of both lines, starting with 'arcpy' going all the way the end, including the right parenthesis:
arcpy.Buffer_analysis('park.shp', 'C:/gispy/scratch/parkBuffer.shp', '0.25 miles', 'OUTSIDE_ONLY', 'ROUND', 'ALL')
- Press the 'Enter' key and you'll see messages in the Python Help Panel that the buffering is occuring.
- When the process completes, confirm that an output buffer file is created and added to the map (Figure 2 shows with both the input and output layers added to the table of contents).
Figure 2 Input (light grey) and output (dark grey) from script Example 1.
- You should receive a message in the Python Window giving the name of the result file. If you get a red error message instead, then either the input data is not set up correctly or the Python statement wasn't copied correctly. If your result doesn't appear automatically on the map, check ArcCatalog to see if the input data (park.shp) is there in C:/gispy/data/ch01and see if parkBuffer.shp has been created in C:/gispy/scratch/.
- You have just called a tool from Python --this is just like running it from the ArcToolbox graphical user interface (GUI) such as the one shown in Figure 3. The items in the parentheses in the tool call are the
parameter values, the user input. Compare these parameters to the user input in Figure 3. Identify the four differences between the parameters used in our Python statement and those used in this GUI example.
Figure 3 Each input slot in the graphical user interface (GUI) for running the buffer tool corresponds to a parameter in the Python code blueprint. |
In class-- Introduction
add.py
- Download add.py by clicking on it and then choosing File > Save As...
- Open it with Pythonwin
- Right-click on the script in Windows Explorer
- Open with ... > Pythonwin
- If Pythonwin is not one of the listed choices, Choose Program... > Browse to > C:\Python**\Lib\site-packages\pythonwin and select Pythonwin.exe. You should only have to do this once for this machine, since the next time you want to do this, it will appear in the list of Open with choices . ** stands for the current version number of Python.
- Choose Window >Tile
- If you don't see the Interactive Window, click the Interactive Window icon and repeat number 3. (whichever window has the focus will be placed on top. Usually we want the script window on top.
- Run it by clicking Ctrl + R (or the run icon)
- Give input arguments: 5 6
- Look for the output in the Interactive Window.
- Uncomment the last 4 lines of the script by selecting them and clicking Alt+4
- Observe the output.
- Can you explain why the sum is 56?
|
Try Me The Python Interactive Window is a good place to try out individual code statements. The code snippets in the white box use built-in functions and illustrate some built-in exceptions. Type each of these lines of code in the PythonWin Interactive Window. You can only run ONE command at a time in this window, so type in one line of code at a time. Before you click the Return or Enter key, try to predict what will be printed. Did you get it right?
|
round(2.56)
x = round(2.56)
print x
x
help(round)
type("5")
help(int)
int("5")
inputData = "trees.shp"
FID = 145
type(FID)
FID
fid
avg = 92
type(avg)
avg = "A"
type(avg)
print = "inputData"
min(1, 2, 3)
type(min)
min = 5
min(1, 2, 3)
type(min)
"hi" in "hiho"
type(True)
dir(__builtins__) |
|
Tip There must be exactly one space between the prompt (>>>) and the input. If you ‘Backspace’ at the prompt before you enter your code, nothing will be printed. Press the Return or Enter key and the cursor will automatically be placed in the correct position, ready for the next line of code.
|
|
|
Exporting a model (if you have extra time, try this one)
- Download simple_tool.tbx and unzip it.
- Download COVER63p.shp from this link and unzip it.
- Place them in a new folder: C:/Temp/export_example
- In ArcCatalog, add toolbox and edit the model (buffer_tool)
- Export > To Script > Python
- Save as exported.py in C:/Temp/export_example
- Run the model with no arguments. Does it run successfully?
- Open the modelbuilder model for editing again. Make output a Model Parameter. (A P should appear near its oval.)
- Save the model and export as a Python script named exported2.py.
- Run the model again with no arguments. Look at the feedback bar. Did it run and exit successfully?
- Compare and contrast the 2 scripts (exported.py and exported2.py).
- Run the script with a 700 foot buffer on the input shapefile COVER63p.shp
Arguments:
"700 feet" "C:\\Temp\\export_example\\COVER63p.shp"
- Look at the feedback bar. Did it run and exit successfully?
- Check the directory for the buffer output.
|
In class-- Strings, lists, and tuples
Exploring string operations: Type each statement in the Interactive Window. After observing the results from all of these, answer the questions that follow.
|
x = “GIS”
x[0]
x[3]
“s” in x
len(x)
y = “rules”
x = x + y
len(x)
“s” in x
x[0:2]
x[:2]
x[2]
x[:-4]
x[3]
x
x.lower( )
x
y.startswith('ru')
print x,y
print x + y
numStr = "742"
numStr.zfill(8) |
Please respond to the following questions about the code you just ran:
- Why does x[3] give an error the 1st time but not the 2nd time?
- What does Python keyword "in" do? Does case matter?
- How could you change the statement x = x+y to print “GIS rules”?
- What’s the difference between x[:2], x[0:2], and x[2]?
- What does x[:-4] do?
- Does x.lower( ) change the value of x? If so, how?
- What's the difference between the output of print x,y and print x+y?
|
convertLat.py
- Download convertLat.py by clicking on it and then choosing File > Save As...
- Open it with an IDE.
- This script should convert the given degrees, minutes, seconds latitude to decimal degrees. Write one or more line of code for each double-hash (##) comment.
- The solution should be generic, not specific to the given input.
- Use the split method, indexing, the rstrip method, casting, mathematical operations, and string the format method.
- Here are some examples of the string 'split' and 'rstrip' methods:
>>> path = "C:/gispy/buffer/output.shp“
>>> p = path.split("/")
>>> print p
['C:', 'gispy', 'buffer', 'output.shp']
>>> path.rstrip(‘.shp’)
'C:/gispy/buffer/output' |
convertLat2.py
- Modify the convertLat.py script so that it takes one argument, the full path file name of a data file that contains the latitudes for a number of different points lats.txt by clicking on it and then choosing File > Save As...
- Rename convertLat.py as convertLat2.py.
- This script should take one argument, the full path for lat.txt, then it should open the file, read each latitude and convert the each degrees, minutes, seconds latitude to decimal degrees. (Don't forget to close the file.
To open a file, use the built-in open function and then loop through each line with. Something like this: inf = open(theFilePath, 'r') for line in inf: # do stuff to line inf.close()
- Put the code that converts things where it says "do stuff".
- Once you get this working, add code that counts the number of lines in the input.
- Then add code that appends the input latitudes to a list
- Then create convertLat3.py that does the same thing, but works on a different input file: lats2.csv
|
Print statements (if you have extra time, try this one)
Try these commands.
>>> dataFile = "counties.shp"
>>> FID = 862
>>> print dataFile, FID
>>> print "The first FID in", dataFile, "is", FID, "!"
>>> print "The first FID in"+ dataFile+ "is"+ FID + "!"
Repair the above statement.
>>> print "The first FID in {0} is {1}!".format( dataFile, FID )
Explain what the above statement did. |
Methods (if you have extra time, try this one)
- Type the following code: What does it return?
>>> path = "C:/gispy/buffer/output.shp"
>>> p = path.split("/")
>>> p
- Write a line of code that will make 'path' all caps.
- Type these commands. Then try to write a line of code that will sort mylistA, but not mylistB. Is it possible?
>>> mylistA = [5,23,7,-1]
>>> mylistB = mylistA
- Use the join string function to make a semicolon separated string from the list p (that you created in question 1).
|
Tuples (if you have extra time, try this one)
Type the following statements in the Interactive Window and discuss the results.
--------
>>> t = (5,8,9)
>>> t[0] = 1
>>> s = [5,8,9]
>>> r = 7, 3, 10
>>> s[0] = 1
>>> s
>>> t
>>> r
>>> type(s)
>>> type(t)
>>> type(r) |
In class-- arcpy tools
Wildfire damage assessment Write a script named 'buffer_clip.py' to find a 1 mile buffer around the fire damaged region ('special_regions.shp'); And then clip the park ('park.shp') on the buffer output. Refer to the ArcGIS help template to see how to call the clip tool. The input data is in C:/gispy/data/ch06. Write the output (both buffer and clip output) in C:/gispy/scratch
|
aggregate.py, call_shape2point.py, and buffer_clip.py
Inspect the scripts located here, here, and here. Identify the following:
- geoprocessing methods.
- geoprocessing properties.
- geoprocessing tool calls.
- toolbox aliases.
...
|
call_shape2point.py
- Download COVER63p.zip and unzip in C:/Temp.
- Download a script that converts Shapes to Points from here: ShapeToPoint.zip
- Download and unzip the toolbox to C:/Temp/ShapeToPoint/
- Follow Example 6.5 in the book to practice calling a custom toolbox.
|
In class-- Pseudocode
Fix it: The conditional code blocks in each of the following examples either contains a logic error that will make it fail in certain cases or is less efficient than it should be or has both these problems. Read the intended purposes and the pseudocode and then answer the following for each:
- Will the fault cause it to work incorrectly in some cases or is it just inefficient?
- If it contains a logic error, in what case(s) would it give incorrect results?
- Identify changes to the conditional clauses that would improve efficiency and/or correct logic errors.
A. Point Statistics
Purpose: For each shapefile in a given directory, check the geometry type of the shapefile. If the geometry type is a point, calculate the point statistics and print the results, otherwise report that the input in not a point shapefile.
FOR each shapefile in the directory
GET geometry type
IF geometry type is a point THEN
CALCULATE point statistics
END IF
IF geometry type is not a point THEN
PRINT "The input file is not a point shapefile”
ENDIF
ENDFOR
B. Currency conversion
Purpose: Convert US Dollars to Euro or vice versa, depending on the input of currency amount and unit.
GET currency amount
GET currency unit
IF currency unit is Euro THEN
CALL convert Euros to US Dollars
PRINT the results
ENDIF
IF currency unit is US Dollars THEN
CALL convert US Dollars to EUROS
PRINT the results
ELSE
PRINT the input units must be Euros or US Dollars
ENDIF
C. Polygon to Raster
Purpose: If the given input is a polygon shapefile, perform polygon to raster conversion using the given field to assign raster values, otherwise inform the user that the conversion did not occur.
GET input file
GET field
IF input file is a shapefile THEN
CALL convert polygon to raster using field to assign raster values.
ELSE IF input file geometry is polygon THEN
CALL convert polygon to raster using field to assign raster values.
ELSE
PRINT Warning: Conversion not performed.
PRINT Input file data type |
Challenge: Insert one or more line of Python code for each pseudocode comment. (excluding the line that says "#CALL geoprocessing operation"
# contour_select.py
# Purpose: Create contours from a raster dataset if the format is JPEG, TIFF, or IMAGINE Image.
#Create geoprocessing object called gp
#SET geoprocessing workspace to "C:/gipsy"
#SET input raster to "Raster1"
#Create describe object for input raster
#Create a format list containing "JPEG", "TIFF", and "IMAGINE Image"
#IF input raster data type is 'RasterDataset' and the format is in the format list
#CALL geoprocessing operation (this will call the spatial analysis coutour tool. You can leave this as is for now)
#ELSE
#PRINT a warning that the data will not be processed because it is not raster or it is not one of the required formats.
#ENDIF
|
Solutions to Word document pseudocode exercises linked here.
In class-- Conditional statements
Topics: conditional statements, logic errors involving conditional statements
conditionalSound.py
Inspect the script conditionalSound.py shown below. Then predict what sounds will play if with these input conditions:
a. No arguments.
b. C:/gispy/data/ch09/park.shp
c. C:/gispy/data/ch09/tree.gif
d. C:/gispy/data/ch09/jack.jpg
e. C:/gispy/data/ch09/xy1.txt
Check your answers by running the script in this Chapter 9 sample scripts directory. C:\gispy\sample_scripts\ch09\conditionalSoundExercise
|
Distance Conversion Pseudocode
Suppose you want to write pseudocode to convert miles to km and km to miles and handle user input of 2, 1, or 0 arguments as follows:
Arguments: 50 miles
>>> 50 miles is equivalent to 80.0 kilometers.
Arguments: 100
>>> Warning: No distance unit provided. Assuming input is in miles.
100.0 miles is equivalent to 160.0 kilometers.
Arguments:
>>> Usage: <numeric_distance> <distance_unit(miles or km)>
The pseudocode below would break, if the user provides less than 2 arguments. Follow these steps to approach the problem:
- Add to the pseudocode below, so checks in case of 'no user arguments'.
- Add pseudocode to part 1 to handle the '1 argument' case.
|
GET numeric dist from args
GET unit from args
IF unit is miles THEN
COMPUTE km
PRINT results
ELSE
COMPUTE miles
PRINT results
ENDIF |
|
In class-- Looping
1. listfc_os.py Write a script to print only the names of the file in C:/gispy/data/ch19 that are shapefiles (print name and :] ), txt files (name and print :[ ), or dbf files (print name and :o ). Use a FOR-loop.
# os.listdir example:
import os
path = 'C:/gispy/data/ch19'
files = os.listdir(path)
2. listfc_os2.py Rewrite listfc_os.py to print each file's index in the list along with the file name.
Sample output:
5 aa.txt :[
9 abc.dbf :o
13 abc.shp :]
16 AccessPoints.dbf :o
20 AccessPoints.shp :]
25 address.txt :[
27 b.txt :[
|
nestedTables.txt
Write pseudocode for the following problem:
For each table in each workspace in a directory, print the file name of the table. |
In class-- Batch processing
Topic: geoprocessing enumeration methods (ListRaster, ListFields, etc.)
listrasters_enum.py
- Modify the code so that it prints a list of the raster datasets in the mdb called:
"C:/Temp/ncrast_geodatabase/ncrast.mdb".
- Modify the code to list only the rasters whose names start with 'land'
# listrasters_enum.py
import arcpy
arcpy.env.workspace = "C:/Temp/Duck"
files = arcpy.ListFeatureClasses( )
for file in files:
print file
print "All done." |
|
List and copy
- List all the point feature classes in C:/gispy/data/ch10/tester.gdb whose names start with 's'.
- Call arcpy.CreateFileGDB_management('C:/gipsy/scratch/', 'out.gdb') to create a new gdb.
- Write copies the point feature classes whose names start with 's' from C:/gispy/data/ch10/tester.gdb and copies them to C:/gispy/scratch/out.gdb. The destination needs to have a slash between the. destination = destWorkspace + '/' + fc
|
Exploring Field objects: Type each statement in the Interactive Window. After observing the results from all of these, answer the questions that follow.
|
import arcpy
fc = "C:/gispy/data/ch10/park.shp"
fs = arcpy.ListFields(fc)
f = fs[0]
f
f.name
f.type
f.length
f = fs[1]
f.name
f.isNullable
len(fs) |
- Which one of these statements tells you how many fields the attribute table has?
- Name four field properties.
- How can you find the name of the 3rd field?
|
check4Field.py
Write a script to checks if C:/gispy/data/ch10/park.shp has a field 'COVER'.
The field names are 'FID', 'Shape', 'COVER', and 'RECNO',
So, if your input argument is 'COVER', the answer should be:
>>> Field 'COVER' found.
If time allows, continue to part 2:
check4FieldV2.py
Make your script more robust by with the following changes:
1. Make it
case in-sensitive.
So, if your input argument is 'coveR', the answer should be:
>>> Field 'coveR' found.
2. Make the file name and field name arguments.
3. Modify the script so that it lets you know if the field is not found:
So, f your input argument is 'MEH', the answer should be:
>>> Field 'MEH' not found.
|
In class-- Debugging
Topic: Finding syntax errors, exceptions, and logic errors, using a debugger
why_debug.py This script finds all kml files in a directory. Each kml file may have a corresponding file with the same basename (Example, a.shp goes with a.kml). It could be either a shapefile or geodatabase feature class. The purpose of this script is to determine if the corresponding file is a shapefile, feature class, or doesn't exist. But the script has a problem! Can you find it using the debugger?
|
agg_debug1.py Should aggregate polyons and produce the output files listed below. But it has problems. Use the debugger to find and repair them.
C:/gispy/scratch/park100agg.shp
C:/gispy/scratch/park300agg.shp
C:/gispy/scratch/park500agg.shp
C:/gispy/scratch/park700agg.shp
C:/gispy/scratch/park900agg.shp
|
superman_debug.py Should give you 3 chances to guess who Clark Kent is.
If you guess incorrectly three times it should print:
>>> Haha! You don't know Superman!
If you guess correctly (Superman), it should print:
>>> You are right!
Use the debugger to correct the syntax and logic errors.
Demo of how it should work.
|
slope_debug2.py
slope = "Undefined"
rise = 1
Run = 3
if run > 0:
print "Rise:", rise, "Run:", run
slope = rise/run
print "Slope:", slope
|
In class-- More Looping
lineLength.py
Task: Check the length of each line in each Python file in a directory and each of its subdirectory in a directory
Approach: Divide and conquer! Each number group will have a separate task.
- Work on it on paper alone first.
- Gather with the other people in your group (such as, all of the other #1’s, all of the other #2's, ...).
- Compare answers
- Write it in Pythonwin and try it (if possible).
- Convert your code to a function (printLineLength (from group 1), getFullFileNames (from group 2), and pyORdir (from group 3)). Groups 1 and 3 take a file name as an argument. Group 2 takes a directory name as arguments. Group 1 don't return anything. Group 2 return a list of names. Group 3 return "py", "dir", or "other".
- Let me know when you have it working.
- Go over each of the individual pieces with whole class.
- Return to your original group of 4.
- Write lineLength.py by merging your code to solve the task.
Group 1 members: Open a “test.py” for reading. Print the length of each line in the file.
Group 2 members: Print a list of full path names of the files in "C:/gispy/data/ch12/wTest/" . Use list comprehension to make a full path list from a base name list.
Group 3 members: Check if an input file is a Python script or a directory. (Hint: There’s an os.path.isdir(path) method.)
Group 4 members: Write pseudocode for the overall task. Assume you have three function: printLineLength (from group 1), getFullFileNames (from group 2), and pyORdir (from group 3)
Test data
----------------------------------
walkPics.py Download and unzip this directory which contains pictures and several subdirectories.
|
In class-- Error Handling
tryExcept.py This script will help you understand how code flows when there are try/except commands in the script. Inspect this script and predict the answers (without running the script) to the questions at the bottom of the script. Then check your answers by running the script.
|
fileOpen_try.py
import sys
filename = sys.argv[1]
fileObj = open(filename,"r")
print fileObj.readlines( ) |
- Copy the code above and save it as fileOpen.py.
- Predict which named exception will occur if you run the script with no arguments.
- Run the script with no arguments and pat yourself on the back if you got it right; otherwise, say 'tisk-tisk'.
- Next, compose a short verse, limerick, or ode to Python and save it in a text file named 'poem.txt'
Here's an example:
Scripterwocky
`Twas brillig, and the Python lists
Did join and pop-le in the loop:
All-splitsy were the string literals,
And the boolean values were true. |
- Run fileOpen.py with 'C:/gispy/data/ch19/poem.txt' as the argument.
- Explain what this script does.
- Run fileOpen.py with a text file that doesn't exist as this argument, perhaps 'C:/gispy/data/ch19/bogus.txt'.
- Which named exception does it throw?
|
slope_try.py
- Save slope_try.py and step through in the debugger for each pair of arguments. Note the behavior in each case.
- Use arguments: 12 6
- Use arguments: 12 0
- Use arguments: twelve six
- Use argument: 12
import sys
rise = sys.argv[1]
run = sys.argv[2]
try:
print "Rise:", rise, "Run:", run
slope = float(rise)/float(run)
print "Slope = rise/run"
except ZeroDivisionError:
slope = "Undefined (line is vertical) "
except ValueError:
print "Usage: <numeric rise> <numeric run>"
slope = "Not found"
print "Slope:", slope
|
try_buffer.py
- Copy try_buffer.py shown below to make a new script.
- Make a bogus shapefile by creating a txt document and then renaming it bogus.shp and putting it in C:/gispy/scratch. Set the argument to C:/gispy/scratch/bogus.shp
- Choose 'step through in the debugger' and watch what the script does as you run it.
- Which statements were printed? Why?
- Copy cover.shp from C:\gispy\sample_scripts\ch14\ to C:/gispy/scratch.
- Set the argument to C:/gispy/scratch/cover.shp
- Step through again.
- Again, which statements were printed and why?
# try_buffer.py
# Input: full path name of a shapefile.
import arcpy, os, sys arcpy.overwriteOutput = True
inputFile = sys.argv[1]
try:
buffer = os.path.splitext(inputFile)[0] + 'Buffer.shp'
arcpy.Buffer_Analysis(inputFile, buffer, "1 mile")
print '{0} created.'.format(buffer)
except:
print arcpy.GetMessages( )
print "Exiting the script now"
|
buffer_loop_try.py
- Copy buffer_loop_try.py, shown below, to make a new scripts.
- Make a bogus shapefile by creating a txt document and then renaming it to C:/Temp/aaadata.shp.
- Copy cover.shp from C:/gispy/data/ch14 to C:/gispy/scratch too.
- Predict what will happen when you run the script, then run it with no debugging.
- Run the script again using the 'step through in debugger' option.
- Ideally, we want the script to create buffers for all of the valid files and just print a warning if it fails for one of the files. try and except are in the wrong positions for this to happen. Repair the script.
- Predict what will happen when you run the script and run it again with no debugging.
- Run the script again stepping through in the debugger. Use the watch window to watch the value of fc.
import arcpy, sys
arcpy.overwriteOutput = 0
arcpy.env.workspace = "C:/Temp"
fcs = arcpy.ListFeatureClasses()
try:
for fc in fcs:
buffer = fc[:-4] + "_buffer.shp"
arcpy.Buffer_analysis(fc, buffer, "1 mile")
print "Created: ", buffer
except arcpy.ExecuteError:
print arcpy.GetMessages( )
|
buffer_loop_try2.py
- Run the code shown below and observe what happens.
- Run the code by stepping through in the debugger to see the flow.
- Repair the mistake on line 11 (buffDist = str(x) + "mile").
- Run the code by stepping through in the debugger again to see the flow.
- Watch the value of x in the watch window.
- Repair the mistake on line 16 (x = x + 1).
- Run the script again and confirm that there are 10 output files.
import arcpy, sys
arcpy.env.overwriteOutput = True
arcpy.env.workspace = "C:/gispy/scratch/"
fc = 'cover.shp'
x = 1
while x <= 10:
try:
buffer = fc[:-4] + "_buffer.shp"
buffDist = str(x) + "mile"
arcpy.Buffer_analysis(fc, buffer, buffDist)
print "Created: ", buffer
except arcpy.ExecuteError:
print arcpy.GetMessages( )
x = x + 1
|
table_to_raster_debug.py
import arcpy, os, sys
try:
myDir = sys.argv[2]
try:
arcpy.env.overwriteOutput = True
arcpy.CheckOutExtension("spatial")
# Set variables
arcpy.env.workspace = myDir.replace("\\", "/")
rasterList = ""
InX = "VELD1"
inY = "VELD2
clipFeatures = "dump_s1_UTM_ED50.shp"
valueField = "VELD3"
tempLayer = "tempLayer"
sumRaster = "sumRaster"
tables = arcpy.ListTables( )
while tables
rootName = os.path.splitext(table)[0]
pointFeatures = "clipped_" + rootName + ".shp"
raster = "rast" + rootName
arcpy.MakeXYEventLayer_management(table, inX, inY, tempLayer)
arcpy.Clip_analysis(tempLayer, clipFeatures, pointFeatures)
arcpy.PointToRaster_conversion(pointFeatures, valueField, raster, "MOST_FREQUENT", "NONE", "25")
rasterList = rasterList + raster + " VALUE 1;"
arcpy.WeightedSum_sa(rasterList, sumRaster)
expect:
print arcpy.GetMessages( )
except IndexError:
pint "Usage: Directory path for input tables"
print "Example: C:/Temp/table_to_raster"
|
In class-- Procedures ^__^
printProcedures.py contains 2 function definitions and calls these functions (as examples).
1. A list of file names is given in the code (testList = ['a.shp', 'a.txt', 'cRaster']). Write code to loop through testList and print only names that end with .shp.
2. When that is working, put the looping code that you wrote for #1 inside a function definition. Pass a list in as an argument.
3. Write a line of code to call the function using the given test list of file names (testList).
(The idea is to replace the code you wrote for #1 with a function definition and call.) |
add5 -- practice defining and calling a function that returns a value.
1. Add another function to the script named add5 that adds five to the numeric argument passed into it and returns the result.
2. Call the function using an argument of 10 and set x to the result. Then print x.
3. Set a variable z to a float value and call the function using z as the argument and set y to the result. Then print y.
|
proc_practice.py Follow the instructions below. Be sure to repair the spacing as needed.
1. Add this function to a script.
def professorTalk():
print "Blah blah blah"
Call the function.
2. Add this function to the same script.
def sitInClass():
print "snore"
Call the function.
3. Add this function to the same script.
def favDessert( theDessert):
print "My favorite dessert is", theDessert
Call the function.
4. Add this function to the same script.
def printCar(make,model, year):
print "I drive a", year, make, model + "."
Call the function.
5. Correct the indendation in this function and add it to the same script.
def sitInClass(quality):
if quality = "interesting":
return "learn"
else:
return "snore"
print "All done."
Call the function. Step through in the debugger to see the flow.
6. Write a function to print a message passed in (by the caller) in both the Interactive Window and the geoprocessing window. Call the function.
7. Write a function that takes a full path file name as an argument and returns a Python list of field names. Call the prodecure, store the return value in a variable, and print the returned list of names and the documentation string.
|
functions.zip
zipall.py Modify zipAll.py so that it is a function.
The function should take one argument: the directory whose contents are to be zipped.
Call the method.
Returning a value
Amend zipAllFunction so that it returns the name of the archive file that was created
Optional Arguments Amend your zipAll.py function so that it has an optional loop to delete all the original files after it creates the archive file
Returning Multiple Values
Define a function that returns the extent of a shapefile before it is clipped, clips it based on a smaller file, then returns the size of the new file
Call this function, printing each extent as follows:
Old extent of in feature: xxxxxxxxxxxx
New extent of in feature: xxxxxxxxxxxx
|
slope_stepin.py
- Repair the syntax errors in slope_stepin.py
- Step through the script using the step over button. Then step through using step in at the function call (findSlope) and step out in the middle of the function definition (slope = rise/run)
Explain the difference between step in/out/over.
- Set a breakpoint on lines 4 and 10. Go through the script 2 times, once using the step-through in debugger mode and once using the run in debugger mode. Then turn off all break points and repeat the run in debugger mode.
Explain the difference between the 2 modes.
|
defprint.py
def printMyYears(start, stop):
yrs = range(start, stop + 1)
for yr in yrs:
print yr
printMyYears(1920,1926)
|
- Modify the given script, so that it has a function called myprint.
- The purpose of myprint is to have a function that will print a given message in both PythonWin and in the geoprocessing Window when it’s called from ArcGIS
- myprint should take one argument: the string message to be printed
- Call the function with a message.
|
In class-- Cursors
Exploring cursor objects Part 1 (Search cursors): Copy C:\gispy\data\ch01\park.shp to the scratch directory to create C:\gispy\scratch\park.shp. Then, type each statement in the Interactive Window (Except for the comments) and answer the questions.
|
import arcpy
fc = "C:/gispy/scratch/park.shp"
fds = arcpy.ListFields(fc)
fds
numFields = len(fds)
sc = arcpy.da.SearchCursor(fc, fds)
fieldNames = [f.name for f in fds]
sc = arcpy.da.SearchCursor(fc, fieldNames)
sc
row = sc.next()
row[0]
row[2]
row = sc.next()
row[0]
sc.reset( )
row = sc.next( )
row[0]
row[1]
del sc
fieldNames = ["SHAPE@"]
sc = arcpy.da.SearchCursor(fc, fieldNames)
row = sc.next()
row[0].extent
row[0].centroid
row[0].extent
type(row[0].centroid)
#What type of object does row[0].centroid #return?
row[0].centroid.X
del sc
row = sc.next( )
|
|
sc = arcpy.da.SearchCursor(fc, "*", "COVER = 'other'")
row = sc.next( )
row[0]
row[2]
sc = arcpy.da.SearchCursor(fc, "*", "COVER <> 'woods'")
for row in sc:
print row[2]
# what does <> mean here in the statement above?
sc =arcpy.da.SearchCursor(fc, "*", "FID > 200")
row = sc.next()
row[0]
|
- What is row?
- What does sc.reset() do?
- How can you find the area of the polygon associated with each?
- What does del do?
- What do you think this statement does sc = arcpy.da.SearchCursor(fc, "*","COVER = 'orch'")?
- What does <> mean in a where clause?
- Use a search cursor with a where_clause to find the RECNO the row FID is 22.
- How can you get the value of the field COVER if you have a row object?
- How can you get the value of a field if you don't know the name of the field ahead of time?
|
Exploring cursors objects Part 2 (insert & update cursors): If you skipped part 1, you'll need to create "C:\gispy\scratch\park.shp" by copying it from C:\gispy\data\ch01\park.shp. Otherwise, simply continue and type each statement in the Interactive Window (Except for the comments), predicting the results as you go.
|
import arcpy
fc = "C:/gispy/scratch/park.shp"
ic = arcpy.da.InsertCursor(fc, ["COVER"])
ic.insertRow(["lake"])
del ic
with arcpy.da.InsertCursor(fc, ["COVER"]) as ic:
... for i in range(4):
........ ic.insertRow(["lake"])
uc = arcpy.da.UpdateCursor(fc, "*")
for row in uc:
....if row[2] == "lake":
.........row[3] = 1000
.........uc.updateRow(row)
del uc
# Refresh view in ArcCatalog.
|
Exploring cursors objects Part 3 Geometric insertions. Copy C:\gispy\data\ch17\fires.shp to C:\gispy\scratch\fires.shp.
|
import arcpy
fc = "C:/gispy/scratch/fires.shp"
ic = arcpy.da.InsertCursor(fc, ["FireId", "SHAPE@"] )
myPoint = arcpy.Point(-70.1, 42.07)
newRow = (500000, myPoint)
ic.insertRow(newRow)
del ic |
|
In class-- Dictionaries
Explore dictionaries Type these lines of code in the interactive window and discuss the results.
|
>>> myD = {0:"woods", 1:"park", 5:"orch"}
>>> for key in myD:
............ print key
>>> for value in myD.values():
............ print value
>>> myD.has_key(3)
>>> myD.has_key(1)
>>> myD[1]
>>> myD[1] = "other"
>>> myD
>>> myList = [0,1,5]
>>> myList[2]
>>> myD[2]
>>> myD[1]
>>> myD
>>> myD[3] = "lake"
>>> myD
>>> myD2 = {}
>>> myD2["strK"] = 5
>>> myD2
|
- What does myD2 = {} do?
- Explain the difference between what happened when you typed myD[1] = "other" and when you typed myD[3] = "lake".
- Explain the difference between myList[2] and myD[2].
- Write a line of code to add an item with key "London" and value "Heathrow" into myD.
- Write a line of code to add an item with key "beer" and value ["Bass", "Corona", "Dunkle"] to myD.
- Write a line of code to append "Pale Ale" list whose key is "beer".
- Set the value of x to "5 hrs". Write a line of code to add an item with key "sleep" and value a list containing one item, x.
|
drinkdict.py Create a dictionary where drinks are the key and a list of people who favor that drink are the value, by completing the code in the given script. The existing code prompts you for 10 people's names and favorite drinks.
Example output:
{ ‘tea’: [’Carlo‘, ’Bo‘],
’water‘: [’Jamie‘, ’Ouise’],
'beer': [’Ali', ’Mayu', ’Geddy', ’Chang'],
'sweet tea': [’Shayo', ’John']}
General format for creating dictionaries that use lists as values:
# If the key is already in the list, append.
if key in dict:
dict[key].append(value)
else: # Otherwise create a new list
dict[key] = [value]
#drinkdict.py
dict={}
for i in range(10):
name = raw_input("Name:")
drink = raw_input(name +"'s fav. drink:") # insert dictionary code here.
print dict
|
|
table2dict.py
Write a script to do the following:
- Get an input file name.
- Get a list of field names objects.
- Use get a list of field names (You can use list comprehension).
- Remove the 'Shape' field from the field name list (if it's there).
- Create a search cursor for an input file.
- Create an empty dictionary.
- For each row, add an item to the dictionary that has a key of the input file's 'FID' and the rest of the non-shape fields the value. For example input C:/gispy/data/ch02/park.shp, the dictionary would look something like this:
{0: (u'woods', 1.0), 1: (u'woods', 2.0), 2: (u'woods', 3.0), 3: (u'woods', 4.0), 4: (u'woods', 5.0), 5: (u'other', 6.0), 6: (u'woods', 7.0), 7: (u'orch', 8.0), 8: (u'woods', 9.0), 9: (u'woods', 10.0), 10: (u'orch', 11.0), 11: (u'orch', 12.0), 12: (u'other', 13.0), and so forth...
|
In class-- Reading and Writing Text Files
Exploring file objects: Type each statement in the Interactive Window (Except for the comments) and discuss the results.
f = open("C:/gispy/scratch/test.txt", 'w')
f.write('a')
f.write('b')
f.write(2)
mylist = ["a","b","c"]
f.write(str(3))
f.write(mylist)
f.writelines(mylist)
f.close( )
Now look at the file you just created.
Why does f.write(2) fail?
Why does f.write(mylist) fail?
Describe an easy way to write each item in mylist on its own line in a file.
f = open("C:/gispy/scratch/test.txt", 'w')
f.write('xyz\n')
f.write('a\nbcd\ne\nf\ng')
f.close( )
Look at your output file.
What happens when you open an existing file in 'w' mode and write things in it?
Explain why the text is not all on one line.
inf = open("C:/gispy/scratch/test.txt", 'r')
print inf.readline()
print inf.readline()
print inf.read(2)
inf.seek(0)
print inf.readline()
inf.seek(0)
print inf.readlines()
inf.seek(0)
print inf.read()
inf.close()
inf.open("C:/nofile.txt", 'r')
What is the difference between the file methods readline, read(2), and readlines?
What does seek(0) do?
Give an example of when an IOError exception is thrown.
|
|
rdu_forest1.py Part 1
Read/write Write a script that opens "C:/gispy/data/ch19/RDUforest.txt", reads it and writes it to an output file named RDUout.txt in the "C:/gispy/scratch" directory.
|
rdu_forest2.py Part 2
Read/modify/write Suppose a mistake was made in calculating the dbh. It should be the square root of the value in the file. E.g., 25 should be 5. Modify the code from Part 1 so that it makes this change in the output, RDUout2.txt. (Hint: the built-in math module has a sqrt method. For example math.sqrt(16) returns 4.
|
rdu_forest3.py Part 3
Delete rows. Modify rdu_forest1.py to read "C:/gispy/data/ch19/RDUforest.txt" and write it to RDUout3.txt deleting all of the records that are not Loblolly pines (species LP). Hint: Instead of thinking in terms of deleting, think about what you DO want to write.
|
rdu_forest4.py Part 4
Delete a column. Modify rdu_forest1.py to read "C:/gispy/data/ch19/RDUforest.txt" and write it to RDUout4.txt. This time, delete the plot column.
|
ipcc2Esri.py (Intergovernmental Panel on Climate Change):
ipcc2Esri.py converts an IPCC .dat format file to Esri ASCII .txt format.
# Then call Esri's ASCIItoRaster tool to convert the ascii file to a GRID raster. Insert lines of code to replace the ### comments. run the script on precipitation6190.dat.
solution script
|
rduRead.py:
- Write a script to read each line of RDU_forest.txt. Print each line to the interactive window.
- Print only the DBH (tree height measurement) of each entry.
- Find the sum of the DBH.
|
In class-- Modules
User-defined modules:
1. Copy and save sortString.py and listManager.py defined BELOW. Save them both in C:/gispy/scratch. sortString calls one of the functions in listManager, but you need to add code to sortString for this to work correctly. The output should look like this:
>>> ['fid', 'fid', 'alt', 'lat', 'long', 'fid', 'lat'] |
If you add the code and it still doesn't work, you may need to click reload while your focus is on listManager.py.
2. Now add one line of code to sortString.py to sort mylist (returned from string2List) and then add another to print the list.
>>> ['alt', 'fid', 'fid', 'fid', 'lat', 'lat', 'long'] |
3. Finally, add code to sortString.py to turn the sorted list back into a string by calling the other listManager function. Print the string.
>>> alt;fid;fid;fid;lat;lat;long |
4. Add the function uniqueList given below to listManager.py
def uniqueList(L):
"""Get list with only unique entries"""
S = set(L)
uniqueL = list(S)
return uniqueL |
5. In sortString.py, add a line of code to call the uniqueList function on mylist.
6. Add print ("Hehe") to listManager.py (outside of any functions).
7. Without reloading listManager.py, run sortString.py. Does it run to completion? Does Hehe print?
8. Reload listManager.py, using the reload button. Does Hehe print?
9. Run sortString.py now. Does it run to completion? |
mystring = "fid;fid;alt;lat;long;fid;lat"
delimiter = ";" # set delimiter
mylist = listManager.string2List(delimiter, mystring)
print mylist |
def string2List(delimiter, s):
"""Take a delimited string and return a list"""
L = s.split(delimiter)
return L
def list2String(delimiter, L):
"""Take a list and return a delimited string"""
stringL = [str(i) for i in L]
s = delimiter.join(stringL)
return s |
In class-- File GUI's
Playing with tkFileDialog:
>>> import tkFileDialog
>>> fc = tkFileDialog.askopenfilename()
>>> print fc
>>> fc = tkFileDialog.askopenfile() # select a python script or a text file.
>>> print fc
>>> print fc.readlines( )
>>> fc = tkFileDialog.askopenfilename(filetypes = [("spam", "*.py"), ("Text files", "*.txt")],
title="Boogiewoogie", initialdir = "C:/gispy/scratch", multiple=True)
>>> print fc
>>> print fc[0] # Print only the first item in the tuple |
In class-- Code Reuse: Classes
Thinking in OOP:
Plan the OOP components for a script that would support daily air traffic analysis of airlines and their flights. The script will use Airline, Flight, and Seat objects. Identify properties and methods for each of these objects based on the following description:
Each airline name is stored along with a set of numbered flights. The origin and destination airports of each flight are stored and can be used to estimate the length of flight paths. Flight departure and arrival times are stored, so that the flight duration can be derived. Each flight has a set of seats organized in rows and columns. Each seat has a fare rate and a status (occupied or vacant) which can be modified when a new reservation is made. The class (first, business, or economy) can be determined based on the row. Flights can be added and removed. The capacity, the load factor, and the total fare for a flight can be calculated. The total number of flights for each airline for a day can also be derived.
Airline properties (2):
Flight properties (5):
Seat properties (4):
Airline methods (3):
Flight methods (5):
Seat methods (2): |
parcelClass.py See ### comments in code for instructions. Do them in order as numbered. Get it running after each step
----------------------------------
callExcelInClass.py # modify this one.
excel_lib.py # download into same directory as callExcelInClass.py, but don't modify
See ### comments in code for instructions. Do them in order as numbered. Get it running after you do #1 and 2. Run it to see how it works. They try #3 and 4.
In class-- 18a
testMessage.mxd
Public Sub PrintMessage()
Dim myMessage As String
myMessage = “Test message”
MsgBox myMessage
End Sub |
- Open ArcMap and go to the VBA editor (Alt+F11)
- Right-click on Project
- Insert a module
- Place the given subroutine in the module.
- Save the document.
- Test the subroutine:
- Alt+F8
- Use the Macro in: combo box to select the project where your function is stored.
- In the Macro name: text box, select your macro.
- Click Run.
- Right-click on Project
- Insert a userform
- Drag a button from the Controls toolbox onto the user form.
- Double click on the button on the form. You'll see function wrappers for a button click event function. In here call your new function. The code should look something like this:
Private Sub CommandButton1_Click()
Call Module1.PrintMessage
End Sub
- Test the CommandButton1 subroutine by placing the cursor inside the function and selecting the run arrow.
|
In class-- HTML
HTML tags
1. Open a new Browser window to this page HTML 5 Tutorial page and click on "Try it yourself":
https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_video_autoplay
2. Replace the code in the left window with the code found on the page linked here.
3. Click 'Submit Code' and observe the results in the right window.
4. Experiment with this code to answer the following questions.
- How do you create a kittens image the same size as the angry face? Like this:
- How do you modify the table to have a third row, like this:
Month |
Savings |
January |
$100 |
February |
$80 |
- How do you make a table with borders? without?
Month |
Savings |
January |
$100 |
- How can you make a numbered list that starts with 50 with 4 items, like this?
- Coffee
- Tea
- Milk
- Mango juice
- What's the difference between HTML tags for a bulleted list and code for a numbered list?
- Remove the <br /> tag between Hey and you. What does a <br /> tag do?
- How can you create a link to the AAG page (http://www.aag.org/) labeled AAG like this:
AAG
|
HTML Spacing
1. Go back to the 'Try it yourself' HTML tutorial page.
2. Replace the code in the left window with the code found on the page linked here.
3. Click 'Edit and Click Me>>' and observe the results in the right window.
4. Experiment with this code to do the following.
- Wrap preformatting tags around sentence 1. Preformatting tags look like this: <pre> stuff to preformat </pre>. This should make the gap appear, so that it looks something like this:
(1) I have a BIG gap in my middle.
- Make a bigger gap in sentence (3) using the tag instead of preformatting. It should look something like this:
(3) I have a SMALL gap in my middle.
- Use <br> tags to put two empty lines between sentences (2) and (3), like this:
(2) I
don't
care.
(3) I have a SMALL gap in my middle.
- Put sentence (2) all on one line like this:
I don't care.
- Can you understand the Python code in the results Window? Wrap preformatting tags around the Python code (before and after these #####). This can be done on the Wolfware message board too because it's HTML enabled.
|
In class-- Write HTML
writeSmallHTML.py
1. Confirm that park.png is in C:\gispy\data\ch20\pics
2. Save writeSmallHTML.py to C:\gispy\scratch.
3. Run the script in its current state and view the resulting html page.
4. Search for the '##' signs and follow the instructions in these comments to create a page like the one shown below. You will need to call 3 functions defined in the script to get a list of cover types in the data, find the unique cover types, and create an html bulleted list of unique cover types. You will also need to add and modify some strings that encode HTML tags.
|
In class-- Fetch and uncompress
wakeURL.py
1. Copy C:\gispy\sample_scripts\ch20\BeautifulSoup.py to C:/gispy/scratch
and save wakeURL.py in C:/gispy/scratch
2. Add code to import 3 built-in modules that the code uses (in addition to os, which is already being imported) and import BeautifulSoup.
3. Find the url assignment statement (line 40), check the url to be sure it's current. Modify if needed.
4. Run the script in its current state and view the resulting print statements.
5. Search for the ## signs and add code there to make functions work and then to call them.
|
In class-- KML
Exploring KML soup:
Copy C:\gispy\sample_scripts\ch20\BeautifulSoup.py to C:/gispy/scratch. Type each statement in the Interactive Window and answer the questions.
|
import os
os.getcwd()
import BeautifulSoup
os.chdir('C:/gispy/scratch')
import BeautifulSoup
mystr = """<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><name>Bubba's Tofu Gumbo</name><description>Tofu Gumbo and Zydeco!<br />Score: 97</description><Point><coordinates>-90,30,0</coordinates></Point></Placemark><Placemark><name>Joe Bob's Good Cookin'</name><description>The best tree top grits n' greens restaurant south of the Mason-Dixon line.<br />Score: 94</description><Point><coordinates>-78,35,0</coordinates></Point></Placemark></Document></kml>"""
soup = BeautifulSoup.BeautifulSoup(mystr)
h = soup.prettify( )
print h
t = soup.find('description')
type(t)
t.name
t.attrs
t.contents
t.contents[0]
ts = soup.findAll('placemark')
for g in ts:
print g.contents[0] |
- What data type is t?
- What does the 'find' method do?
- What's the difference between t.contents and t.contents[0]?
- What does a KML description tag contain?
- How many KML placemarks are in this file?
- What does a placemark tag contain?
|
parseKMLpts_inclass.py
1. Copy C:\gispy\sample_scripts\ch20\BeautifulSoup.py to C:/gispy/scratch.
2. Save parseKMLpts_inclass.py in C:/gispy/scratch.
3. Search for the ### signs in the Python script. Add code as instructed in the comments. When complete the script parses the driving stops from the kml and creates an output shapefile.
|
In class-- arcpy mapping module
Exploring the arcpy MapDocument: Copy the ch24 data directory (found at C:\gispy\data\ch24) into the scratch directory (C:\gispy\scratch). Then open 'states.mxd' found in C:\gispy\scratch\ch24\maps. Next, open the Python window embedded in ArcMap. Now, type each statement in the Python Window (except for the comments) and answer the questions.
|
mxd = arcpy.mapping.MapDocument('CURRENT')
mxd
(#View File > 'Map document properties' and see the values written there)
mxd.author
mxd.author = 'Moi!'
(#Open map properties and see change)
mxd.activeView
mxd.activeView = 'PAGE_LAYOUT'
mxd.title
mxd.title = 'Eastern US'
arcpy.RefreshActiveView( )
mxd.filePath
mxd.dateSaved
mxd.relativePaths
mxd.relativePaths = False
mxd.relativePaths
mxd.filePath
p = 'C:/gispy/scratch/states2.mxd'
mxd.filePath = p
mxd.save( )
mxd.saveACopy(p) |
- What is mxd?
- What does mxd.relativePaths mean?
- How can you change mxd.filePath from a Python script?
- How do you get or change the author of the map from a Python script?
- How can you force the map to refresh to show changes you've made in the current session?
- Keep ArcMap open for now. Try the following in the PythonWin Interactive Window. Note...which of three calls to arcpy.mapping.MapDocument work/don't work.
>>> import arcpy
#Attempt #1
>>> mxd1 = arcpy.mapping.MapDocument('CURRENT')
#Attempt #2
>>> arcpy.env.workspace = "C:/gispy/scratch/ch24/maps/"
>>> arcpy.env.workspace
>>> mapName = 'states.mxd'
>>> mxd2 = arcpy.mapping.MapDocument(mapName)
# Attempt #3
>>> mapName = "C:/gispy/scratch/ch24/maps/states.mxd"
>>> mxd3 = arcpy.mapping.MapDocument(mapName)
# make a change to the map in ArcMap (e.g., change the title)
>>> mxd3.title = "Smart map"
# and try to save the map.
>>> mxd3.save()
>>> del mxd3
- Close ArcMap and try the following in the PythonWin interactive Window. What does it do?
import os
os.startfile('C:/gispy/scratch/ch24/maps/landCover.mxd')
- a) Where can you find a complete list of map properties and methods b) How do you know which properties can be modified from a Python script?
|
Exploring the arcpy DataFrame and Layer objects:
If you haven't already done so during the above exercise, copy the ch24 data directory (found at C:\gispy\data\ch24) into the scratch directory (C:\gispy\scratch). Then open 'states.mxd' found in C:\gispy\scratch\ch24\maps.
Now, type each statement in the Python Window (except for the comments) and answer the questions.
|
mxd = arcpy.mapping.MapDocument('CURRENT')
dfs = arcpy.mapping.ListDataFrames(mxd) #get a list of first data frame
dfs
df = dfs[0]
df.name
df2 = dfs[1]
df.displayUnits
ext = df2.extent
ext.YMin
arcpy.SelectLayerByAttribute_management('VA')
df2.zoomToSelectedFeatures( )
for df in dfs:
print df
for df in dfs:
print df.name
layers = arcpy.mapping.ListLayers(mxd, "*", df)
for layer in layers:
print layer
for layer in layers:
print layer.name
layer.isFeatureLayer
layer.isRasterLayer
e = layer.getExtent()
e.XMax
df. extent = e
for layer in layers:
x = layer
print x
x.dataSource
for layer in layers
x = layer.name
print x
x.dataSource
|
- How can you get a list of ALL the layers in map? (hint: the last two arguments in ListLayers are optional)
- How can you use Python to zoom?
- How can you get the 5th layer in the 3rd dataframe (if the map has 3 or more data frames and the third frame has 5 or more layers)?
- Where can you find a complete list of layer properties and methods?
|
listFeatureLayers
1. By hand, add raster "C:\gispy\data\ch24\otherData\getty_rast" to the 'C:/gispy/scratch/ch24/maps/states.mxd' map. Save the map.
2.
Add to the code below, to print the names of the feature type layers in a map (not the raster layers).
Hint1: Need nested looping to loop through the data frames and the layers.
Hint2: layers have a Boolean property called isFeatureLayer
import arcpy
mapName = 'C:/gispy/scratch/ch24/maps/states.mxd'
mxd = arcpy.mapping.MapDocument(mapName)
dfs = arcpy.mapping.ListDataFrames(mxd)
for df in dfs:
print "Frame " + df.name
layers = arcpy.mapping.ListLayers(mxd, "*", df) |
addLayer1.py Run this script.
- Note that if the map document doesn't already exist, you will get an error. Change the name of the map document in the script to one that you have on your machine.
- Note that an error occurs if "C:/Temp/Cover63p3.lyr" doesn't exist.
- Add these lines of code to the script to create the .lyr file and try running it again.
fileName = "C:/Temp/Cover63p.shp"
inMemLyr = "GettysburgLandCover"
onDiskLyr = "C:/Temp/Cover63p.lyr"
arcpy.MakeFeatureLayer_management(fileName, inMemLyr)
arcpy.SaveToLayerFile_management(inMemLyr, onDiskLyr) |
In class-- Messaging
printPoly.py part 1 You will create a script tool and use it to observe the difference between running a script in Pythonwin and running a script tool from ArcToolbox.
- Launch ArcCatalog now and move on to step 2, so that it's open by the time you need it.
- printPoly.py Write a script which prints all of the polygon feature classes in a directory.
Allow the user to pass in one argument, the directory.
- In PythonWin, run printPoly.py. It takes one argument: a workspace directory path.
- In ArcCatalog, create a new toolbox mytoolbox.tbx in C:/Temp (right-click on the directory. Then new > toolbox)
- Add the script to mytoolbox.tbx (right-click on the toolbox add > script).
- Use the wizard to set up your script tool:
Set the name and label as printShapes. (Always set name and label to the same value.)
Set the script to take one input parameter, a directory path of datatype String.
(You can always go back and modify these properties by right-clicking on the script tool and choosing properties)
- Run the script tool by double clicking on it in mytoolbox.tbx. Enter a directory that has some data.
Make a note of the results. Do you see the shapefiles listed?
|
printPoly.py part 2
- Add a line of code to the script so that it prints the output in both the Pythonwin Interactive window and the geoprocessing window.
- Run the script in Pythonwin again. Does it print the messages twice there?
- Run the script tool again from ArcCatalog again. Do you see the output statements?
|
printPoly.py part 3
- Open the script properties. (Right-click on the script tool in ArcCatalog)
- Click on the source tab.
- Check the box: "Show command window when executing scripts."
- Place this line of code at the end of your script: raw_input( "Click ENTER to close the window")
raw_input is a built-in Python function that waits for user input. The command window will stay open until the user clicks ENTER.
Note:
If run a script with a raw_input command without showing the command window, it will hang with no explanation and you have to cancel the run.
|
fieldCheck.py script tool
- Save the script fieldCheck.py
- Add a script tool to the mytoolbox.tbx
- Test the new script tool.
- Build a model following the steps for this example given on the messaging page.
|
In class-- Script Tools
Create a script tool
Part 1: Get some hands-on experience by following these steps:
- Copy sample script 'textLister.py' from C:\gispy\sample_scripts\ch23\scripts to C:\gispy\scratch. Then run in PythonWin. It should print text file names:
>>> cfactors.txt
crop_yield.txt
poem.txt
RDUforest.txt
report.txt
wheatYield.txt
xyData2.txt
- In ArcCatalog, browse to 'C:\gispy\scratch\' and create a new toolbox in this directory. To do so, right-click and create a new toolbox (New > Toolbox). Rename it as 'practice.tbx'.
- Add a script tool to the new toolbox by right-clicking on 'practice.tbx' in ArcCatalog and choosing Add > Script... This launches a Script Tool wizard to customize the script tool step by step.
- In the first pane of the wizard, set the script 'Name' and 'Label' to 'printTextFiles'. The label appears in the ArcCatalog table of contents; It can have spaces, but the name can't. For simplicity, you can use the same value for both. Check 'Store relative path names'. This is an important choice, as we'll discuss shortly. Click 'Next >' to go to the next wizard pane.
- We want this script tool to point to 'textLister.py'. To set the 'Script File', browse to 'textLister.py' in 'C:\gispy\scratch\'. Leave the default values for the check boxes. Running a script tool in-process improves efficiency, so this is usually the preferred approach. Click 'Next >' to proceed.
- The final pane pertains to script parameters. Since 'textLister.py' needs no arguments, we'll leave this page as-is. Finally, click 'Finish' to exit the wizard. You can always come back and change any of the choices made during the initial setup by right-clicking on the script tool and selecting 'Properties...'.
- Check that a script tool named 'printTextFiles' appears in ArcCatalog.
- Run the tool by double-clicking on it. A GUI with several buttons and a help panel appears. The left panel states 'This tool has no parameters'. This is what we expect to see, since we didn't set up any parameters.
- Click 'OK' to run the script tool. When the script tool run has completed, it launches a window to report success or failure. We refer to this as the 'Geoprocessing Window'.
What prints in the 'Geoprocessing Window'? Compare this to what printed when you ran the script in PythonWin and hypothesize why there's a difference.
Part 2: Add a button to access your tool:
1.‘Customize’ > ‘Customize mode…’
2.‘Commands’ tab
3.Under Categories, scroll to select [Geoprocessing tool]
4.Add Tools… Browse to toolbox > Select script tool in toolbox > Add (Script tool appears under Commands )
5.Drag script tool from under Commands to an ArcMap toolbar
6.Before closing the ‘Customize’ dialog, right-click on the tool in the toolbar to display text and image and modify these as desired. (can also be done by reopening the customize dialog) |
Break a script tool
- Right click on the 'printTextFiles' script tool, select 'Properties...', and then select the 'Source' tab. Note the Python script specified by the 'Script file' path on this tab ('C:\gispy\scratch\textLister.py'). Close the script tool properties by clicking 'OK'.
- Browse to 'textLister.py' and open it. Add another message to 'textLister.py' and save the script:
arcpy.AddMessage('***I like kale***!')
- Double click on the script tool to run it again. Do you see a change?
- Rename 'textLister.py' to 'textLister2.py' and run the script tool again. What happens?
- Rename the script back to its original name, 'textLister.py' and run the script tool again. Is it working? Why?
- Now make a directory 'C:\gispy\scratch\breakStuff' and move 'textLister.py' down into it. Run the script tool again. What happens?
- Copy the toolbox to your 'Documents' directory. Run the script tool again. Does it work? Why?
- Move textLister.py to the 'Documents' directory. Run the script tool again. Does it work? Why?
|
Running scripts in the command window and in Arc's Python Window.
1. listPrinters.py takes 2 arguments. Run it in PythonWin to see how it works. Suggested args:
C:\Python27\ArcGIS10.4\python "Available printers" "Printer name"
2. Search for python.exe. Use the path to this executable, the name of the script and two argument to run listPrinters.py on the command line. It should look something like this. (Executable path and script path may vary)
"Available printers" "Printer name"
3. Run Arc Python Window -- Confirm that it won't work as is.
4. Use variables to make it work in the Arcpy Window. The Python code will look something like this:
>>> firstMessage = "Available printers"
>>> secMessage = "Printer name: "
>>> import arcpy, sys
... print firstMessage #First message
... for printerName in arcpy.mapping.ListPrinterNames():
... print secMessage + ": "+printerName |
In class-- Script Tools Parameter Properties 1 (Adding multivalue tool output to the map)
Script Tools Parameter Properties 1
(Adding multivalue tool output to the map)
- Copy C:\gispy\sample_scripts\ch23\scripts\bufferallv1.py to C:/gispy/scratch.
- Put some vector data in the scratch directory. Copy the contents of "C:\gispy\data\ch02" into C:\gispy\scratch
- Run the code in PythonWin to see what output it creates.
- Delete the output.
- Add code to bufferallv1.py so that it takes 2 input arguments-- the workspace and the buffer distance. It should retain the existing functionality of returning the semicolon delimited string of output names. Notice that you'll need to change the index since it will now be the 3rd (zero-based) parameter, not the first.
- Create a toolbox and a new script tool pointing to bufferallv1.py. Set up 3 appropriate parameters:
1) An input Folder type for the workspace parameter.
2) An input Linear Unit type for the buffer distance. The Linear Unit data type will pass in the numeric value and the unit separated by a space.
3) An derived output multivalue Feature Class type for the feature classes that are created by the script.
- Set default values for the input parameters to C:/gispy/scratch and 0.2 miles.
- Test the Script Tool in ArcMap.
|
In class-- Script Tools Parameter Properties 2
Use Filters
- Write a script that prints the index and value of the arguments that it receives in both PythonWin and Geoprocessing Window.
- Create a script tool in C:\gispy\scratch and use filters to allow the user to:
- Choose the word 'float' or 'integer' from a combobox.
- Choose a value between [-10, 10].
- Choose one or more polygon feature classes.
- Set the default value as the relative path to park.shp in the chapter 2 data directory in gispy.
Printed output should look something like this:
Argument 0: C:\gispy\scratch\printArgs.py
Argument 1: float
Argument 2: -4
Argument 3: C:\gispy\ch02\data\park.shp;C:\gispy\data\ch11\USA.shp
|
selectOrchards.py
The park cover types in park.shp include woods, orchards, park, and others. Fruit farmers would like a table including only those polygons with a cover type of orch. Write a script to perform a Table Select that will generate this table. Call the output table orchards.dbf.
|
In class-- Script Tools Parameter Properties 3
Script tool argument 'obtained from' property
countOccurrences2.py: Counts the number of occurrences of a particular value of a particular field in a file. It takes 3 argument: a file name, a field name, and a field value.
- Modify the script so that it prints the count in both the Interactive Window and the geoprocessing window.
- Create a script tool for countOccurrences2.py that passes in 3 arguments:
- The first arg (file name) should be a required table. Set the default value to C:/Temp/Cover63p.shp.
- The second argument (field name) should be required input obtained from the first argument.
- The third argument (field value) should be a required string. Set the default value to woods.
|
Setting symbology
feature2point.py finds the centroids of an input polygon feature class. Suppose there are information booths at each of these centroids. We want to display the results using a blue information symbol encoded in information.lyr.
- Download and save information.lyr in C:/Temp. This will provide the symbology for your output.
- Create a script tool for feature2point.py with 2 arguments:
- The first arg (file name) should be a required feature class. Set the default value to C:/Temp/Cover63p.shp.
- The second argument (field name) should be derived output feature class. Set the symbology to the full path of the information layer file (C:\Temp\ information.lyr).
- Add a last line of code to the script (use SetParameterAsText to link it to the second parameter you set up in the script tool) so that output file will be added to the map after the script tool is run.
|
Add the following scripts as script tools in a toolbox. Run them to observe the progressor in action and answer the questions below each:
simpleDefaultProgressor.py
- What does time.sleep(5) do?
- How can you change the progressor label to 'He he, ho ho'?
- How do you print messages in the geoprocessing window?
- How do you set the position of the default progressor?
simpleStepProgressor.py
- How do you set the position of the step progressor?
- What happens if you set your 'max' to 100*(len(files) - 1) instead of len(files) - 1 in the second script? Add time.sleep statements so that you can see what's going on.
- What happens if you don't provide upper and lower bounds ('min' and 'max') or 'interval' when you set up the step progressor?
bigDemo.py
- How do you count down with the step progressor? (See sample code in 'bigDemo.py' to inform this response.)
|
In class-- ToolValidator
updateMessage
1. Create a script tool (no need to point to an actual script--this is just an empty shell). Set up 2 parameters:
- Favorite number, a required input with datatype long.
- Favorite color a required input with datatype string.
2. Modify the updateMessages method in the ToolValidator class so that if the user enters a negative number in the first parameter, the tool gives an error and tells the users to enter a positive number. Check to be sure the value has been altered before the number is checked.
Pseudocode:
IF the first parameter has been altered THEN
IF the first parameter's value is less than zero THEN
Set the error message to remind the bozo running the tool to use a positive number
ENDIF
ENDIF
ToolValidator Help
Parameter properties: altered, value, ...
Parameter methods: setErrorMessage(theError)
|
getUniqueValues.py
1. Write a script which gets the unique values for a given field in a given GIS table. For the moment, hard-code the table and field. The script is started for you here. Fill in code where you see ###
import arcpy
fc = "C:/gispy/data/ch01park.shp"
fieldname = "COVER"
sc = ### Get a search cursor.
valueList = [ ]
### Loop through the rows; get the value for field name for the current row; append it to the list.
uniqueValueSet = set(valueList) #Casts valueList to a set (only unique values retained)
uniqueList = ### Cast uniqueValueSet back to a list.
print uniqueList
2. Create a script tool (no need to point to an actual script--this is just an empty shell). Set up 3 parameters:
- The first arg (file name) should be a required feature class type.
- The second argument (field name) should be required input field type obtained from the first argument.
- The third argument (field value) should be a required string.
3. Use parts of getUniqueValues to modify the updateParameters method in the ToolValidator class so that the 3rd parameter is updated to a unique list of values in the selected field for the selected feature class. The method is started for you here. Fill in code where you see ###
def updateParameters(self): """Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parmater has been changed.""" if ### The 2nd parameter is altered: fc = str(self.params[0].value) #Feature class is the first parameter fieldname = str( ###use the 2nd parameter ) #Has to be cast to string, since it's a field object. sc = ### Get a search cursor. valueList = [] ### Loop through rows and get the values for the selected field name and append to valuelist. uniqueValueSet = set(valueList) #Cast valueList to a set (only unique values retained) uniqueList = ### Cast uniqueValueSet back to a list. self.params[2].filter.list = ### This should be your unique list. return
Test the tool by selecting C:/gispy/data/ch01/park.shp for the first parameter. The 2nd parameter should automatically get populated with a list of the field names in park.shp. Select COVER for the second parameter. The third parameter should get dynamically populated with a list of the landcover types in park.shp. If it does, congratulations--you got it working! |
In class-- R & rpy2
Review
1. Rewrite these statements so that they use the minimum number of arguments necessary to achieve the same results.
arcpy.Buffer_analysis(fctrace, fctrace[:-4] + "_buffer.shp", "500 Feet", "FULL", "ROUND", "ALL")
dist = arcpy.sa.EucDistance(inSourceData, “#”, “25”,"#")
2. Rewrite the following lines of code to address the width problems.
arcpy.MakeFeatureLayer_management(infile, layerName, "", "", "FID FID VISIBLE NONE;Shape Shape VISIBLE NONE;STUDENT_ID STUDENT_ID VISIBLE NONE;FIRST_INST FIRST_INST VISIBLE NONE;FIRST_STAT FIRST_STAT VISIBLE NONE;FIRST_CURR FIRST_CURR VISIBLE NONE;FIRST_HS_D FIRST_HS_D VISIBLE NONE;FIRST_HS_N FIRST_HS_N VISIBLE NONE")
arcpy.CreateTin_3d(newtin, "PROJCS['NAD_1983_StatePlane_South_Carolina_FIPS_3900_Feet_Intl',GEOGCS['GCS_North_American_1983',DATUM['D_North_American_1983',SPHEROID['GRS_1980',6378137.0,298.257222101]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]],PROJECTION['Lambert_Conformal_Conic'],PARAMETER['False_Easting',2000000.0],PARAMETER['False_Northing',0.0],PARAMETER['Central_Meridian',-81.0],PARAMETER['Standard_Parallel_1',32.5],PARAMETER['Standard_Parallel_2',34.83333333333334],PARAMETER['Latitude_Of_Origin',31.83333333333333],UNIT['Foot',0.3048]]", newshp, "Shape.Z masspoints <None>", "DELAUNAY")
3. Rewrite this code to make use of triple quotes.
outfile.write(" 0\n")
outfile.write("SECTION\n")
outfile.write(" 2\n")
outfile.write("HEADER\n") # Header Section
outfile.write(" 9\n")
4. Run this code and see the results. Then rewrite using string formatting. Confirm that your results match the original.
count1 = 4
count = 2
count3 = "6"
print "Out of " + str(count1) + " segments, " + str(count) + " require cleaning and " + str(count2) + " received no signal." |
Procedures Review
Run this script and confirm that you understand what it does. It creates a dictionary from the fields of a table. The dictionary is like this. {field1:[value1,value2, value3], field2:[value1,value2, value3]}
Next follow these steps to break the function into two parts so that each of the parts could be used independently if desired.
1. Write a function that returns a list of fieldNames given a table and a list of field names to avoid (such as FID and shape). Start with the following code.
def getFields(tableName, avoidList):
'''Returns a list of field names not in avoidList'''
return fieldsList
2. Call the function to confirm that it works using this code:
fields = getFields(inputFile,["FID", "Shape"] )
print fields
3. Rewrite and rename the original function so that it takes a table and a list of fields and returns a dictionary with a list of the values in the table for each field. The dictionary will be like this: {field1:[value1,value2, value3], field2:[value1,value2, value3]}
Start with this code and take part of the original function to fill it in:
def getValues( tableName, fieldsList = [] ):
'''Return table values for give fields in dictionary {fieldname:[valList]}'''
return d
4. Confirm that it workds by using this code
dict1 = PullOutTimeSeriesXYZ("C:/Temp/COVER63p.shp")
fields = getFields(inputFile,["FID", "Shape"] )
dict2 = getValues(inputFile, fields)
if dict1 == dict2:
print "Hurray"
|
|
Additional materials
ADDING output to a map with a script tool 2
1. Modify buffer_tool2.py so that it takes 2 arguments: input file name and buffer distance.
And so that it creates an output file name based on the input file name.
2. Create a script tool pointing to the script that passes in the first two arguments and adds the output file to the map automatically. |
aggregate.py, call_shape2point.py, and buffer_clip.py answers
Inspect the scripts located here, here, and here. Identify the following:
- geoprocessing methods.
SetProduct, AddToolbox, AggregatePolygons_management, ShapesToPnts_s2p, buffer_analysis, clip_analysis, GetMessages()
- geoprocessing properties.
overwriteoutput, workspace
- geoprocessing tool calls.
AggregatePolygons_management, ShapesToPnts_s2p, buffer_analysis
- toolbox aliases.
management, s2p, analysis
...
|
Distance Conversion Pseudocode answers
- Add pseudocode to handle the 'no user arguments' case
GET number of arguments
IF number of arguments is one
PRINT usage
EXIT code
ENDIF
GET numeric distance
GET distance unit
IF unit is miles THEN
COMPUTE kilometers
PRINT results
ELSE
COMPUTE miles
PRINT results
ENDIF
- Add pseudocode to handle the '1 user argument' case
GET number of arguments
IF number of arguments is one
PRINT usage
EXIT code
ENDIF
IF number of arguments is two
SET distance unit to default
ELSE
GET distance unit from arguments
ENDIF
GET numeric distance from arguments
IF unit is miles THEN
COMPUTE kilometers
PRINT results
ELSE
COMPUTE miles
PRINT results
The resulting Python script:
import sys
listLength = len(sys.argv)
if listLength < 2:
print "Usage: <numeric_distance> <distance_unit(miles or km)>"
sys.exit(0) #exit the script
if listLength == 2:
unit = "miles".
print "Warning: No distance unit provided. Assuming input is in miles."
else:
unit = sys.argv[2]
dist = float(sys.argv[1])
if unit == "miles":
output = float(dist)*1.6
print dist, unit, "is equivalent to", output, "kilometers."
else:
output = float(dist)*.62
print dist, unit, "is equivalent to", output, "miles."
|
-------
nestedLooping1.py
nestedLooping2.py |
batch_feature2raster.py
A GIS analyst posed the following question on the Esri forum:
...I have 100’s of feature classes files that I need to process. I process these feature classes, through “FeatureToRaster_conversion”, then write them out to a different folder with a chosen name. I’ve tried to modify my code to loop through input files based on examples but get errors. The problem is, I don’t know what I’m doing with Python... |
He posted a script like the one below. He wants to generate one raster for each bus route in the mdb, ncrast.shp. He wants the output raster to be generated using the 'cat' field. Start modifying the script towards solving his problem by following these steps:
- Replace the ### comments with code
- Change the variable name inFeatures to the variable you're using to iterate through the loop.
- Identify which other variable needs to change each time the code loops.
import arcpy
InFeatures ="C:/Temp/busroute1.shp"
InField = "cat"
OutRaster = "C:/Temp/output/busroute1.shp"
arcpy.env.workspace = "C:/Temp/ncshape.mdb"
print InFeatures
print InField
print OutRaster
print "All done."
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 | #pig_latin.py
#Purpose: Translate English phrases to pig latin.
#Input: English word or phrase.
#Output: Pig latin phrase.
#Example: Scram or else -> 'amScray oray elseay'
import sys
#Remove script path.
sys.argv.pop(0)
def myfunction("test"):
'''docstring goes here'''
pass
wordList = sys.argv
vowelList = ["a","e","i","o","u","y"]
pigLatinList = []
#Convert each word to pig latin and add it to the list.
for word in wordList:
index = 0
#Find the index of the first vowel.
for letter in word:
if letter in vowelList:
#break out of the smallest enclosing for loop.
break
index = index + 1
#Example: word = 'Scram', front = 'am'
front = word[index:len(word)]
#Example: word = 'Scram', back = 'Scr' + 'ay'
back = word[:index] + "ay"
pigLatinList.append( front + back )
print "English phrase: {0}.".format(phrase)
print "Pig Latin Translation: {0}".format(" ".join(pigLatinList))
|