]>
gitweb.michael.orlitzky.com - dead/census-tools.git/blob - src/SummaryFile1.py
7 class RecordError ( StandardError ):
12 This class wraps one record in an SF1 geo file.
15 MINIMUM_LINE_LENGTH
= 400
20 Represents a block (which is a special case of a GeoRecord.
21 All we care about here is the block number, population,
22 area, and coordinates.
25 def __init__ ( self
, geo_record
):
26 """We initialize from a GeoRecord object"""
27 # All of these int/float conversions will throw a ValueError
28 # if the input string cannot be converted o the specified
30 self
. block_number
= int ( geo_record
. block
)
31 self
. tract_number
= int ( geo_record
. tract
)
32 self
. population
= int ( geo_record
. pop100
)
33 self
. area_land
= float ( geo_record
. arealand
)
34 self
. area_water
= float ( geo_record
. areawatr
)
36 self
. coordinates
= GPS
. Coordinates ()
37 self
. coordinates
. latitude
= float ( geo_record
. intptlat
)
38 self
. coordinates
. longitude
= float ( geo_record
. intptlon
)
40 if ( self
. total_area () == 0 ):
41 raise InvalidAreaError ( 'A block may not have zero area.' )
45 return ( self
. area_land
+ self
. area_water
)
48 def population_density ( self
):
49 return ( self
. population
/ self
. total_area ())
52 class GeoRecordParser
:
54 def parse_file ( self
, path
):
56 Assuming that path refers to an SF1 (geo) file, parse the
57 geographic header records contained within it. Return a list
61 # Our list of GeoRecord objects to return. Empty at first.
67 record
= self
. parse_line ( line
)
68 records
. append ( record
)
75 def parse_blocks ( self
, path
):
76 """Parse only the blocks from a geo file."""
78 records
= self
. parse_file ( path
)
80 for record
in records
:
85 # A value couldn't be converted to the appropriate type.
92 def parse_line ( self
, line
):
94 Parse one line of an SF1 geo file. Hopefully, the input will
95 match the specification. We can check the line length here, or
96 allow the GeoRecord class to parse the data meaningfully and
97 throw an error if something doesn't look right.
99 if ( len ( line
) < GeoRecord
. MINIMUM_LINE_LENGTH
):
100 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
)))
104 # Note that Python list indexes are zero-based, whereas the SF1
105 # specification gives the field offsets as one-based. For example,
106 # the first field, "File Identification," is defined as beginning
107 # at position 1, and having length 6. The following line corresponds
108 # to this definition.
109 record
. fileid
= line
[ 0 : 6 ]
111 # State / US Abbreviation (USPS)
112 record
. stusab
= line
[ 6 : 8 ]
115 record
. sumlev
= line
[ 8 : 11 ]
117 # Geographic Component
118 record
. geocomp
= line
[ 11 : 13 ]
120 # Characteristic Iteration
121 record
. chariter
= line
[ 13 : 16 ]
123 # Characteristic Iteration File Sequence Number
124 record
. cifsn
= line
[ 16 : 18 ]
126 # Logical Record Number
127 record
. logrecno
= line
[ 18 : 25 ]
130 record
. region
= line
[ 25 ]
133 record
. division
= line
[ 26 ]
136 record
. statece
= line
[ 27 : 29 ]
139 record
. state
= line
[ 29 : 31 ]
142 record
. county
= line
[ 31 : 34 ]
145 record
. countysc
= line
[ 34 : 36 ]
147 # County Subdivision (FIPS)
148 record
. cousub
= line
[ 36 : 41 ]
150 # FIPS County Subdivision Class Code
151 record
. cousubcc
= line
[ 41 : 43 ]
153 # County Subdivision Size Code
154 record
. cousubsc
= line
[ 43 : 45 ]
157 record
. place
= line
[ 45 : 50 ]
159 # FIPS Place Class Code
160 record
. placecc
= line
[ 50 : 52 ]
162 # Place Description Code
163 record
. placedc
= line
[ 52 ]
166 record
. placesc
= line
[ 53 : 55 ]
169 record
. tract
= line
[ 55 : 61 ]
172 record
. blkgrp
= line
[ 61 ]
175 record
. block
= line
[ 62 : 66 ]
178 record
. iuc
= line
[ 66 : 68 ]
180 # Consolidated City (FIPS)
181 record
. concit
= line
[ 68 : 71 ]
183 # FIPS Consolidated City Class Code
184 record
. concitcc
= line
[ 73 : 75 ]
186 # Consolidated City Size Code
187 record
. concitsc
= line
[ 75 : 77 ]
189 # American Indian Area/Alaska Native Area/Hawaiian Home Land
191 record
. aianhh
= line
[ 77 : 81 ]
193 # American Indian Area/Alaska Native Area/Hawaiian Home Land
195 record
. aianhhfp
= line
[ 81 : 86 ]
197 # FIPS American Indian Area/Alaska Native Area/Hawaiian Home
199 record
. aianhhcc
= line
[ 86 : 88 ]
201 # American Indian Trust Land/Hawaiian Home Land Indicator
202 record
. aihhtli
= line
[ 88 ]
204 # American Indian Tribal Subdivision (Census)
205 record
. aitsce
= line
[ 89 : 92 ]
207 # American Indian Tribal Subdivision (FIPS)
208 record
. aits
= line
[ 92 : 97 ]
210 # FIPS American Indian Tribal Subdivision Class Code
211 record
. aitscc
= line
[ 97 : 99 ]
213 # Alaska Native Regional Corporation (FIPS)
214 record
. anrc
= line
[ 99 : 104 ]
216 # FIPS Alaska Native Regional Corporation Class Code
217 record
. anrccc
= line
[ 104 : 106 ]
219 # Metropolitan Statistical Area/Consolidated Metropolitan
221 record
. msacmsa
= line
[ 106 : 110 ]
224 record
. masc
= line
[ 110 : 112 ]
226 # Consolidated Metropolitan Statistical Area
227 record
. cmsa
= line
[ 112 : 114 ]
229 # Metropolitan Area Central City Indicator
230 record
. macci
= line
[ 114 ]
232 # Primary Metropolitan Statistical Area
233 record
. pmsa
= line
[ 115 : 119 ]
235 # New England County Metropolitan Area
236 record
. necma
= line
[ 119 : 123 ]
238 # New England County Metropolitan Area Central City Indicator
239 record
. necmacci
= line
[ 123 ]
241 # New England County Metropolitan Area Size Code
242 record
. necmasc
= line
[ 124 : 126 ]
244 # Extended Place Indicator
245 record
. exi
= line
[ 126 ]
248 record
. ua
= line
[ 127 : 132 ]
250 # Urban Area Size Code
251 record
. uasc
= line
[ 132 : 134 ]
254 record
. ustype
= line
[ 134 ]
257 record
. ur
= line
[ 135 ]
259 # Congressional District (106th)
260 record
. cd106
= line
[ 136 : 138 ]
262 # Congressional District (108th)
263 record
. cd108
= line
[ 138 : 140 ]
265 # Congressional District (109th)
266 record
. cd109
= line
[ 140 : 142 ]
268 # Congressional District (110th)
269 record
. cd110
= line
[ 142 : 144 ]
271 # State Legislative District (Upper Chamber)
272 record
. sldu
= line
[ 144 : 147 ]
274 # State Legislative District (Lower Chamber)
275 record
. sldl
= line
[ 147 : 150 ]
278 record
. vtd
= line
[ 150 : 156 ]
280 # Voting District Indicator
281 record
. vtdi
= line
[ 156 ]
283 # ZIP Code Tabulation Area (3 digit)
284 record
. zcta3
= line
[ 157 : 160 ]
286 # ZIP Code Tabulation Area (5 digit)
287 record
. zcta5
= line
[ 160 : 165 ]
290 record
. submcd
= line
[ 165 : 170 ]
292 # FIPS Subbarrio Class Code
293 record
. submcdcc
= line
[ 170 : 172 ]
296 record
. arealand
= line
[ 172 : 186 ]
299 record
. areawatr
= line
[ 186 : 200 ]
301 # Area Name - Legal/Statistical
302 # Area Description (LSAD)
303 # Term - Part Indicator
304 record
. name
= line
[ 200 : 290 ]
306 # Functional Status Code
307 record
. funcstat
= line
[ 290 ]
309 # Geographic Change User Note Indicator
310 record
. gcuni
= line
[ 291 ]
312 # Population Count (100%)
313 record
. pop100
= line
[ 292 : 301 ]
315 # Housing Unit Count (100%)
316 record
. hu100
= line
[ 301 : 310 ]
318 # Internal Point (Latitude)
319 record
. intptlat
= line
[ 310 : 319 ]
321 # Internal Point (Longitude)
322 record
. intptlon
= line
[ 319 : 329 ]
324 # Legal/Statistical Area Description Code
325 record
. lsadc
= line
[ 329 : 331 ]
328 record
. partflag
= line
[ 331 ]
330 # School District (Elementary)
331 record
. sdelm
= line
[ 332 : 337 ]
333 # School District (Secondary)
334 record
. sdsec
= line
[ 337 : 342 ]
336 # School District (Unified)
337 record
. sduni
= line
[ 342 : 347 ]
339 # Traffic Analysis Zone
340 record
. taz
= line
[ 347 : 353 ]
342 # Oregon Urban Growth Area
343 record
. uga
= line
[ 353 : 358 ]
345 # Public Use Microdata Area - 5% File
346 record
. puma5
= line
[ 358 : 363 ]
348 # Public Use Microdata Area - 1% File
349 record
. puma1
= line
[ 363 : 368 ]
352 record
. reserve2
= line
[ 368 : 383 ]
354 # Metropolitan Area Central City
355 record
. macc
= line
[ 383 : 388 ]
357 # Urban Area Central Place
358 record
. uacp
= line
[ 388 : 393 ]
361 record
. reserved
= line
[ 393 : 400 ]
368 def FindClosestBlock ( blocks
, target_coords
):
370 Find the closest block (from within blocks) to the GPS
371 coordinates given by target_coords.
374 # Empty by default. Hopefully we're passed some blocks.
376 min_distance
= 999999999.0 # Don't look at me like that.
379 this_distance
= GPS
. CalculateDistance ( target_coords
, block
. coordinates
)
380 if ( this_distance
< min_distance
):
381 closest_block
= block
382 min_distance
= this_distance
388 def FindAveragePopulationDensity ( coords
, geo_file_path
):
389 grp
= GeoRecordParser ()
390 blocks
= grp
. parse_blocks ( geo_file_path
)
391 closest_block
= FindClosestBlock ( blocks
, coords
)
393 return closest_block
. population_density ()