]>
gitweb.michael.orlitzky.com - dead/census-tools.git/blob - src/SummaryFile1.py
50f23ad0c96a83227137d60c7ff0fd2a4057efe8
1 import os
, GPS
, inspect
3 class RecordError ( StandardError ):
9 This class wraps one record in an SF1 geo file.
12 MinimumLineLength
= 400
17 Represents a block (which is a special case of a GeoRecord.
18 All we care about here is the block number, population,
19 area, and coordinates.
22 def __init__ ( self
, geo_record
):
23 """We initialize from a GeoRecord object"""
24 # All of these int/float conversions will throw a ValueError
25 # if the input string cannot be converted o the specified
27 self
. block_number
= int ( geo_record
. block
)
28 self
. population
= int ( geo_record
. pop100
)
29 self
. area_land
= float ( geo_record
. arealand
)
30 self
. area_water
= float ( geo_record
. areawatr
)
32 self
. coordinates
= GPS
. Coordinates ()
33 self
. coordinates
. latitude
= float ( geo_record
. intptlat
)
34 self
. coordinates
. longitude
= float ( geo_record
. intptlon
)
38 return ( self
. area_land
+ self
. area_water
)
41 def population_density ( self
):
42 return ( self
. population
/ self
. total_area ())
45 class GeoRecordParser
:
47 def parse_file ( self
, path
):
49 Assuming that path refers to an SF1 (geo) file, parse the
50 geographic header records contained within it. Return a list
54 # Our list of GeoRecord objects to return. Empty at first.
60 record
= self
. parse_line ( line
)
61 records
. append ( record
)
68 def parse_blocks ( self
, path
):
69 """Parse only the blocks from a geo file."""
71 records
= self
. parse_file ( path
)
73 for record
in records
:
84 def parse_line ( self
, line
):
86 Parse one line of an SF1 geo file. Hopefully, the input will
87 match the specification. We can check the line length here, or
88 allow the GeoRecord class to parse the data meaningfully and
89 throw an error if something doesn't look right.
91 if ( len ( line
) < GeoRecord
. MinimumLineLength
):
92 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
)))
96 # Note that Python list indexes are zero-based, whereas the SF1
97 # specification gives the field offsets as one-based. For example,
98 # the first field, "File Identification," is defined as beginning
99 # at position 1, and having length 6. The following line corresponds
100 # to this definition.
101 record
. fileid
= line
[ 0 : 6 ]
103 # State / US Abbreviation (USPS)
104 record
. stusab
= line
[ 6 : 8 ]
107 record
. sumlev
= line
[ 8 : 11 ]
109 # Geographic Component
110 record
. geocomp
= line
[ 11 : 13 ]
112 # Characteristic Iteration
113 record
. chariter
= line
[ 13 : 16 ]
115 # Characteristic Iteration File Sequence Number
116 record
. cifsn
= line
[ 16 : 18 ]
118 # Logical Record Number
119 record
. logrecno
= line
[ 18 : 25 ]
122 record
. region
= line
[ 25 ]
125 record
. division
= line
[ 26 ]
128 record
. statece
= line
[ 27 : 29 ]
131 record
. state
= line
[ 29 : 31 ]
134 record
. county
= line
[ 31 : 34 ]
137 record
. countysc
= line
[ 34 : 36 ]
139 # County Subdivision (FIPS)
140 record
. cousub
= line
[ 36 : 41 ]
142 # FIPS County Subdivision Class Code
143 record
. cousubcc
= line
[ 41 : 43 ]
145 # County Subdivision Size Code
146 record
. cousubsc
= line
[ 43 : 45 ]
149 record
. place
= line
[ 45 : 50 ]
151 # FIPS Place Class Code
152 record
. placecc
= line
[ 50 : 52 ]
154 # Place Description Code
155 record
. placedc
= line
[ 52 ]
158 record
. placesc
= line
[ 53 : 55 ]
161 record
. tract
= line
[ 55 : 61 ]
164 record
. blkgrp
= line
[ 61 ]
167 record
. block
= line
[ 62 : 66 ]
170 record
. iuc
= line
[ 66 : 68 ]
172 # Consolidated City (FIPS)
173 record
. concit
= line
[ 68 : 71 ]
175 # FIPS Consolidated City Class Code
176 record
. concitcc
= line
[ 73 : 75 ]
178 # Consolidated City Size Code
179 record
. concitsc
= line
[ 75 : 77 ]
181 # American Indian Area/Alaska Native Area/Hawaiian Home Land
183 record
. aianhh
= line
[ 77 : 81 ]
185 # American Indian Area/Alaska Native Area/Hawaiian Home Land
187 record
. aianhhfp
= line
[ 81 : 86 ]
189 # FIPS American Indian Area/Alaska Native Area/Hawaiian Home
191 record
. aianhhcc
= line
[ 86 : 88 ]
193 # American Indian Trust Land/Hawaiian Home Land Indicator
194 record
. aihhtli
= line
[ 88 ]
196 # American Indian Tribal Subdivision (Census)
197 record
. aitsce
= line
[ 89 : 92 ]
199 # American Indian Tribal Subdivision (FIPS)
200 record
. aits
= line
[ 92 : 97 ]
202 # FIPS American Indian Tribal Subdivision Class Code
203 record
. aitscc
= line
[ 97 : 99 ]
205 # Alaska Native Regional Corporation (FIPS)
206 record
. anrc
= line
[ 99 : 104 ]
208 # FIPS Alaska Native Regional Corporation Class Code
209 record
. anrccc
= line
[ 104 : 106 ]
211 # Metropolitan Statistical Area/Consolidated Metropolitan
213 record
. msacmsa
= line
[ 106 : 110 ]
216 record
. masc
= line
[ 110 : 112 ]
218 # Consolidated Metropolitan Statistical Area
219 record
. cmsa
= line
[ 112 : 114 ]
221 # Metropolitan Area Central City Indicator
222 record
. macci
= line
[ 114 ]
224 # Primary Metropolitan Statistical Area
225 record
. pmsa
= line
[ 115 : 119 ]
227 # New England County Metropolitan Area
228 record
. necma
= line
[ 119 : 123 ]
230 # New England County Metropolitan Area Central City Indicator
231 record
. necmacci
= line
[ 123 ]
233 # New England County Metropolitan Area Size Code
234 record
. necmasc
= line
[ 124 : 126 ]
236 # Extended Place Indicator
237 record
. exi
= line
[ 126 ]
240 record
. ua
= line
[ 127 : 132 ]
242 # Urban Area Size Code
243 record
. uasc
= line
[ 132 : 134 ]
246 record
. ustype
= line
[ 134 ]
249 record
. ur
= line
[ 135 ]
251 # Congressional District (106th)
252 record
. cd106
= line
[ 136 : 138 ]
254 # Congressional District (108th)
255 record
. cd108
= line
[ 138 : 140 ]
257 # Congressional District (109th)
258 record
. cd109
= line
[ 140 : 142 ]
260 # Congressional District (110th)
261 record
. cd110
= line
[ 142 : 144 ]
263 # State Legislative District (Upper Chamber)
264 record
. sldu
= line
[ 144 : 147 ]
266 # State Legislative District (Lower Chamber)
267 record
. sldl
= line
[ 147 : 150 ]
270 record
. vtd
= line
[ 150 : 156 ]
272 # Voting District Indicator
273 record
. vtdi
= line
[ 156 ]
275 # ZIP Code Tabulation Area (3 digit)
276 record
. zcta3
= line
[ 157 : 160 ]
278 # ZIP Code Tabulation Area (5 digit)
279 record
. zcta5
= line
[ 160 : 165 ]
282 record
. submcd
= line
[ 165 : 170 ]
284 # FIPS Subbarrio Class Code
285 record
. submcdcc
= line
[ 170 : 172 ]
288 record
. arealand
= line
[ 172 : 186 ]
291 record
. areawatr
= line
[ 186 : 200 ]
293 # Area Name - Legal/Statistical
294 # Area Description (LSAD)
295 # Term - Part Indicator
296 record
. name
= line
[ 200 : 290 ]
298 # Functional Status Code
299 record
. funcstat
= line
[ 290 ]
301 # Geographic Change User Note Indicator
302 record
. gcuni
= line
[ 291 ]
304 # Population Count (100%)
305 record
. pop100
= line
[ 292 : 301 ]
307 # Housing Unit Count (100%)
308 record
. hu100
= line
[ 301 : 310 ]
310 # Internal Point (Latitude)
311 record
. intptlat
= line
[ 310 : 319 ]
313 # Internal Point (Longitude)
314 record
. intptlon
= line
[ 319 : 329 ]
316 # Legal/Statistical Area Description Code
317 record
. lsadc
= line
[ 329 : 331 ]
320 record
. partflag
= line
[ 331 ]
322 # School District (Elementary)
323 record
. sdelm
= line
[ 332 : 337 ]
325 # School District (Secondary)
326 record
. sdsec
= line
[ 337 : 342 ]
328 # School District (Unified)
329 record
. sduni
= line
[ 342 : 347 ]
331 # Traffic Analysis Zone
332 record
. taz
= line
[ 347 : 353 ]
334 # Oregon Urban Growth Area
335 record
. uga
= line
[ 353 : 358 ]
337 # Public Use Microdata Area - 5% File
338 record
. puma5
= line
[ 358 : 363 ]
340 # Public Use Microdata Area - 1% File
341 record
. puma1
= line
[ 363 : 368 ]
344 record
. reserve2
= line
[ 368 : 383 ]
346 # Metropolitan Area Central City
347 record
. macc
= line
[ 383 : 388 ]
349 # Urban Area Central Place
350 record
. uacp
= line
[ 388 : 393 ]
353 record
. reserved
= line
[ 393 : 400 ]
360 def FindClosestBlock ( blocks
, target_coords
):
362 Find the closest block (from within blocks) to the GPS
363 coordinates given by target_coords.
366 # Empty by default. Hopefully we're passed some blocks.
368 min_distance
= 999999999.0 # Don't look at me like that.
371 this_distance
= GPS
. CalculateDistance ( target_coords
, block
. coordinates
)
372 if ( this_distance
< min_distance
):
373 closest_block
= block
374 min_distance
= this_distance
380 def FindAveragePopulationDensity ( coords
, geo_file_path
):
381 grp
= GeoRecordParser ()
382 blocks
= grp
. parse_blocks ( geo_file_path
)
383 closest_block
= FindClosestBlock ( blocks
, coords
)
385 return closest_block
. population_density ()