If you’ve read most of my previous posts, you know I’m a big fan of all things python in GIS. Specifically relating to ArcGIS, because well…that’s the software with which I’m most comfortable/proficient. Like many GIS professionals, my education and experience has revolved around ESRI products. I am however aware of, and have used, other platforms like QGIS, PostGIS, MapBox, Manifold, etc., but just do so much less frequently.
I usually hand-write most of my workflows, then build them entirely as stand-alone python scripts before integrating them within an ArcGIS toolbox. To me, it makes more sense to get them functioning in python first. Plus, that allows me to maintain a known and working back-up should integrating within ArcGIS prove challenging. Ultimately connecting the scripts to tools within Arc is required because my user audience is less comfortable with cracking open a ‘.py’ file, editing variable assignments, and/or interacting with a python IDE, than they are with their familiar ArcGIS tools.
Defining parameters in the script tool properties dialog, and their required data type is a useful way to control how the user interacts with a tool. In a stand-alone python script, I can request the user enter a number, a string, a folder path, a feature class, etc. but I usually can’t control what they actually input. If they enter an unexpected value, the script will either fail then, or fail later when trying to use that value. You definitely don’t want to start to run a script, only to have it fail halfway through if you can avoid it. Defining parameters and their required data types greatly reduces the likelihood of any erroneous entries and won’t allow the tool to run if any are entered. Additionally, you can even create a value list for a selected parameter. The items in this list will then become the only acceptable inputs for that parameter, further refining and reducing tool failure once you hit the run button.
Below are examples of setting parameters, defining their required datatypes, and a look at a value list:
So that’s parameter definition.
Parameter validation code is like appetizer-code. It’s the code that runs before the main script code. It’s actually pretty powerful, and I’d be lying if I said I understand all of its available functionality, but I’m becoming more comfortable with it.
Parameter validation is wonderfully convenient because it allows me to forego some error handling in my main script code. It gives me the option to scrutinize all of the user inputs, and if there’s an error, prevents the script from executing. I don’t have to put a try-catch statement after each variable assignment in my main script, or wonder if the user enters incorrect values, and runs the script, that it will just fail over to the ‘except’ portion and not run the script fully or correctly. Selfishly, implementing parameter validation also saves me time from explaining/diagnosing errors with the user.
In many standard ArcGIS tools, what the user enters in preceding parameters can influence subsequent ones. For example, Parameter 0 calls for a shapefile; the user enters a shapefile. Parameter 1 then populates and shows all the fields that are contained within that shapefile, and the user can select some or all of those results. I replicated relatively similar functionality for the purposes of the script/tool I created.
I created a script that automates downloading Openstreetmap data. Based upon the user selection from the value list in Parameter 0 of my script (Continent), and Parameter 1 (Download Type), Parameter 2 (Files) populates with all the files available for that continent/download type.
Whole continent selection results:
Sub-region selection results:
I also added validation for the ‘Directory’ and ‘Uncompress after Download’ parameters. The way I uncompress the ‘.bz2’ files after download requires the use of 7zip. I actually do a command line call from the script to unzip the files. If the files were downloaded to a directory that has a ‘space’ anywhere in the folder path, calling 7zip will not work, and the files will not be uncompressed automatically. To avoid any issue with this, I validate the ‘Directory’ input and identify whether there is a space in the folder path. If there is, ‘Uncompress after Download’ will only have one option to select: ‘No’. If there is no space in the folder path, either ‘Yes’ or ‘No’ will be selectable.
Here’s an excerpt of the code from the updateParameter method, within the ToolValidation class, inside the parameter validation script that populates the file name(s) and allows the user to select ‘Uncompress after Download’:
elif self.params.value == 'australia-oceania': self.params.filter.list = ["Whole Continent", "Sub-Region(s)"] if self.params.value == 'Whole Continent': archive_url = "http://download.geofabrik.de/australia-oceania-latest.osm.bz2" files.append(archive_url) self.params.filter.list = files if ' ' in str(self.params.value): self.params.filter.list = ["No"] self.params.value = "No" else: self.params.filter.list = ["Yes", "No"] elif self.params.value == 'Sub-Region(s)': archive_url = base_url+"/"+self.params.value+"/" # create response object r = requests.get(archive_url) # create beautiful-soup object soup = BeautifulSoup(r.content,'html5lib') # find all links on web-page links = soup.findAll('a') #for link in links: #print link # filter the link sending with latest.osm.bz2 files = [archive_url + link['href'] for link in links if link['href'].endswith('latest.osm.bz2')] self.params.filter.list = files if ' ' in str(self.params.value): self.params.filter.list = ["No"] self.params.value = "No" else: self.params.filter.list = ["Yes", "No"]
Directory input has no ‘space’ in its path:
Directory input has a ‘space’ in its path:
So, there’s my short foray into parameter validation in ArcGIS Tools. I’ve really only scratched the surface in my understanding of the functionality possible using and extending parameter validation. Here are some additional resources of note which showcase the possibilities:
This post was written by Christian.
Contact us for more information on this post or our services.