Search code examples
pythongeometrybokehhexagonal-tiles

How to skew hexagonal tiles on an x,y graph, using bokeh HexTile


I am trying to create a hexmap of the UK parliamentary constituencies in python using the HexTile feature of the Bokeh library. I am attempting to emulate the Leeds ODI hexmap (https://odileeds.org/projects/hexmaps/constituencies/) and have used the q r coordinate system as supplied in their downloadable .hexjson file.

However, my plot looks skewed.

I am aware that the q r coordinate system that us used in the Bokeh HexTile feature may be different from the one that is used by the Leeds ODI. Hence why I have inverted the r value as before this plotted at a strange angle.

from bokeh.models import ColumnDataSource, Plot, LinearAxis, Grid, HoverTool
from bokeh.models.glyphs import HexTile
from bokeh.io import curdoc, show
import pandas as pd

df = pd.read_csv('/Users/georgefry/Documents/data_science/uk_pol/hex_map/cons_hex_coords.csv')

df['r'] = df['r'] * -1

df['q'] = df['q']

source = ColumnDataSource(df)

hover = HoverTool(tooltips=[('Code', '@code')])

plot = Plot(
    title=None, plot_width=300, plot_height=300,
    min_border=0, toolbar_location=None, tools=[hover])

glyph = HexTile(q="q", r="r", size=1, fill_color="#fb9a99", line_color="white")
plot.add_glyph(source, glyph)

xaxis = LinearAxis()
plot.add_layout(xaxis, 'below')

yaxis = LinearAxis()
plot.add_layout(yaxis, 'left')

plot.add_layout(Grid(dimension=1, ticker=xaxis.ticker))
plot.add_layout(Grid(dimension=0, ticker=yaxis.ticker))

curdoc().add_root(plot)

show(plot)

I appreciate that this is as much a geometry problem as a Bokeh-specific problem. I am also aware that the solution would be found by progressively skewing everything below the origin on the y-axis to the left, and everything above to the right. However, I have tried a number of transformations but none of them produced the desired result.

The desired result is something similar to the Leeds ODI link.

enter image description here


Solution

  • If you look at this image from the Bokeh docs:

    enter image description here

    You can see the "q=0" axis goes up and to the left. There are unfortunately different conventions, and some systems have a "q=0" axis that goes up and to the right. I think to convert, you will need to successively add 1 to the q value for every row in your data i.e. q+=1 for all the hexes in the first row, then q+=2 for all the hexes in the second row, etc... including taking in to account and "missing" rows of data (though you don't appear to have any in your particular data set).

    Assuming that works, please open an issue on GitHub, perhaps we can provide some sort of adapter for this situation.