Problem Set 4 - GIS in Python

ENV 859 - Geospatial Data Analytics   |   Fall 2025   |   Instructor: John Fay  

 

Task Description
Set up Fetching the data for the exercise, instructions, & tips
Task 1 Using geoprocessing tools in Python
Task 2 Using geoprocessing tools in a loop
Task 3 Using ArcPy functions, classes, and geoprocessing tools
Task 4 Describing data in ArcPy; Creating script tools in ArcGIS Pro
Task 5 Working with ArcPy geometry objects
Submission Submitting your assignment

Set up

The following tasks refer to data in the zip file “ENV859_PS4.zip”, available here. This zip file should be uncompressed to your V: drive to create a V:\ENV859_PS4 workspace. This workspace contains the familiar Data, Scripts, Scratch, and Docs folders. Within the Data folder are the datasets needed to do the assignment. Save all scripts in the `Scripts` folder and write your code to send output files to the *scratch* folder unless otherwise specified.

When writing scripts in this exercise, there’s no need to include extensive front matter (e.g., the script name, description, name, date, etc.), but it may be helpful to add comments that briefly describe each step in your script so that we can offer partial credit.

When you’ve completed this assignment, compress your entire workspace folder into a single zip file, being sure to include any requested screen captures in your Docs folder. Rename the zip file using your NetID followed by “_PS4” (e.g. jpfay_PS4.zip), and submit it via the Assignments section on Canvas.

Some general tips to contemplate as you tackle this assignment:

  • Use intuitive names for your variables, and use lots of variables.

  • If you comment out lines for debugging, clean them up before submitting your final scripts.

  • The construction of a compound if statement requires fully written tests for all conditions.

    • Incorrect: If x == "something" or "another thing"
    • Correct: If x == "something" or x == "another thing"
  • For multiple tests in an if statement, consider when and where to use parentheses. The following yield different results!

    • if (x>1 or x<10 and x!=4) vs if (x>1 or x<10) and (x!=4) vs if (x>1) or (x<10 and x!=4)
  • Logic - thinking through the different results from and, or, ==, != :

    • if x != "A" or x != "B" → when x is “C” how does this test evaluate? What if x is “A”?
    • if x != "A" and x!= "B" → when x is “C” how does this test evaluate? What if x is “A”?

Task 1

Task 1 is a sequence of steps that lead you toward building an interactive Python scripts that implements the ArcGIS’s Buffer tool. Each step is used as a building block to the next step.

References:

1a. (5 pts.) Creating the initial buffer script

Write a Python script (Task1a.py) in your Scripts folder that buffers the Streams.shp feature class 1000 meters, writing the output to a new feature class called StrmBuff1km.shp located in the Scratch folder. Include in this script statements that do the following:

  • Creates a string variable that includes the path to the streams.shp feature class

  • Creates a second string variable that specifies the buffer distance as “1000 meters”

  • Creates a third string variable that sets the path and filename of where the buffer tool should write its output. This should be a file named StrmBuff1km.shp located in the Scratch folder.

  • Executes the buffer command such that the streams are buffered set buffer distance, in planar (not geodesic) terms, on both sides (the default), with a round end type (the default), and dissolved into a single feature (not the default).

  • At the end of your script, add the following line to display any messages, warnings, or errors to your Python interactive console:

    print(arcpy.GetMessages())
    

:point_right: NOTE: All inputs and output data references can be ‘hard-coded’ (meaning full pathnames can be typed in the code itself, not passed as user input variables).

1b. (3 pts.) Setting environment values in your script

Copy (or “Save as…”) the above script to a new file (Task1b.py) and modify it so that it includes the ArcPy environment settings that:

  • Sets the ArcPy workspace environment to the Data folder in the ENV859_PS4 folder;
  • Allows script outputs to be overwritten.

Also, since the workspace environment variable has been set to the data folder, you should also be able to just specify the stream feature class file name in the buffer tool, not the full path. Make that edit to your script, but keep the output file hard-coded to go to the scratch folder just as in the previous script.

:point_right: NOTE: When testing new scripts, it’s always wise to restart your interactive session or clear existing variables before running them.

1c. (5 pts.) Enabling user input

Copy the above script to a new file (Task1c.py) and restart your interactive session. Modify the new script so that:

  • The buffer distance and the output feature class values are both specified as user input variables rather than hard wired. (e.g. distance = sys.argv[] or distance = arcpy.GetParameterAsText()).
  • The user knows to enter buffer distance input in meters such that he/she can simply enter a numeric value (e.g. “1000”). But code your script so that this number is interpreted as meters, not decimal degrees, miles, km, etc. In other words, convert the user input integer into string that reflects a “linear unit” data type: “1000” becomes “1000 meters”.

The filename of the input stream feature class can remain static as in the previous Task2b.py script. You can assume that the user will input values without making a mistake (i.e., no need to do any error trapping).

You can also assume that the output filename supplied by the user will include the full file path, e.g. “V:\ENV859_PS4\Scratch\StrmBuff1km.shp

:point_right: NOTE: Recall that to test scripts using parameters for user input, as above, you need to create a “launch.json” file and add a line to the “configurations” dictionary with the key of “args” and your input values as strings inside a list (e.g., "args": ["1000", "V:/ENV859_PS4/Scratch/StrmBuff1km.shp"]). Also recall, that the script needs to be run in debug mode for the values in the launch.json file to be read into your script.

1d. (4 pts.) Adding auto-generated output names

Copy the above script to a new file (Task1d.py) and modify it so that the user continues to input the buffer distance as above. This time, however, the output feature class will be generated by the script. (In other words, remove it as a user input in your code.)

Set the buffer output to be saved into the Scratch folder and named buff_1000m.shp, where the “1000” in the name reflects whatever the user inputs as a distance. For example, if the user input 550 as the input buffer distance, the output shapefile would be buff_550m.shp. Again, you can assume that the user will enter a valid input so that no error trapping is required.

1e. (3 pts.) Iterating through buffer distances

Copy your Task1d.py to a new script called Task1e.py and tweak it so that, instead of asking the user for a single buffer distance, it buffers the streams distances of 100, 200, 300, 400, and 500 meters, each time renaming the outputs as above, i.e., with the distance in the file names. Continue to use the ArcPy Buffer command (not the “MultipleRing Buffer” tool), and strive for efficiency in your script, meaning avoid simply copying and pasting the Buffer command 5 times in your code. (Really this tweak should take very view edits to your previous script…)


Task 2

(20 pts) The data folder in the workspace provided contains a feature class of roads (roads.shp). In this exercise you will write a script that iterates through a set of road type codes, and for each code, extracts the road features having that code and writes them to a new output file using the Select_analysis tool.

The catch here is that the list of road types to process is supplied as a “multi-value string” (see link below). Thus, you need to parse this string into a list of road code items before you can iterate through them.

The following steps will guide you through the workflow, though you may want to construct (and debug) your script incrementally and not necessarily in the order described below.

References:

► Write a script (Task2.py) that:
  • Enables any existing ArcPy outputs to be overwritten
  • Creates a string variable containing the path to the Roads.shp feature class.
  • Simulates a ‘multi-value input’ by creating a string variable with the value “0;201;203” (i.e. a “multi-value string”) of the road type class values to be processed.
  • Creates a list variable by splitting the values between the semi-colons in the string created above so the three values each become an item in the list.
  • Loops through each item (i.e. each road type value) in this list, and in each iteration:
    • Selects features in the roads.shp feature class with the ROAD_TYPE attribute matching the value in the list, writing these selected features to a new, separate feature class, ideally with the “road type” value in the name, in the Scratch folder.
      (For example, the first iteration will select roads with a ROAD_TYPE = 0 and write them to a new file called “roads_0.shp”.)
    • Prints geoprocessing messages to the console (e.g. with arcpy.GetMessages() - see the last step in 1a.)

Use a ‘for’ loop to accomplish this, and ensure that each result produces a unique output (i.e. so that three distinct shapefiles are created). All outputs should be written to the Scratch folder.

:point_right:Tip: You may want to begin by writing code that runs the Select tool first, and when that runs well, then put that into a loop…
:point_right: Also: To get the proper syntax for a query expression, I find it easy to run the tool (e.g. the Select tool) in ArcGIS Pro and then examine the expression in SQL mode. That will reveal what needs to be in single, double, or no quotes….

:point_right: Lastly: Check your output: you should have three new feature classes in your Scratch folder…

🎖️CHALLENGE - 0 pts (bragging rights)
For full credit, use the Path object (from the pathlib package) to allow your code to use relative paths. Be sure, however, to convert these Path objects to strings before using them in any ArcPy geoprocessing tool. You will not lose any points by not doing this, but you will lose “bragging rights”.


Additional Tasks in Progress