wxPython versus ArcToolbox tool


It started out to be simple stuff that I wanted to accomplish with Python and geoprocessing.  A lot of the tools that I created or wanted to create were quite easy to do in ArcToolbox but I soon found that I wanted to have more flexibility and more input options.  The ArcToolbox tools work great but they are limited in their uses and functions.  So in walked wxPython.  I tried messing around with several different options but after the dust settled it was wxPython that I went with.

Tinkter was ok but lacked a lot of options.  I tried Boa-Constructor but found that it was confusing to get going.  I tried Python-Card and although it seemed easier that Boa-Constructor, I was left with the nagging question of now what when I finished the “window.”  So back to wxPython.  As it is based on wxWidgets there is a lot of information on the web and tutorials as well.  So my mind was made up and then I had to figure out what it was that I wanted to do.

Being new to programming, I quickly learned that there are two stages to programming.  The first stage is “what am I trying to do” followed by the second stage of “OK, now how the heck do I do it!”  I know for all of you programmer gurus or those with formal programming training, this is quite obvious but for me it wasn’t obvious at all.  Now that I have gotten better at both Python and wxPython, I see that it sometimes takes longer to understand what I want to accomplish than it does to code it once my mind is made up.

So back to wxPython…….One of the functions that I soon found lacking in the ArcToolbox tools is taking inputed data and allowing user to perform functions based on the actual data that was imported.  What I am trying to say here is that I wanted to input a point file and then based on the data in the file, decide what processes I wanted to perform.  Another example of this is that I can input a shapefile and get a list of field names but I cannot choose a field and decide what to do with it.  The ArcToolbox allows minimal input and output but that is it.  I wanted more interaction such as input a shapefile, create a list of fields, allow the user to choose a field, and then make calculations based off of that.  This back and forth interaction wasn’t possible so off the wxPython I went.

Now by creating “wizard” like interfaces, I can accept inputed data, create lists and dropdown choices of those lists and further functions.  Don’t get me wrong, I have more ArcToolbox tools than I have wxPython GUI’s but they each serve a different function.

BR

Good Geoprocessing practices


Something that I learned as good practice is working with copies of my shapefiles and not the originals.  When doing this you do create several temporary tables and/or shapefiles and these need to be cleaned up.


## System arguments
 # Input Streets shapefile
 Streets = sys.argv[1]
 # Output Streets shapefile
 Streets_output = sys.argv[2]
 # Output Streets shapefile
 Streets_output2 = sys.argv[3]
 # facility streets layer
 facilstr = sys.argv[5]

# Set the workspace for the processing files
 gp.workspace = os.path.dirname(sys.argv[2])

# Make copies so that processing doesn't take place on the original.
 gp.AddMessage("\nCreating processing files...")
 gp.Copy_management(Streets, "Streets_process.shp")
 gp.Copy_management(facilstr, "facilstreets.shp")
 gp.AddMessage ("Copies created")

This creates copies of the input shapefiles which I then use for processing.  Because there are these temp files, in the end of the script I need to delete those temp files.  For this you need to import the “os” and “glob” functions such as import os, glob in the beginning of the script.  Then at the end of the script we use these functions to clean up the temp files.  I also cleanup the xml files that are created when working with temporary tables.


gp.AddMessage("Cleanup...")
 # Delete "process" files

for file in glob.glob(gp.workspace+"/Streets_process*"):
 os.remove(file)
 for file in glob.glob(gp.workspace+"/facilstreets*"):
 os.remove(file)
 for file in glob.glob(gp.workspace+"/*.xml"):
 os.remove(file)
 gp.AddMessage("\nDone.\n")

Merging shapefiles


Another process that I though would be quite simple was merging 2 shapefiles.  It seems there is an issue with the shapefile names not being recognized and I had to use “str” to identify the names as strings.


temp1 = "temp1.shp"
 temp2 = "temp2.shp"

strlist = str(temp1)+";"+str(temp2)
 outshp = (gp.workspace+"/final.shp")
 gp.Merge_management (str(strlist), outshp)
 gp.AddMessage ("Merged Shapefiles")

When I tried to just use the names of the shapefile copies I could not get this to work.  I then created a simple list and identified the shapefile names as strings as well as in the actual Merge_managment, I had to identify the strlist as string.

BR

Joining a table to a feature class


I have had the need to join tables to a shapefile or feature class many times and after not finding anything on the web, I posted on the ESRI forum and got my solution.

The difference with joining a table is that it is a one way join.  That is, you can copy from the table to the feature but not the other way around.

gp.MakeFeatureLayer("temp.shp", "temp")
 joinTable = "temp2.dbf"
 gp.AddJoin_management("temp", "field 1", joinTable, "field 1")
 gp.CalculateField_management("temp", "Field_2", "[temp2.Field_2]")
 gp.RemoveJoin_management("temp", "temp2.dbf")

I originally tried making a tableview of the table but found that it wasn’t necessary to do so.  Notice that because it is a table, tou need the [] around the table that is being read from.

I find this function very useful as I often have the need to read from a table and copy values over to a shapefile.

In this instance I needed to join a table to a table.  The first table  (table 1) was an input table and the second table (table 2) was a copy of the .dbf from a shapefile.


gp.AddMessage("Making Layer & View...")
 # Make Feature Layer from Stops
 gp.Copy_management(sys.argv[3], "temp.dbf")
 gp.MakeTableView_management("temp2.dbf", "temp2")
 joinTable1 = "temp.dbf"
 joinTable2 = "temp2"
 gp.AddJoin_management(joinTable1, "field_1", joinTable2, "field_2")
 gp.AddMessage("Joined table views")
 gp.CalculateField_management("temp2", "TIME", "[temp.TIME]")
 gp.RemoveJoin_management("temp2", "temp.dbf")