Auto set vbar line_width based on x_range in Bokeh

bokeh, graph, python

Solution

I finally figured this out with help from @bigreddot. It turns out that I was using the wrong property. Instead of using `line_width` I needed to use `width`. Since my `x_range` is a `datetime` range, and `datetimes` are expressed in milliseconds, I needed a large enough width to display correctly. This takes care of setting a proportional width when zooming in, since the width represents a specific period on the `x_axis`.

Since I have a function to change the `freq` of how I group my columns and update my `ColumnDataSource.data`, I just need to re-calculate the `width` when I update it.

Here's the working code:

def get_data(freq='MS'):
    return pd.DataFrame(srs.groupby(pd.Grouper(freq=freq)).mean())

source = ColumnDataSource(data=ColumnDataSource.from_df(get_data()))

def get_width():
    mindate = min(source.data['date'])
    maxdate = max(source.data['date'])
    return 0.8 * (maxdate-mindate).total_seconds()*1000 / len(source.data['date'])

f = figure(plot_width=550, plot_height=400, x_axis_type="datetime")
f.x_range.set(bounds='auto')
r = f.vbar(source=source, top='volume', x='date', width=get_width())
bar_glyph = f.renderers[-1].glyph

handle = show(f, notebook_handle=True)

and my update function:

def update_data(freq={'Quarter': 'QS', 'Month': 'MS', 'Week': 'W'}):
    source.data = ColumnDataSource.from_df(get_data(freq))
    r.glyph.width = get_width()
    push_notebook()

i = interact(update_data)

Problem

I have a `vbar` tied to a `ColumnDataSource` which gets updated based on some widget selections. If I start with `line_width=5` it looks great with my initial data. However, when I update the graph, the `x_range` gets updated to fit the updated data and causes the relative width of the bars to change. Ideally, the width should always be proportional to the number of bars displayed. I tried looking at the various properties on the `x_range` and `xaxis` to see if I could get the range and try to calculate the width myself but I haven't found anything that helps. Been looking around and the documentation and nothing. Any thoughts?

Original source