I have a bokeh figure that has a reset button in the toolbar. Basically, I want to \"reset\" the figure when I update the data that I\'m plotting in the figure. How can I do
Example with a radiogroup callback, that's the best way I found to reset while changing plots, just get the range of the data and set it to the range:
from bokeh.plotting import Figure
from bokeh.models import ColumnDataSource, CustomJS, RadioGroup
from bokeh.layouts import gridplot
from bokeh.resources import CDN
from bokeh.embed import file_html
x0 = range(10)
x1 = range(100)
y0 = [i for i in x0]
y1 = [i*2 for i in x1][::-1]
fig=Figure()
source1=ColumnDataSource(data={"x":[],"y":[]})
source2=ColumnDataSource(data={"x0":x0,"x1":x1,"y0":y0,"y1":y1})
p = fig.line(x='x',y='y',source=source1)
callback=CustomJS(args=dict(s1=source1,s2=source2,px=fig.x_range,py=fig.y_range), code="""
var d1 = s1.get("data");
var d2 = s2.get("data");
var val = cb_obj.active;
d1["y"] = [];
var y = d2["y"+val];
var x = d2["x"+val];
var min = Math.min( ...y );
var max = Math.max( ...y );
py.set("start",min);
py.set("end",max);
var min = Math.min( ...x );
var max = Math.max( ...x );
px.set("start",min);
px.set("end",max);
for(i=0;i<=y.length;i++){
d1["y"].push(d2["y"+val][i]);
d1["x"].push(d2["x"+val][i]);
}
s1.trigger("change");
""")
radiogroup=RadioGroup(labels=['First plot','Second plot'],active=0,callback=callback)
grid = gridplot([[fig,radiogroup]])
outfile=open('TEST.html','w')
outfile.write(file_html(grid,CDN,'Reset'))
outfile.close()
The Bokeh website is seriously lacking in examples for different ways to set callbacks for the different widgets.
UPDATE: A PR has been submitted for this feature. After Bokeh 0.12.16
is released, the following will work:
from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import Button, CustomJS
from bokeh.plotting import figure
p = figure(tools="reset,pan,wheel_zoom,lasso_select")
p.circle(list(range(10)), list(range(10)))
b = Button()
b.js_on_click(CustomJS(args=dict(p=p), code="""
p.reset.emit()
"""))
show(column(p, b))
As of Bokeh 0.12.1
there is no built in function to do this. It would possible to make a custom extension that does this. However, that would take a little work and experimentation and dialogue. If you'd like to pursue that option, I'd encourage you to come to the public mailing list which is better suited to iterative collaboration and discussion than SO. Alternatively, please feel free to open a feature request on the project issue tracker
I was struggling to make it work with Bokeh 2.2.1, but this JS p.reset.emit()
does not seem to work.
What worked for me was to manually set the Figure renderers
attribute to an empty list inside a callback function, called via on_click()
. This only works with a Bokeh server running, though:
$ bokeh serve --show example.py
example.py:
from bokeh.layouts import column
from bokeh.models import Button
from bokeh.plotting import curdoc, figure
p = figure(tools="reset,pan,wheel_zoom,lasso_select")
p.circle(list(range(10)), list(range(10)))
def clear_plot(attr):
p.renderers = []
b = Button(label="Clear plot")
b.on_click(clear_plot)
curdoc().add_root(column(p, b))