I just solved a problem that has perplexed me for a week. I have banged my head and the heads of my colleagues on an issue that has pretty much halted a project. It was solved today because someone 4 years ago posted a little note on the ESRI forums and I am so grateful to them I would like to hug them. Thank you Rafael Ferraro! I would thank you in the forums, but the comments have been closed in the old archived forums.
So this brings to mind the importance of each and every one of us participating in our communities. Each voice is
This one had me stumped for awhile. I wanted to insert an image into an HTML pop-up in ArcMap, which is another way to identify data. The pop up can be formatted to embed links, video, images, and colored to look nicer than the plain identify box that ArcMap typically uses. The pop-up box is formatted by modifying stylesheets and the style sheets are in XSL format. -sigh- yet another ‘programming’ language to hack at. Esri provides stylesheet examples, but I couldn’t find a sample of how to embed an image file into the pop-up box. It seems like that would be the most commonly desired thing, but no samples that I could find. So I searched around the internet and finally cobbled together something that works. Here it is. I hope this saves you a bit of hunting.
The important part excerpted here is this:
<xsl:when test="FieldValue[starts-with(., '\\')]">
<img width="350" height="210">
<xsl:attribute name = "src"><xsl:value-of select="FieldValue"/></xsl:attribute>
Click on through to see the whole template XSL file:
Here’s a rough script (but it does work) that reads EXIF information from already downloaded photos (tested with an iPhone) and creates a file geodatabase using the latitude and longitude stored with the photo.
You have to have had your GPS active while taking the photos. The pictures are moved into the file geodatabase and a hardcoded path is stored. Eventually I’d like to calc that as a relative path and leave the photos where they are. The benefit to moving them into the geodatabase means they won’t get lost, but you duplicate the photos and increase storage needs.
The settings for running the script to accept arguments, or to run with a hard coded path, are near the bottom. Be sure to modify the paths to be what you want.
Click on through to get to the script: Continue reading
Perhaps this is something that is inherently understood by “coders”, but as a newbie code writer, I had to figure this out on my own. It’s much more efficient to make your own tools and reference them over and over than it is to write the same code over and over in each little script you make.
I didn’t come to realize that I had things I wanted to do over and over until I had a library of scripts and started to see patterns. Some of the ‘do-overs’ are things like FTP all the files in a folder to our FTP site, or email myself a note once a script has completed (or even if it has failed), or log events into a table or file as the script progresses.
This sort of thing was intimidating as I was reading python tutorials and the samples use things like double underscores and references to “self” in a def statement. I still have no idea what those do (I”ll let you know if I figure it out!) but honestly I haven’t needed it yet. It doesn’t have to be that complicated. Continue reading
Every so often I run an automated process that copies all of our clients data to file geodatabases and then zips them up to post to the web. Previously I used PKZip as a command line zipper, calling it from my python script in a batch file. I decided to explore the possibility of zipping from within python. Turns out there is a module called zipfile that does just what I need. A fellow blogger got me started on the right path with a very helpful blog posting (here it is).
# run this after creating the gis data for the web script
import sys, string, os, zipfile
#if available add compression
compressType = zipfile.ZIP_DEFLATED
compressType = zipfile.ZIP_STORED
shpPath = "N:/yourpath/datafiles"
# Read the list of shapefiles and zip'em
# shapefiles have a prefix that determines what zip file the go in
# reads the files alphabetically, or this script wouldn't work
# if the zip file already exists, it will overwrite
x = 0
currentZip = ''
itemList = os.listdir(shpPath)
for i in itemList:
fullpath = os.path.join(shpPath, i)
shpName = i.split("_",1) # the data naming convention for the data includes an underscore. This reads the prefix and name into a list
thisZip = shpName # reads the prefix
shp = shpName #reads the name of the file
zipname = 'ClientName_' + thisZip +'_shps.zip' #add a new prefix (ClientName_) and groups all the like prefixes into one zip. So... all the transportation data is in one zip file.
if i <> zipname:
if currentZip == thisZip:
#add to zip archive
zf = zipfile.ZipFile(shpPath + '/zips/'+ zipname, mode='a')
print 'adding', i
zf.write(fullpath, arcname='ClientName_'+ i, compress_type=compressType) #this writes the zip file
#arcname sets the name and strips the folder location from the saved path internal to the zip file
#make a new archive and set the new currentZip variable
currentZip = thisZip
print '\ncreating new archive'
zf = zipfile.ZipFile(shpPath + '/zips/'+ zipname, mode='w')
print 'adding', i
zf.write(fullpath, arcname='ClientName_'+i, compress_type=compressType)
print "Unexpected error:", sys.exc_info()
print 'cannot zip a zip file'
print "Unexpected error:", sys.exc_info()
In repeated automated tasks, I often have to delete a set of data I am about to recreate fresh.
ArcPy offers a delete function, but the faster way to delete is through the os module.
Wouldn’t it be great to get an email once a script has finished letting you know if it worked or failed? Well it’s actually really easy to pull off. Here’s how I did it:
Note for this example you would replace ‘smtp.example.com’ with your email host.
def SendEmail(sender, receivers, message):
import sys, smtplib
smtpObj = smtplib.SMTP('smtp.example.com')
smtpObj.sendmail(sender, receivers, message)
print 'email sent'
print 'error sending'
then in your script you use the code like this:
—script did some stuff—
–script made some output—
message = "my output message" + output #for example. use whatever you want here to convey the info you need
receivers = "email@example.com"
sender = "firstname.lastname@example.org"
SendEmail(sender, receivers, message)