from bokeh.plotting import figure, show, output_notebook
import json
from bokeh import palettes
from bokeh import plotting
import numpy as np
import ogr
from bokeh.models import HoverTool, TapTool
from bokeh.models import ColumnDataSource
from bokeh.models import Patches
from bokeh.models.widgets import Tabs, Panel
import json
import ogr
import pandas as pd
def getAttributes(inds):
# read the attributes of a vector (OGR) dataset and
# returns it as a Pandas DataFrame, including the
# geometry, which is formatted for Bokeh (xs, ys)
def getFielddef(lyr):
# function to get the field definitions
# of the attributes
lyrdef = lyr.GetLayerDefn()
fielddef = {}
for i in range(lyrdef.GetFieldCount()):
fdef = lyrdef.GetFieldDefn(i)
fielddef[fdef.GetName()] = (i, fdef.GetTypeName())
return fielddef
# open dataset and layer
ds = ogr.Open(inds)
lyr = ds.GetLayer(0)
lyr.ResetReading()
ft = lyr.GetNextFeature()
features = []
fielddef = getFielddef(lyr)
# loop over all features
while ft:
ft_atts = {}
# read all atributes for the feature
for att_name, (i, att_type) in fielddef.items():
if att_type == 'String':
ft_atts[att_name] = ft.GetFieldAsString(att_name)
elif att_type == 'Integer':
ft_atts[att_name] = ft.GetFieldAsInteger(att_name)
elif att_type == 'Real':
ft_atts[att_name] = ft.GetFieldAsDouble(att_name)
elif att_type == 'Date':
ft_atts[att_name] = pd.datetools.parse(ft.GetField(i))
elif att_type == 'DateTime':
ft_atts[att_name] = pd.datetools.parse(ft.GetFieldAsDateTime(att_name)).to_datetime()
# get the geometry
geom = ft.GetGeometryRef()
geom_json = json.loads(geom.ExportToJson())
geom_type = geom.GetGeometryType()
if geom_type == ogr.wkbMultiPolygon:
# append NaN after each part of a multipolygon
ys = [list(zip(*sum(poly, [])))[1] for poly in geom_json['coordinates']]
ys = sum([list(part) + [float('NaN')] for part in ys], [])
xs = [list(zip(*sum(poly, [])))[0] for poly in geom_json['coordinates']]
xs = sum([list(part) + [float('NaN')] for part in xs], [])
elif geom_type == ogr.wkbPolygon:
denest = list(zip(*sum(geom_json['coordinates'], [])))
ys = denest[1]
xs = denest[0]
ft_atts['xs'] = xs
ft_atts['ys'] = ys
sr = pd.Series(ft_atts)
sr.name = ft.GetFID()
features.append(sr)
ft = lyr.GetNextFeature()
attributes = pd.concat(features, axis=1).T
attributes.index.name = 'FID'
ds = None
return attributes
infile = r'gem_2011_gn1_utf8.shp'
# read the attributes, including the geometry
df = getAttributes(infile)
# view the DF
df[['AANT_INW','AANT_MAN','AANT_VROUW','xs', 'ys']].head()
AANT_INW | AANT_MAN | AANT_VROUW | xs | ys | |
---|---|---|---|---|---|
FID | |||||
0 | 12090 | 5870 | 6220 | (254800.0000000013, 254800.0000000013, 254700.... | (596500.0000000028, 596000.0, 595500.000000001... |
1 | 10495 | 5280 | 5215 | (235500.0000000022, 235900.00000000154, 236100... | (596300.0, 595600.0, 595600.0, 595300.0, 59500... |
2 | 9400 | 4740 | 4665 | (272800.0, 274500.00000000093, 274700.00000000... | (576200.0, 574900.0, 575500.0, 575700.0, 57570... |
3 | 7455 | 3740 | 3710 | (245600.0, 246100.00000000218, 246600.0, 24680... | (591800.0, 591100.0, 590700.0, 591100.0, 59040... |
4 | 26565 | 13295 | 13270 | (253000.00000000224, 253800.00000000084, 25390... | (603900.0, 603400.0000000002, 603400.000000000... |
# discrete mapping, how linear?
# this should be easier...
color_key = 'AANT_INW'
cmap = palettes.Blues9[::-1]
vmax = df[color_key].max() / 2.
n = len(cmap)-1
df['inw_color'] = [cmap[min(int(round(val / vmax * n)), n)] for val in df[color_key]]
color_key = 'AANT_MAN'
cmap = palettes.Greens9[::-1]
vmax = df[color_key].max() / 2.
n = len(cmap)-1
df['man_color'] = [cmap[min(int(round(val / vmax * n)), n)] for val in df[color_key]]
color_key = 'AANT_VROUW'
cmap = palettes.Reds9[::-1]
vmax = df[color_key].max() / 2.
n = len(cmap)-1
df['vrouw_color'] = [cmap[min(int(round(val / vmax * n)), n)] for val in df[color_key]]
source = ColumnDataSource(df)
def make_map(source, fill_color='inw_color'):
polys = Patches(xs='xs',
ys='ys',
fill_color=fill_color,
line_color='black'
)
selected_polys = Patches(xs='xs',
ys='ys',
fill_color=fill_color,
line_color='red',
line_width=5)
p = figure(title='Gemeenten',
plot_width=600,
plot_height=640,
x_range=[0, 300000],
y_range=[300000, 620000],
toolbar_location=None,
outline_line_color='#FFFFFF',
min_border=0,
tools='')
p.add_glyph(source, polys, selection_glyph=selected_polys, nonselection_glyph=polys)
p.add_tools(TapTool())
hover = p.select(dict(type=HoverTool))
ttip = [("Naam", "@GM_NAAM"),
("Inwoners", "@AANT_INW"),
("Mannen", "@AANT_MAN"),
("Vrouwen", "@AANT_VROUW")]
p.add_tools(HoverTool(tooltips=ttip))
return p
inw_plot = make_map(source, fill_color='inw_color')
man_plot = make_map(source, fill_color='man_color')
vrouw_plot = make_map(source, fill_color='vrouw_color')
tabs = Tabs(tabs=[
Panel(title="Inwoners", child=inw_plot),
Panel(title="Mannen", child=man_plot),
Panel(title="Vrouwen", child=vrouw_plot),
])
show(tabs)