I have recently been writing my first script to handle a geoprocessing task related to our Cityscapes project, where we place georeferenced historical maps in a Google Maps framework that can be used in urban studies classes (more to come!). Since the beginning I have been converting the georeferenced maps into Google Maps tiles by hand, a process that takes a couple of hours. This is small compared to the georeferencing time, so even though it was a prime candidate for scripting I had been putting it off in order to complete more maps.
For about a year now I have been learning the scripting language Python, as it has become the new, open way to script ArcGIS (and also has many fans in other areas of scientific computing). As my summer Cityscapes efforts ended, and as I prepare for my Cityscapes presentation at the NEArc meeting on November 8, my education has finally shifted over to using Python with ArcGIS (9.3). The documentation I have been using includes the following items:
- A nice, short overview from a course at San Francisco State University;
- A longer overview from ESRI, Writing Geoprocessing Scripts with ArcGIS;
- The ArcGIS Desktop Help Reference, in particular Writing Geoprocessing Scripts and The Geoprocessor Object.
- A chart of the ArcGIS Geoprocessing Model.
The script is being implemented through ArcToolbox, which makes it easier to provide script parameters, such as the input raster, through a GUI dialog. But because I want it to be usable by others, I have to write it in a general way, which means displaying information about the input raster, suggesting reasonable values for subsequent inputs, and checking for illegal values. Hence I have been learning about the ToolValidator class, apparently a new feature in version 9.3, and I've been struggling to understand some undocumented characteristics. Some of my observations follow.
The ToolValidator Class and Toolbox Dialogs
First off, the ToolValidator class is only very loosely connected to its Tool dialog. In particular, it is not instantiated just once when the dialog opens, which would allow the preservation of state within the class as the user changes the dialog, but instead every time the dialog parameters are changed, and before each of its methods are called. Hence the dialog parameters themselves are the only way to store information as the user fills in the fields and they are validated.
Accessing Tool Parameters
The ToolValidator template provided for each script accesses the dialog parameters in its initialization method:
import arcgisscripting as ARC
self.GP = ARC.create(9.3)
self.params = self.GP.GetParameterInfo()
The parameter values themselves are accessed through, for example,
self.params.Value, but be forewarned that sometimes the property
Value is a Value object, rather than just a string of characters (poor documentation on this is discussed here). This seems to be the case when the parameter refers to a file or other data structure, and if you want its name as a character string you must reference the property
or use the expression
str( self.params.Value )
The latter conversion will occur automatically in contexts requiring a string, such as concatenation.
The initializeParameters() Method
When a dialog is first opened, the ToolValidator method
initializeParameters() is called. It can be used to insert initial values into the parameter fields, and also set some characteristics of those fields in the dialog. For example, to disable a parameter field (make it uneditable), you can include code such as:
self.params.Enabled = False
When a dialog field has been modified (which may include when the dialog first opens), verification that a parameter value is usable occurs at several places:
- If the user enters an inappropriate value into a dialog, for example a letter when a number is expected or a nonexistent folder when one is required, the Toolbox provides some very basic validation based on the field type, beeping and preventing one from "tabbing" out of the field. The user can still click out of it, though; in the first example the field is reset, and in the second an error message is displayed (probably due to steps 3 & 4, though).
- The ToolValidator method
updateParameters()comes next, and can be used to verify many characteristics of input values and avoid processing bad ones. It's also possible to correct the values directly, but in most cases it's better to send a message to the user as described in step 4 and let them correct them.
- Next, the Geoprocessor performs a basic validation, I guess so that it can catch script errors. If any are found, it sets error messages that will display unless cleared in the next step.
- Finally, the ToolValidator method
updateMessages()is called, where the messages returned from step 3 can be inspected and, if you want, reset with your own. These messages can direct users to fix their errors.
The result of the separation of steps 2 and 4 is that sometimes the same tests must take place, first to avoid processing bad data and second to send a message about it.
The updateParameters() Method
The ToolValidator method
updateParameters() can be used to process new parameter values (e.g. to set related parameters). No information is provided about which of the dialog fields was modified, though, so you must check each parameter of interest to see if it is the one that needs to be validated:
if not self.params.HasBeenValidated :
elif not self.params.HasBeenValidated :
Once you find the modified parameter, you can ignore the update if it's due to the script itself (e.g. initialization) rather than being altered by the user:
if not self.params.altered : return
Before processing an input dataset, you should test for its existence:
if not self.GP.Exists( str( self.params ) ) : return
If the data isn't actually there, this method will raise an error, but it won't be reported until later, hence the need to
return at this point.
The updateMessages() Method
The ToolValidator method
updateMessages() can be used to send the user a message about problems with the value in a dialog field. The result is a red ⊗ next to the input field, and clicking on it will display the message. Once again no information is provided about which of the dialog fields has the problem, so you must check each parameter of interest (even if this was done previously), e.g.:
if self.params.Value and self.params.Value <= 0 :
self.params.SetErrorMessage("This parameter must be positive.")
Providing basic documentation for the tool and its parameters is fairly easy, once you know that the simplest way to create and modify them is with the Documentation Editor. The ArcGIS documentation provides two options for opening the Editor, the first of which doesn't work, the second of which is available by opening ArcCatalog and menuing View > Toolbars > Metadata to bring up that toolbar. Then click on the script, click on its tab Metadata, and finally, in the Metadata toolbar, click on the button Edit metadata.
When the Documentation Editor opens, the left side lists the various types of information you can provide. The main tool description, visible when it first opens, is added in the section General Information, in the item Abstract. The various parameters are described in the section Help in the item Parameters, and they will all be listed to the right under Contents. Open the one you want to describe, click on Dialog Reference, click on the [A] Paragraph button, and then click in the box to the right to add text.
Warning: if you change a parameter name after creating a description for it, the latter will be lost!