From 23cc74b0e781d57e68a055944c9220c33ad0bcc4 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Tue, 15 Sep 2009 23:16:43 -0400 Subject: [PATCH] Modified find_avg_population_density to perform a GIS database query. Added optparse argument parsing so that database information does not need to be hard-coded in to the script. Switched the order of (longitude, latitude) in the arguments. --- bin/find_avg_population_density | 111 ++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 14 deletions(-) diff --git a/bin/find_avg_population_density b/bin/find_avg_population_density index e58d1ca..e6d8ac7 100755 --- a/bin/find_avg_population_density +++ b/bin/find_avg_population_density @@ -1,27 +1,110 @@ #!/usr/bin/python +""" +Find the average population density of a set of GPS coordinates. +""" + +import sys +import os +import site +import pgdb +from optparse import OptionParser + # Basically, add '../src' to our path. -import sys, os, site +# Needed for the imports that follow. site.addsitedir(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../src') -import ExitCodes, GPS, SummaryFile1 +import Configuration.Defaults +import ExitCodes +import GPS +import StringUtils +import SummaryFile1 + + +""" +Parse the command line options. There's some magic involved here; +otherwise, optparse woule like nothing more than to interpret GPS +coordinates such as '-78.000000' as options. +""" +for idx, value in enumerate(sys.argv): + # Please oh please don't rename this script to something which + # validates as a negative float. + if (StringUtils.is_negative_float(value)): + sys.argv.insert(idx, '--') + # We have to break here, otherwise the negative argument + # will get shifted down the list, and we'll hit it again + # in the next iteration of enumerate(). And then it'll + # get shifted down the list... + break + +usage = '%prog [options] ' + +# -h (help) Conflicts with -h HOSTNAME +parser = OptionParser(usage=usage, add_help_option = False) + +# Use this module's docstring as the description. +parser.description = __doc__ -# Find the average population density of a set of GPS coordinates -# given a (SF1) geographic header file. +parser.add_option('-h', + '--host', + help='The hostname/address where the database is located.', + default=Configuration.Defaults.DATABASE_HOST) -if (len(sys.argv) < 4): - print "Usage: %s " % sys.argv[0] - raise SystemExit(ExitCodes.NotEnoughArgs) +parser.add_option('-d', + '--database', + help='The database in which the population data are stored.', + default=Configuration.Defaults.DATABASE_NAME) + +parser.add_option('-U', + '--username', + help='The username who has access to the database.', + default=Configuration.Defaults.DATABASE_USERNAME) + +(options, args) = parser.parse_args() + +if len(args) < 2: + print "\nERROR: You must supply a longitude and latitude.\n" + parser.print_help() + print '' # Print a newline + raise SystemExit(ExitCodes.NOT_ENOUGH_ARGS) -# If we made it here, it's sort of safe to parse the arguments -# and hope they're in order. coords = GPS.Coordinates() -coords.latitude = float(sys.argv[1]) -coords.longitude = float(sys.argv[2]) -geo_file_path = sys.argv[3] +coords.longitude = float(args[0]) +coords.latitude = float(args[1]) + +conn = pgdb.connect(host=options.host, + database=options.database, + user=options.username) + +cursor = conn.cursor() + +########### +# WARNING # +########### +# +# Most GIS software, including PostGIS and the associated libraries, +# store and manipulate GPS coordinates in (longitude, latitude) format +# rather than (latitude, longitude) format. +# -avg_density = SummaryFile1.FindAveragePopulationDensity(coords, geo_file_path) +query = """ +SELECT population_density +FROM (sf1_blocks INNER JOIN tiger + ON sf1_blocks.tiger_blkidfp00=tiger.blkidfp00) +WHERE ST_Contains(tiger.the_geom, + ST_SetSRID(ST_Point(%.6f, %.6f), 4269)); +""" % (coords.longitude, coords.latitude) -print str(avg_density) +cursor.execute(query) +rows = cursor.fetchall() +if len(rows) > 0: + avg_density = rows[0][0] + print str(avg_density) +else: + print 'Error: No rows returned.' + print 'Did you pass (longitude, latitude) in the correct order?' + raise SystemExit(ExitCodes.NO_RESULTS) + +conn.close() -- 2.44.2