Objective: To apply basic Python skills in an ArcGIS environment to broaden Model Builder and map analysis abilities.
In Lab 3, two image treatment methods were explored: the extraction of a portion of an image, and reclassification of the pixels of an image into 5 categories using "Natural Breaks". These treatments were first developed using Model Builder. Next, the Python code underlying the tools' execution was exported as Python Script, and adjusted to be applicable to any input file. This created a script that could support the application of the tools to many images in a short amount of time, with minimal user input. This approach makes the analysis and treatment of multiple images more efficient, and can be applied to any method designed in Model Builder.
Seven LANDSAT TIF files representing a single image separated into seven individual bands were provided. Figure 1 shows B10, the blue band on which the principle extraction is performed.
Figure 1: LANDSAT Band 10
Our first task is to design a model in Model Builder to extract a portion of a single layer. The code underlying the model is exported into Python Script, which is then adjusted for use with any file.
Figure 2: Segment Extraction Model
The portion of the image of interest (this was arbitrary for the current analysis) was framed in the display. Under the "Environments" tab in Model Builder, "Processing Extent" was set to "Same as Display", which allowed us to select only the pixels contained in our display for analysis. The "Times" tool, under the "Spatial Analyst -> Math" toolbox was used to simulate treatment of the image. 1 was selected as the constant with which to multiply the input TIF. This created a subset with the same values as the original TIF, covering an extent equivalent to the display extent we specified. The model is presented in Figure 2, its output in Figure 3.
Figure 3: Output of the Spatial Analyst Times Tool
Once the model was executable, the code underlying the model tools was exported, using Model -> Export -> To Python Script on the Model Builder main menu. The script was opened in the Notepad++ text editor. Figure 4 shows the script as it was exported from Model Builder. For a more detailed image of the script, see Figure 15. The general logic for approaching this problem is as follows:
arcpy.CheckOutExtension("spatial")
arcpy.env.snapRaster = "L5018024_02420100707_B10.TIF"
arcpy.env.extent = "377141.451949619 5711818.92176418 398738.109726267 5730339.79213926"
arcpy.env.overwriteOutput = True
:
theInputTIF = "L5018024_02420100707_B10.TIF"
theMultiplicationFactor = "1"
theOutputGrid = "F:\\Winter 2019\\ENVB530\\3.Lab3\\graphics\\other\\timesOut1"
arcpy.gp.Times_sa(theInputTIF, theMultiplicationFactor, theOutputGrid)
Figure 4: Extraction Python Script as Exported directly from Model Builder
The next portion of the lab focused on basic programming skills. This included an introduction to:
These will not be described in detail here, but their application to the problem addressed in this exercise will become evident as it is further explored.
The skills applied to extract the portion of the image above are now applied to "slice" the image into 5 classification levels, using the "Natural Breaks" algorithm. First, the model was prepared using Model Builder. Figure 5 shows the model, and Figure 6 shows the output when the Slice Model is run on the B10 layer of the LANDSAT image file.
Figure 5: Natural Breaks Model Builder
Figure 6: Output of Slice model applied to LANDSAT layer B10
The Python script developed for the single file was exported from Model Builder, and then adjusted to accommodate all seven files. First, a list is created containing the locations of all seven files. A file is opened to store Raster Data, specifically Standard Deviation (STD) and Mean values. A For Loop is developed to iterate through the files and perform the specified action, which was, in this case, "slicing" the provided rasters into 5 segments using the Natural Breaks algorithm. Inside the For Loop, new files are created to store the output of the GIS process, the "Slice" is executed, the STD and Mean Raster data are extracted, and written to the RasterData.txt file. A sample of the data is displayed below, in Figure 7. At this point, we exit the for loop and close the file. The raster output produced when running the code a single time is shown in Figures 8-14. More specifics on the approach to the problem can be found in the comment section of the code, seen in Figure 16.
Figure 7: Raster Data Python Code Output
Figure 8: Layer B10 after Natural Breaks algorithm application
Figure 9: Layer B20 after Natural Breaks algorithm application
Figure 10: Layer B30 after Natural Breaks algorithm application
Figure 11: Layer B40 after Natural Breaks algorithm application
Figure 12: Layer B50 after Natural Breaks algorithm application
Figure 13: Layer B60 after Natural Breaks algorithm application
Figure 14: Layer B70 after Natural Breaks algorithm application
The code in its current iteration is quite inflexible, as the file names have to be manually input by the user. A more robust and flexible code would access the folder where the files are held and iterate through the files automatically.
Ideas from others:
# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------------
# 1.Scheske.Chelsea.raster.calculator.script.py
# Created on: 2019-01-23 11:39:43.00000
# (generated by ArcGIS/ModelBuilder)
# Description: The following code extracts a section of the input TIF file according
# to the instructions given in "Set Geoprocessing environments -> arcpy.env.extent"
# multiplies the pixels by a given multiplication factor (see "Local Variables") and
# outputs the treated, extracted section in a new file
# ---------------------------------------------------------------------------
# Import arcpy module
import arcpy
# Check out any necessary licenses
arcpy.CheckOutExtension("spatial")
# Set Geoprocessing environments
arcpy.env.snapRaster = "L5018024_02420100707_B10.TIF"
arcpy.env.extent = "377141.451949619 5711818.92176418 398738.109726267 5730339.79213926"
# Overwrite pre-existing files
arcpy.env.overwriteOutput = True
# Local variables:
theInputTIF = "L5018024_02420100707_B10.TIF"
theMultiplicationFactor = "1"
theOutputGrid = "F:\\Winter 2019\\ENVB530\\3.Lab3\\graphics\\other\\timesOut1"
# Process: Times
arcpy.gp.Times_sa(theInputTIF, theMultiplicationFactor, theOutputGrid)
# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------------
# 7.Scheske.Chelsea.slice.script-1.py
# Created on: 2019-01-28 16:24:37.00000
# (generated by ArcGIS/ModelBuilder)
# Description: The following code performs Natural Breaks reclassification on
# the files in the local variable section, in this case, 7 TIF files representing
# layers of a single image. The code separates the data into 5 classes, based on
# the Natural Breaks algorithm, and saves the output files as new files. Raster
# data, specifically, the mean and standard deviation (STD) are extracted to a file
# "Raster Data" and saved.
# ---------------------------------------------------------------------------
# Import arcpy module
import arcpy
# Check out any necessary licenses
arcpy.CheckOutExtension("spatial")
# Overwrite pre-existing files
arcpy.env.overwriteOutput = True
# Local variables:
b10 = "L5018024_02420100707_B10.TIF"
b20 = "L5018024_02420100707_B20.TIF"
b30 = "L5018024_02420100707_B30.TIF"
b40 = "L5018024_02420100707_B40.TIF"
b50 = "L5018024_02420100707_B50.TIF"
b60 = "L5018024_02420100707_B60.TIF"
b70 = "L5018024_02420100707_B70.TIF"
# Create a list of the files
myFileList = [b10, b20, b30, b40, b50, b60, b70]
#Create a file to store the Raster Data
file = open("RasterData.txt", "w")
# Create a for loop to iterate through the list of files, perform the Natural Breaks reclassification, and retrieve the STD and MEAN
# Raster Data
for fileIterator in myFileList:
#Output files
NaturalBreaks = "F:\\Winter 2019\\ENVB530\\3.Lab3\\graphics\\other\\scriptResults\\New " + str(fileIterator)
#Process: Slice
arcpy.gp.Slice_sa(fileIterator, NaturalBreaks, "5", "NATURAL_BREAKS", "1")
#Get the geoprocessing result object and add to std and mean list
getSTDResult = arcpy.GetRasterProperties_management(NaturalBreaks, "STD")
getSTD = getSTDResult.getOutput(0)
getMeanResult = arcpy.GetRasterProperties_management(NaturalBreaks, "MEAN")
getMean = getMeanResult.getOutput(0)
#Write data to the file
file.write(str(fileIterator)+" Standard Deviation: "+getSTD+" Mean: "+getMean+"\n")
#Close the file when done
file.close()
References:
ArcGIS. (2016). Data Management Toolbox: Get Raster Properties. Retrieved from: http://desktop.arcgis.com/en/arcmap/10.3/tools/data-management-toolbox/get-raster-properties.htm. Accessed on: 26 January 2019.Done for Advanced GIS for Natural Resource Management, in the McGill University Department of Natural Resource Sciences, Professor Jeffrey Cardille