]> gitweb.michael.orlitzky.com - dead/census-tools.git/blobdiff - src/SummaryFile1.py
Added the Tiger data directory to .gitignore.
[dead/census-tools.git] / src / SummaryFile1.py
index 3c82186474108e72908d3d3ded341d48470c1409..bfc62582f2d80db6c9b96f6d57b8386838d4e065 100644 (file)
@@ -1,9 +1,10 @@
-import os, GPS, inspect
+import os
 
 
-class RecordError(StandardError):
-    pass
+import GPS
+import StringUtils
 
 
-class InvalidAreaError(StandardError):
+
+class RecordError(StandardError):
     pass
 
 class GeoRecord:
     pass
 
 class GeoRecord:
@@ -11,41 +12,76 @@ class GeoRecord:
     This class wraps one record in an SF1 geo file.
     """
 
     This class wraps one record in an SF1 geo file.
     """
 
-    MinimumLineLength = 400
+    MINIMUM_LINE_LENGTH = 400
 
 
 class Block:
     """
 
 
 class Block:
     """
-    Represents a block (which is a special case of a GeoRecord.
-    All we care about here is the block number, population,
-    area, and coordinates.
+    Represents a block (which is a special case of a GeoRecord).
+    There are some convenience methods tacked on to make computation
+    and querying easier.
     """
 
     def __init__(self, geo_record):
     """
 
     def __init__(self, geo_record):
-        """We initialize from a GeoRecord object"""
+        """
+        We initialize from a GeoRecord object. It is important that
+        we raise some kind of error if there is no 'block' field, since
+        that means we weren't passed a block.
+        """
+        if not (StringUtils.is_integer(geo_record.block)):
+            raise RecordError('GeoRecord object does not represent a block.')
+
+        # These need to be stored as strings so they don't
+        # affect the block_identifier() generation.
+        self.state = geo_record.state
+        self.county = geo_record.county
+        self.tract = geo_record.tract
+        self.block = geo_record.block
+
         # All of these int/float conversions will throw a ValueError
         # if the input string cannot be converted o the specified
         # type.
         # All of these int/float conversions will throw a ValueError
         # if the input string cannot be converted o the specified
         # type.
-        self.block_number = int(geo_record.block)
-        self.tract_number = int(geo_record.tract)
-        self.population = int(geo_record.pop100)
-        self.area_land = float(geo_record.arealand)
-        self.area_water = float(geo_record.areawatr)
+        self.pop100 = int(geo_record.pop100)
+        self.arealand = float(geo_record.arealand)
+        self.areawatr = float(geo_record.areawatr)
 
         self.coordinates = GPS.Coordinates()
         self.coordinates.latitude = float(geo_record.intptlat)
         self.coordinates.longitude = float(geo_record.intptlon)
 
 
         self.coordinates = GPS.Coordinates()
         self.coordinates.latitude = float(geo_record.intptlat)
         self.coordinates.longitude = float(geo_record.intptlon)
 
-        if (self.total_area() == 0):
-            raise InvalidAreaError('A block may not have zero area.')
-        
+
+    def tiger_blkidfp00(self):
+        # From the Tiger/Line shapefile documentation:
+        #
+        #   Current block identifier; a concatenation of Census 2000
+        #   state FIPS code, Census 2000 county FIPS code, Census
+        #   BLKIDFP 16 String 2000 census tract code, Census 2000
+        #   tabulation block number, and current block suffix 1.
+        #
+        return (self.state +
+                self.county +
+                self.tract +
+                self.block)
+
 
     def total_area(self):
 
     def total_area(self):
-        return (self.area_land + self.area_water)
+        return (self.arealand + self.areawatr)
 
 
     def population_density(self):
 
 
     def population_density(self):
-        return (self.population / self.total_area())
+        # There are some unusual cases where a block will have a
+        # total area of zero. It also seems that these unusual blocks
+        # do in fact posess geometries, provided in the Tiger database.
+        # Therefore, we allow them to be parsed.
+        #
+        # The choice to assign these blocks an average density of 0
+        # was arbitrary.
+        #
+        if (self.total_area() == 0):
+            return 0
+        else:
+            return (self.pop100 / self.total_area())
+
 
     
 class GeoRecordParser:
 
     
 class GeoRecordParser:
@@ -80,12 +116,12 @@ class GeoRecordParser:
             try:
                 block = Block(record)
                 blocks.append(block)
             try:
                 block = Block(record)
                 blocks.append(block)
+            except RecordError:
+                # Ain't a block.
+                continue
             except ValueError:
                 # A value couldn't be converted to the appropriate type.
                 continue
             except ValueError:
                 # A value couldn't be converted to the appropriate type.
                 continue
-            except InvalidAreaError:
-                # Something is funny with the geometry.
-                continue
             
         return blocks
 
             
         return blocks
 
@@ -98,8 +134,8 @@ class GeoRecordParser:
         allow the GeoRecord class to parse the data meaningfully and
         throw an error if something doesn't look right.
         """
         allow the GeoRecord class to parse the data meaningfully and
         throw an error if something doesn't look right.
         """
-        if (len(line) < GeoRecord.MinimumLineLength):
-            raise RecordError("The input line is too short. The SF1 specification requires a line length of %d characters; this line contains only %d characters" % (GeoRecord.MinimumLineLength, len(line)))
+        if (len(line) < GeoRecord.MINIMUM_LINE_LENGTH):
+            raise RecordError("The input line is too short. The SF1 specification requires a line length of %d characters; this line contains only %d characters" % (GeoRecord.MINIMUM_LINE_LENGTH, len(line)))
         
         record = GeoRecord()
 
         
         record = GeoRecord()