#!/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] <longitude> <latitude>'
+
+# -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 <latitude> <longitude> <geo_file>" % 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()