]> gitweb.michael.orlitzky.com - dead/census-tools.git/blob - bin/blocks2kml
Updated the queries in blocks2kml to use the new "blocks" table.
[dead/census-tools.git] / bin / blocks2kml
1 #!/usr/bin/env python
2
3 """
4 Export block geometries from the database (PostGIS) to Keyhole Markup
5 Language (KML). The exported polygons will be assigned a color based
6 upon their blocks' average population densities. Output is written to
7 stdout.
8 """
9
10 import os
11 import pgdb
12 import site
13 import sys
14
15 # Basically, add '../src' to our path.
16 # Needed for the imports that follow.
17 site.addsitedir(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../src')
18
19 import CLI
20 import Configuration.Defaults
21 import ExitCodes
22 import GPS
23 import SummaryFile1
24 import KML
25
26
27 """
28 Parse the command line options. All of these are optional; defaults
29 are provided for the database information and the output is written
30 to stdout.
31 """
32
33 parser = CLI.default_option_parser()
34
35 # Use this module's docstring as the description.
36 parser.description = __doc__
37 (options, args) = parser.parse_args()
38
39
40 def GenerateRedStyles(alpha='7f'):
41 """
42 Generate 256 styles (0-255), each corresponding to a shade of red.
43
44 The RGB values in KML are represented as aabbggrr, where each of
45 'aa','bb','gg','rr' is a hexadecimal value between 00-ff such that,
46
47 aa -> Alpha Component
48 bb -> Blue Component
49 gg -> Green Component
50 rr -> Red Component
51 """
52
53 styles = []
54
55 for rgb_value in range(0, 256):
56 hex_value = "%s0000%02x" % (alpha, rgb_value)
57 s = KML.Style(initial_id=(hex_value))
58 poly_style = KML.PolyStyle()
59 color = KML.Color(hex_value)
60 poly_style.children.append(color)
61 s.children.append(poly_style)
62 styles.append(s)
63
64 return styles
65
66
67 conn = pgdb.connect(host=options.host,
68 database=options.database,
69 user=options.username)
70
71 # We'll use this cursor for all of our queries.
72 cursor = conn.cursor()
73
74 # Here we calculate a bunch of magic parameters. If we try to use a
75 # linear gradient based on the population density, it turns out that
76 # everyone gets assigned the color for "zero." So, we need to massage
77 # the numbers a little bit in order to get some color in our polygons.
78
79 avg_avg_pop_query = """
80 SELECT AVG(population_density)
81 FROM blocks
82 WHERE population_density > 0.005;
83 """
84
85 cursor.execute(avg_avg_pop_query)
86 rows = cursor.fetchall()
87 avg_avg_population = float(rows[0][0])
88
89 stddev_avg_pop_query = """
90 SELECT stddev_samp(population_density)
91 FROM blocks
92 WHERE population_density > 0.005;
93 """
94
95 cursor.execute(stddev_avg_pop_query)
96 rows = cursor.fetchall()
97 stddev_avg_population = float(rows[0][0])
98
99 # These parameters were carefully guessed.
100 floor_avg_population = avg_avg_population - (0.5 * stddev_avg_population)
101 ceil_avg_population = avg_avg_population + (2*stddev_avg_population)
102
103
104 # We always want to include these styles (defining all 256 colors) in
105 # our document.
106 doc = KML.Document()
107 red_styles = GenerateRedStyles()
108
109 for style in red_styles:
110 doc.styles.append(style)
111
112
113 query = """
114 SELECT blkidfp00, population_density, AsKML(the_geom) as geom
115 FROM blocks;
116 """
117
118 cursor.execute(query)
119 rows = cursor.fetchall()
120
121 for row in rows:
122 placemark = KML.Placemark()
123 name = KML.Name(row[0])
124 placemark.children.append(name)
125
126 avg_pop = float(row[1])
127
128 # If the average population is outside of the limits that I have
129 # decreed acceptable, set its value back to the max/min
130 # appropriately.
131 if (avg_pop < floor_avg_population):
132 avg_pop = floor_avg_population
133
134 if (avg_pop > ceil_avg_population):
135 avg_pop = ceil_avg_population
136
137 # We can calculate the color as a percentage of "completely red,"
138 # which is #ff000ff in hex, or (255, 0, 0, 0) in RGB. We start
139 # with RGB, and then convert it to hex.
140 #
141 # We rely on the KML file containing 256 different styles, each
142 # named after the RGB (Hex) representation of its PolyStyle
143 # color.
144 #
145 red_base10 = (avg_pop / (3*stddev_avg_population)) * 255.0
146 red_hex = "#7f0000%02x" % red_base10
147 style = KML.StyleUrl(red_hex)
148 placemark.children.append(style)
149
150 multigeometry = KML.RawText(row[2])
151 placemark.children.append(multigeometry)
152
153 doc.children.append(placemark)
154
155 doc.print_kml()
156
157 conn.close()