Customizing script tool behavior |
|
|
Release 9.3
Last modified June 3, 2010 |
Print all topics in : "Creating script tools" |
Note:
This topic was updated for 9.3.1.
You can provide custom behavior for your script tool dialog such as enabling and disabling of parameters, providing default values, and updating string keywords. To add custom behavior for your script tool, right-click the script tool, click Properties, and click the Validation tab. On the Validation panel, you can provide Python code that implements a Python class named ToolValidator. By adding Python code, you can
The ToolValidator class is a block of Python code that geoprocessing uses to control how the tool dialog and command line change based on user input. The ToolValidator class is also used to describe the output data of the tool, which is important for building models. System tools (those provided by ESRI) have always had the capability to react to user input and subsequently modify the tool dialog as described above. Until ArcGIS 9.3, script tools did not have this capability—the tool dialog was static and the output of the script tool did not contain an updated description, making it difficult to work with script tools in ModelBuilder. With version 9.3, the ToolValidator class was added to give you all the capabilities of a system tool.
Even though the ToolValidator class is implemented using Python code, you can still use any scripting language to do the actual work of the tool.
ToolValidator is a Python class that contains three methods: initializeParameters(self), updateParameters(self), and updateMessages(self). It also contains the standard Python class initialization method, __init__(self). To view and edit the ToolValidator class, right-click your script tool, click Properties, then click the Validation tab. The illustration below shows the Validation tab with the default ToolValidator class code. Click the Edit button to edit the code and, after editing, click OK or Apply to apply your edits.
| Method | Description |
| __init__ | Initializes the ToolValidator class. Import any libraries (such as arcgisscripting) you need and initialize the object (self). |
| initializeParameters | Called once when the tool dialog first opens, or when the tool is first used in command line. |
| updateParameters | Called each time the user changes a parameter on the tool dialog or the command line. After returning from updateParameters, geoprocessing calls its internal validation routine. |
| updateMessages | Called after returning from the internal validation routine. You can examine the messages created from internal validation and change them if desired. |
NOTE: Do not call other geoprocessing tools or open datasets in ToolValidator because the ToolValidator class is executed each time a user changes something on the tool dialog. Use geoprocessing tools in your script—not in ToolValidator.
NOTE: You must implement the three methods, initializeParameters(self), updateParameters(self), and updateMessages(self). They don't have to do anything except return, but they must be provided for ToolValidator to be a valid Python class.
def updateParameters(self):
# If the option to use a weights file is selected (the user chose
# "Get Spatial Weights From File", enable the parameter for specifying
# the file, otherwise disable it
#
if self.params[3].Value == "Get Spatial Weights From File":
self.params[8].Enabled = 1
else:
self.params[8].Enabled = 0
self.params[8].Enabled = 1 self.params[8].Enabled = bool(1) self.params[8].Enabled = True # Note upper case: "True", not "true"
def updateParameters(self):
# Set the default distance threshold to 1/100 of the larger of the width
# or height of the extent of the input features. Do not set if there is no
# input dataset yet, or the user has set a specific distance (Altered is true).
#
import string
if self.params[0].Value:
if not self.params[6].Altered:
extent = string.split(self.GP.Describe (self.params[0].Value).extent, " ")
width = float(extent[2]) - float(extent[0])
height = float(extent[3]) - float(extent[1])
if width > height:
self.params[6].Value = width / 100
else:
self.params[6].Value = height / 100
return
class ToolValidator:
def __init__(self):
import arcgisscripting as ARC
self.GP = ARC.create(9.3)
self.params = self.GP.getparameterinfo()
def initializeParameters(self):
return
def updateParameters(self):
# Provide default values for "file format type" and
# "feature type in file"
#
if not self.params[1].Altered:
self.params[1].Value = "OLD_FORMAT"
if not self.params[2].Altered:
self.params[2].Value = "POINT"
# Update the value list filter of the "feature type in file" parameter
# depending on the type of file (old vs. new format) input
#
if self.params[1].Value == "OLD_FORMAT":
self.params[2].Filter.List = ["POINT", "LINE", "POLYGON"]
elif self.params[1].Value == "NEW_FORMAT":
self.params[2].Filter.List = ["POINT", "LINE", "POLYGON", "POINT_WITH_ANNO", "LINE_WITH_ANNO", "POLYGON_WITH_ANNO"]
return
def updateMessages(self):
return
def updateParameters(self):
# Update the value list filter in the second parameter based on the
# shape type in the first parameter
#
stringFilter = self.params[1].Filter
fc = self.params[0].Value
if fc:
shapetype = self.GP.Describe(fc).ShapeType.lower()
if shapetype == "point" or shapetype == "multipoint":
stringFilter.List = ["RED", "GREEN", "BLUE"]
elif shapetype == "polygon":
stringFilter.List = ["WHITE", "GRAY", "BLACK"]
else:
stringFilter.List = ["ORANGE", "INDIGO", "VIOLET"]
else:
stringFilter.List = ["RED", "GREEN", "BLUE"]
# If the user hasn't changed the keyword value, set it to the default value
# (first value in the value list filter).
#
if not self.params[1].Altered:
self.params[1].Value = stringFilter.List[0]
return
def updateMessages(self):
self.params[6].ClearMessage()
# Check to see if the threshold distance contains a value of zero and the user has
# specified a fixed distance band.
#
if self.params[6].Value <= 0:
if self.params[3].Value == "Fixed Distance Band":
self.params[6].SetErrorMessage("Zero or a negative distance is invalid when using a fixed distance band. Please use a positive value greater than zero." )
elif self.params[6].Value < 0:
self.params[6].SetErrorMessage("A positive distance value is required when using a fixed distance band. Please specify a distance.")
return
In addition to customizing the behavior of the tool dialog and Command Line, you can use ToolValidator to update descriptions of output data variables for ModelBuilder. You can think of data variables in ModelBuilder as nothing more than brief descriptions of datasets, as illustrated below. Data variables contain every property you access using the geoprocessing object's Describe method.
All tools should update the description of their output data for use in ModelBuilder. By updating the description, subsequent processes in ModelBuilder can see pending changes to data before any process is run. The two examples below show how subsequent processes see pending changes.
The first example shows a model containing the Add Field and Calculate Field tools. In Add Field, the output data variable, Parks (2), is updated to contain the new field, TrackingID. Because the output is updated, the Calculate Field dialog shows TrackingID in the list of field names.
The next illustration shows a model where the output of the Clip tool is used as input to the Polygon to Raster tool. Since the Clip tool simply "cookie cuts" the input features, the output feature class has all the same properties as the input feature class with one notable exception: its geographic extent. The geographic extent of the output feature class is the geometric intersection of the input and clip features extents. The Polygon to Raster tool uses the new geographic extent to determine a default cellsize.
Within the ToolValidator class, you can use a Schema object to set rules for building the description of the output. For example, you can set rules such as the following:
def initializeParameters(self): # Set the dependencies for the output and its schema properties # self.params[2].ParameterDependencies = [0, 1]
def initializeParameters(self): # Set the dependencies for the output and its schema properties # self.params[2].ParameterDependencies = [0, 1] # Feature type, geometry type, and fields all come from the first # dependent (parameter 0), the input features # self.params[2].Schema.FeatureTypeRule = "FirstDependency" self.params[2].Schema.GeometryTypeRule = "FirstDependency" self.params[2].Schema.FieldsRule = "FirstDependency" # The extent of the output is the intersection of the input features and # the clip features (parameter 1) # self.params[2].Schema.ExtentRule = "Intersection" return def updateParameter(self): return
Programming a ToolValidator class provides details on the Parameter, Schema, and Filter objects and gives code examples.
All script-based system tools, such as Multiple Ring Buffer, have ToolValidator code that you can examine and learn from. Many of the tools in the Spatial Statistics toolbox are script tools and have ToolValidator implementation you can examine.
Alas, you'll make mistakes in your ToolValidator implementation—either syntax, runtime, or logic errors. Debugging a ToolValidator class shows you how geoprocessing traps and reports errors and gives you some strategies for debugging.