def create_block_group_graph(block_group_config) -> nx.Graph: """Build a block group graph.""" indir = block_group_config.get("directory", "wa-block-groups") infile = block_group_config.get("filename", "block-groups.shp") draw_shapefile = block_group_config.get("draw_shapefile", False) draw_graph = block_group_config.get("draw_graph", False) pickle = block_group_config.get("pickle_graph", True) reload_graph = block_group_config.get("reload_graph", False) if not reload_graph: if os.path.exists( os.path.join(indir, infile + ".annotated_graph.pickle")): return nx.read_gpickle( os.path.join(indir, infile + ".annotated_graph.pickle")) elif os.path.exists(os.path.join(indir, infile + ".graph.pickle")): return nx.read_gpickle( os.path.join(indir, infile + ".graph.pickle")) G = nx.Graph() with cd(indir): with fiona.open(infile) as block_groups: for shp in tqdm(block_groups, "Reading block groups from shapefile"): shape_obj = shape(shp['geometry']) vertex_name = shp['properties'].get("GEOID") G.add_node(vertex_name, shape=shape_obj) # draw the input shapefile if draw_shapefile: plot_shapes([n[1]['shape'] for n in G.nodes(data=True)]) _connect_graph(G) if draw_graph: pos = { n[0]: [n[1]['shape'].centroid.x, n[1]['shape'].centroid.y] for n in G.nodes(data=True) } nx.draw_networkx(G, pos=pos) plt.show() if pickle: nx.write_gpickle(G, os.path.join(indir, infile + ".graph.pickle")) return G
def export(self): with cd('out/chromosome_{}/'.format(self.name)): with open('elements.csv') as outfile: outfile.write(','.join(['element', 'population', 'component']) + '\n') graph = self.chromosome.get_master_graph() for vertex in graph: data = graph.nodes[vertex] component_idx = self.chromosome.get_component(vertex) outfile.write(','.join([str(vertex), str(data.get('pop', 0)), str(component_idx)]) + '\n') with open('components.csv') as outfile: component_scores = self.chromosome.get_component_scores() outfile.write(','.join(['component'] + Chromosome.__scores__) + "\n") for component in component_scores: scores = component_scores[component] outfile.write(','.join([str(component)] + [str(scores[name]) for name in Chromosome.__scores__])) outfile.write('\n')
def plot_shapes(objects, outdir="out/", random_color=False, title="plot"): """Plots shapely shapes.""" fig = plt.figure() ax = fig.add_subplot(111) # calculate plot bounds min_x = min_y = float('inf') max_x = max_y = float('-inf') for obj in objects: color = None if isinstance(obj, tuple): obj, color = obj if not color and random_color: color = (random.random(), random.random(), random.random()) patch = descartes.PolygonPatch(obj, color=color, ec=(0, 0, 0)) elif color: patch = descartes.PolygonPatch(obj, color=color, ec=(0, 0, 0)) else: patch = descartes.PolygonPatch(obj, ec=(0, 0, 0)) ax.add_patch(patch) min_x = min(min_x, obj.bounds[0]) min_y = min(min_y, obj.bounds[1]) max_x = max(max_x, obj.bounds[2]) max_y = max(max_y, obj.bounds[3]) ax.set_xlim(min_x - (max_x - min_x) * 0.1, max_x + (max_x - min_x) * 0.1) ax.set_ylim(min_y - (max_y - min_y) * 0.1, max_y + (max_y - min_y) * 0.1) plt.title(title) ax.set_aspect(1) if outdir: with cd(outdir): plt.savefig('plot.png') os.chmod('plot.png', 0o666) else: plt.show()
def create_graphs(data_dir, configs, districts): with cd(data_dir): county_graph = shape.create_county_graph(configs.get('county')) annotater.initialize_county_graph(configs.get('county'), configs.get('precinct'), configs.get('voting_data'), county_graph) block_group_graph = shape.create_block_group_graph( configs.get('block_group')) annotater.initialize_block_group_graph(configs.get('block_group'), configs.get('precinct'), configs.get('voting_data'), county_graph, block_group_graph) print("Finished reading in all graphs. Leaving data directory.") county_graph['graph']['districts'] = block_group_graph['graph'][ 'districts'] = districts return nx.freeze(county_graph), nx.freeze(block_group_graph)
def get_precinct_shapes(precinct_config): """Get precincts from file.""" indir = precinct_config.get("directory", "wa-precincts") infile = precinct_config.get("filename", "precincts.shp") precinct_shapes = {} with cd(indir): with fiona.open(infile) as precincts: for shp in tqdm(precincts, "Reading precincts from shapefile"): precinct_obj = shape(shp['geometry']) precinct_data = shp['properties'] if not precinct_obj.is_valid: plot_shapes([precinct_obj]) assert False assert precinct_obj.area != 0, precinct_obj.area st_code = precinct_data.get('ST_CODE') assert st_code not in precinct_shapes precinct_shapes[st_code] = (precinct_obj, precinct_data) return precinct_shapes
def create_county_graph(county_config) -> nx.Graph: """Build a county graph.""" indir = county_config.get("directory", "wa-counties") infile = county_config.get("filename", "counties.shp") draw_shapefile = county_config.get("draw_shapefile", False) draw_graph = county_config.get("draw_graph", False) pickle = county_config.get("pickle_graph", True) reload_graph = county_config.get("reload_graph", False) state_code = county_config.get("state_code", "53") if not reload_graph: if os.path.exists( os.path.join(indir, infile + ".annotated_graph.pickle")): return nx.read_gpickle( os.path.join(indir, infile + ".annotated_graph.pickle")) elif os.path.exists(os.path.join(indir, infile + ".graph.pickle")): return nx.read_gpickle( os.path.join(indir, infile + ".graph.pickle")) G = nx.Graph() # map English name (e.g., King County) to GEOID (e.g., 53033) name_to_geoid = {} with cd(indir): with fiona.open(infile) as counties: for shp in tqdm(counties, "Reading counties from shapefile"): if shp['properties'].get("STATEFP") != state_code: continue shape_obj = shape(shp['geometry']) # the vertex in the graph is named for the geoid # the county name is also stored for data matching vertex_name = shp['properties'].get("GEOID") county_name = shp['properties'].get("NAME") G.add_node(vertex_name, shape=shape_obj) name_to_geoid[county_name] = vertex_name # draw the input shapefile if draw_shapefile: plot_shapes([n[1]['shape'] for n in G.nodes(data=True)]) _connect_graph(G) if draw_graph: pos = { n[0]: [n[1]['shape'].centroid.x, n[1]['shape'].centroid.y] for n in G.nodes(data=True) } nx.draw_networkx(G, pos=pos) plt.show() G.graph['name_map'] = name_to_geoid if pickle: nx.write_gpickle(G, os.path.join(indir, infile + ".graph.pickle")) return G
def create_block_graph(block_config, block_groups: nx.Graph) -> nx.Graph: """Using a block group graph as a base, build a block graph.""" indir = block_config.get("directory", "wa-blocks") infile = block_config.get("filename", "blocks.shp") draw_shapefile = block_config.get("draw_shapefile", False) draw_graph = block_config.get("draw_graph", False) pickle = block_config.get("pickle_graph", True) reload_graph = block_config.get("reload_graph", False) if not reload_graph: if os.path.exists( os.path.join(indir, infile + ".annotated_graph.pickle")): return nx.read_gpickle( os.path.join(indir, infile + ".annotated_graph.pickle")) elif os.path.exists(os.path.join(indir, infile + ".graph.pickle")): return nx.read_gpickle( os.path.join(indir, infile + ".graph.pickle")) G = nx.Graph() # block group --> list of vertices in that block group blocks_per_block_group = defaultdict(list) with cd(indir): with fiona.open(infile) as blocks: for shp in tqdm(blocks, "Reading blocks from shapefile"): geo_id = shp['properties'].get('GEOID10') # name = shp['properties'].get('NAME10', "Block " + str(idx)) block_obj = shape(shp['geometry']) G.add_node(geo_id, shape=block_obj) # GEOID of block == GEOID of block group + block ID block_group = geo_id[:-3] blocks_per_block_group[block_group].append(geo_id) if draw_shapefile: plot_shapes([n[1]['shape'] for n in G.nodes(data=True)]) for i in tqdm(block_groups.nodes(), "Building block group subgraphs"): _connect_subgraph(G, blocks_per_block_group[i], blocks_per_block_group[i], same=True) for i, j in tqdm(block_groups.edges(), "Building cross-block group subgraphs"): _connect_subgraph(G, blocks_per_block_group[i], blocks_per_block_group[j]) if draw_graph: pos = { n[0]: [n[1]['shape'].centroid.x, n[1]['shape'].centroid.y] for n in G.nodes(data=True) } nx.draw_networkx(G, pos=pos) plt.show() if pickle: nx.write_gpickle(G, os.path.join(indir, infile + ".graph.pickle")) return G
"filename": "block-groups.shp", "pickle_graph": False, "draw_graph": False, "draw_shapefile": False, "reload_graph": False } G = shape.create_block_group_graph(block_group_config) block_config = { "directory": "blocks", "filename": "blocks.shp", "pickle_graph": False, "draw_graph": False, "draw_shapefile": False, "reload_graph": False } G2 = shape.create_block_graph(block_config, G) self.assertEqual(len(G2), 96**2) self.assertTrue(nx.is_isomorphic(G2, nx.grid_graph([96, 96]))) if __name__ == "__main__": with cd('/var/local/rohan/test_data/'): if not os.path.exists('block-groups/block-groups.shp') \ or not os.path.exists('blocks/blocks.shp'): generate_test_data() unittest.main()