]>
gitweb.michael.orlitzky.com - dead/census-tools.git/blob - SummaryFile1.py
bd69d0095137d30caff160fbed0cea2567530040
1 import os
, GPS
, inspect
3 class RecordError ( StandardError ):
6 class InvalidAreaError ( StandardError ):
11 This class wraps one record in an SF1 geo file.
14 MINIMUM_LINE_LENGTH
= 400
19 Represents a block (which is a special case of a GeoRecord.
20 All we care about here is the block number, population,
21 area, and coordinates.
24 def __init__ ( self
, geo_record
):
25 """We initialize from a GeoRecord object"""
26 # All of these int/float conversions will throw a ValueError
27 # if the input string cannot be converted o the specified
29 self
. block_number
= int ( geo_record
. block
)
30 self
. tract_number
= int ( geo_record
. tract
)
31 self
. population
= int ( geo_record
. pop100
)
32 self
. area_land
= float ( geo_record
. arealand
)
33 self
. area_water
= float ( geo_record
. areawatr
)
35 self
. coordinates
= GPS
. Coordinates ()
36 self
. coordinates
. latitude
= float ( geo_record
. intptlat
)
37 self
. coordinates
. longitude
= float ( geo_record
. intptlon
)
39 if ( self
. total_area () == 0 ):
40 raise InvalidAreaError ( 'A block may not have zero area.' )
44 return ( self
. area_land
+ self
. area_water
)
47 def population_density ( self
):
48 return ( self
. population
/ self
. total_area ())
51 class GeoRecordParser
:
53 def parse_file ( self
, path
):
55 Assuming that path refers to an SF1 (geo) file, parse the
56 geographic header records contained within it. Return a list
60 # Our list of GeoRecord objects to return. Empty at first.
66 record
= self
. parse_line ( line
)
67 records
. append ( record
)
74 def parse_blocks ( self
, path
):
75 """Parse only the blocks from a geo file."""
77 records
= self
. parse_file ( path
)
79 for record
in records
:
84 # A value couldn't be converted to the appropriate type.
86 except InvalidAreaError
:
87 # Something is funny with the geometry.
94 def parse_line ( self
, line
):
96 Parse one line of an SF1 geo file. Hopefully, the input will
97 match the specification. We can check the line length here, or
98 allow the GeoRecord class to parse the data meaningfully and
99 throw an error if something doesn't look right.
101 if ( len ( line
) < GeoRecord
. MINIMUM_LINE_LENGTH
):
102 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
)))
106 # Note that Python list indexes are zero-based, whereas the SF1
107 # specification gives the field offsets as one-based. For example,
108 # the first field, "File Identification," is defined as beginning
109 # at position 1, and having length 6. The following line corresponds
110 # to this definition.
111 record
. fileid
= line
[ 0 : 6 ]
113 # State / US Abbreviation (USPS)
114 record
. stusab
= line
[ 6 : 8 ]
117 record
. sumlev
= line
[ 8 : 11 ]
119 # Geographic Component
120 record
. geocomp
= line
[ 11 : 13 ]
122 # Characteristic Iteration
123 record
. chariter
= line
[ 13 : 16 ]
125 # Characteristic Iteration File Sequence Number
126 record
. cifsn
= line
[ 16 : 18 ]
128 # Logical Record Number
129 record
. logrecno
= line
[ 18 : 25 ]
132 record
. region
= line
[ 25 ]
135 record
. division
= line
[ 26 ]
138 record
. statece
= line
[ 27 : 29 ]
141 record
. state
= line
[ 29 : 31 ]
144 record
. county
= line
[ 31 : 34 ]
147 record
. countysc
= line
[ 34 : 36 ]
149 # County Subdivision (FIPS)
150 record
. cousub
= line
[ 36 : 41 ]
152 # FIPS County Subdivision Class Code
153 record
. cousubcc
= line
[ 41 : 43 ]
155 # County Subdivision Size Code
156 record
. cousubsc
= line
[ 43 : 45 ]
159 record
. place
= line
[ 45 : 50 ]
161 # FIPS Place Class Code
162 record
. placecc
= line
[ 50 : 52 ]
164 # Place Description Code
165 record
. placedc
= line
[ 52 ]
168 record
. placesc
= line
[ 53 : 55 ]
171 record
. tract
= line
[ 55 : 61 ]
174 record
. blkgrp
= line
[ 61 ]
177 record
. block
= line
[ 62 : 66 ]
180 record
. iuc
= line
[ 66 : 68 ]
182 # Consolidated City (FIPS)
183 record
. concit
= line
[ 68 : 71 ]
185 # FIPS Consolidated City Class Code
186 record
. concitcc
= line
[ 73 : 75 ]
188 # Consolidated City Size Code
189 record
. concitsc
= line
[ 75 : 77 ]
191 # American Indian Area/Alaska Native Area/Hawaiian Home Land
193 record
. aianhh
= line
[ 77 : 81 ]
195 # American Indian Area/Alaska Native Area/Hawaiian Home Land
197 record
. aianhhfp
= line
[ 81 : 86 ]
199 # FIPS American Indian Area/Alaska Native Area/Hawaiian Home
201 record
. aianhhcc
= line
[ 86 : 88 ]
203 # American Indian Trust Land/Hawaiian Home Land Indicator
204 record
. aihhtli
= line
[ 88 ]
206 # American Indian Tribal Subdivision (Census)
207 record
. aitsce
= line
[ 89 : 92 ]
209 # American Indian Tribal Subdivision (FIPS)
210 record
. aits
= line
[ 92 : 97 ]
212 # FIPS American Indian Tribal Subdivision Class Code
213 record
. aitscc
= line
[ 97 : 99 ]
215 # Alaska Native Regional Corporation (FIPS)
216 record
. anrc
= line
[ 99 : 104 ]
218 # FIPS Alaska Native Regional Corporation Class Code
219 record
. anrccc
= line
[ 104 : 106 ]
221 # Metropolitan Statistical Area/Consolidated Metropolitan
223 record
. msacmsa
= line
[ 106 : 110 ]
226 record
. masc
= line
[ 110 : 112 ]
228 # Consolidated Metropolitan Statistical Area
229 record
. cmsa
= line
[ 112 : 114 ]
231 # Metropolitan Area Central City Indicator
232 record
. macci
= line
[ 114 ]
234 # Primary Metropolitan Statistical Area
235 record
. pmsa
= line
[ 115 : 119 ]
237 # New England County Metropolitan Area
238 record
. necma
= line
[ 119 : 123 ]
240 # New England County Metropolitan Area Central City Indicator
241 record
. necmacci
= line
[ 123 ]
243 # New England County Metropolitan Area Size Code
244 record
. necmasc
= line
[ 124 : 126 ]
246 # Extended Place Indicator
247 record
. exi
= line
[ 126 ]
250 record
. ua
= line
[ 127 : 132 ]
252 # Urban Area Size Code
253 record
. uasc
= line
[ 132 : 134 ]
256 record
. ustype
= line
[ 134 ]
259 record
. ur
= line
[ 135 ]
261 # Congressional District (106th)
262 record
. cd106
= line
[ 136 : 138 ]
264 # Congressional District (108th)
265 record
. cd108
= line
[ 138 : 140 ]
267 # Congressional District (109th)
268 record
. cd109
= line
[ 140 : 142 ]
270 # Congressional District (110th)
271 record
. cd110
= line
[ 142 : 144 ]
273 # State Legislative District (Upper Chamber)
274 record
. sldu
= line
[ 144 : 147 ]
276 # State Legislative District (Lower Chamber)
277 record
. sldl
= line
[ 147 : 150 ]
280 record
. vtd
= line
[ 150 : 156 ]
282 # Voting District Indicator
283 record
. vtdi
= line
[ 156 ]
285 # ZIP Code Tabulation Area (3 digit)
286 record
. zcta3
= line
[ 157 : 160 ]
288 # ZIP Code Tabulation Area (5 digit)
289 record
. zcta5
= line
[ 160 : 165 ]
292 record
. submcd
= line
[ 165 : 170 ]
294 # FIPS Subbarrio Class Code
295 record
. submcdcc
= line
[ 170 : 172 ]
298 record
. arealand
= line
[ 172 : 186 ]
301 record
. areawatr
= line
[ 186 : 200 ]
303 # Area Name - Legal/Statistical
304 # Area Description (LSAD)
305 # Term - Part Indicator
306 record
. name
= line
[ 200 : 290 ]
308 # Functional Status Code
309 record
. funcstat
= line
[ 290 ]
311 # Geographic Change User Note Indicator
312 record
. gcuni
= line
[ 291 ]
314 # Population Count (100%)
315 record
. pop100
= line
[ 292 : 301 ]
317 # Housing Unit Count (100%)
318 record
. hu100
= line
[ 301 : 310 ]
320 # Internal Point (Latitude)
321 record
. intptlat
= line
[ 310 : 319 ]
323 # Internal Point (Longitude)
324 record
. intptlon
= line
[ 319 : 329 ]
326 # Legal/Statistical Area Description Code
327 record
. lsadc
= line
[ 329 : 331 ]
330 record
. partflag
= line
[ 331 ]
332 # School District (Elementary)
333 record
. sdelm
= line
[ 332 : 337 ]
335 # School District (Secondary)
336 record
. sdsec
= line
[ 337 : 342 ]
338 # School District (Unified)
339 record
. sduni
= line
[ 342 : 347 ]
341 # Traffic Analysis Zone
342 record
. taz
= line
[ 347 : 353 ]
344 # Oregon Urban Growth Area
345 record
. uga
= line
[ 353 : 358 ]
347 # Public Use Microdata Area - 5% File
348 record
. puma5
= line
[ 358 : 363 ]
350 # Public Use Microdata Area - 1% File
351 record
. puma1
= line
[ 363 : 368 ]
354 record
. reserve2
= line
[ 368 : 383 ]
356 # Metropolitan Area Central City
357 record
. macc
= line
[ 383 : 388 ]
359 # Urban Area Central Place
360 record
. uacp
= line
[ 388 : 393 ]
363 record
. reserved
= line
[ 393 : 400 ]
370 def FindClosestBlock ( blocks
, target_coords
):
372 Find the closest block (from within blocks) to the GPS
373 coordinates given by target_coords.
376 # Empty by default. Hopefully we're passed some blocks.
378 min_distance
= 999999999.0 # Don't look at me like that.
381 this_distance
= GPS
. CalculateDistance ( target_coords
, block
. coordinates
)
382 if ( this_distance
< min_distance
):
383 closest_block
= block
384 min_distance
= this_distance
390 def FindAveragePopulationDensity ( coords
, geo_file_path
):
391 grp
= GeoRecordParser ()
392 blocks
= grp
. parse_blocks ( geo_file_path
)
393 closest_block
= FindClosestBlock ( blocks
, coords
)
395 return closest_block
. population_density ()