So with Bokeh I can do something like this to create a hover option:
From bokeh.models import HoverTool #add hover functionality
Hover = HoverTool(tooltips=[(name1:#column1), (name2:#columns2)])
Plot = figure(tools=[hover])
Plot.circle(x,y,hover_color=’red’)
However, by doing so, I lose the standard tools you get when you call figure() like pan, box_zoom, wheel_zoom, etc. I know I can add them back 1 by 1 inside the figure(tools=[]), but is there a way to only add hover to the rest of the default tools of figure(), after it is defined??
Thanks!
Use the add_tools() method, as outlined in the docs:
https://docs.bokeh.org/en/latest/docs/user_guide/tools.html#specifying-tools
Slightly modified example from the docs:
from bokeh.plotting import figure, output_file, show
from bokeh.models import HoverTool
output_file("toolbar.html")
# create a new plot with the toolbar below
p = figure(plot_width=400, plot_height=400,
title=None, toolbar_location="below")
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)
p.add_tools(HoverTool())
show(p)
Related
I want to add a hover tool to an Arrow in add_layout. However, it seems that the hover tool does not add anything to it. Here is my code:
from bokeh.models import Arrow, VeeHead, ColumnDataSource, HoverTool
from bokeh.plotting import figure, output_file, show
output_file("arrow.html", title="arrow.py example")
p = figure(plot_width=600, plot_height=600)
p.circle(x=[0, 1, 3], y=[0, 5, 0.7], radius=0.1,
color=["navy", "yellow", "red"], fill_alpha=0.1)
data = ColumnDataSource({"x_start": [0],
"x_end": [2],
"y_start": [0],
"y_end": [1]})
p.add_layout(Arrow(end=VeeHead(size=35), line_color="red", x_start="x_start", y_start="y_start", x_end="x_end", y_end="y_end", source = data, name="arrow"))
hover_tool = HoverTool(tooltips=[('x_start', '#x_start'), ("x_end", "#x_end"), ("y_start", "#y_start")], names=["arrow"])
p.add_tools(hover_tool)
show(p)
Arrows are annotations, not glyphs, and do not support hit-testing. It is not possible to attach a hover tool to an arrow.
I wanted to put only reset toolbar on by the graph, so I was trying to like
logo=None, tools='reset'
The reset button is actually placed but instead the graph is fixed and cannot move from original position.
How can I improve it?
To move the plot you just need to add the PanTool. Check this minimal example:
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.io import curdoc
plot = figure(
width=300,
height=300,
tools='pan,reset',
logo=None,
)
x = [1, 2, 3, 4]
y = [4, 3, 2, 1]
source = ColumnDataSource(data=dict(x=x, y=y))
plot.circle(
x='x',
y='y',
source=source,
size=5,
fill_alpha=1.0,
fill_color='green',
line_color=None,
)
curdoc().add_root(plot)
Run this with bokeh serve --show example.py
I tried to plot multiple line on bokeh server and it almost work find.
But there is one problem of colors for lines.
My code is like below and when I operate in on bokeh server, it raise 'Runtime error' , why? how can i fix it?
p.multi_line('year', 'area', alpha=0.6, color=BuGn8, source=source)
RuntimeError:
Supplying a user-defined data source AND iterable values to glyph methods is
not possibe. Either:
Pass all data directly as literals:
p.circe(x=a_list, y=an_array, ...)
Or, put all data in a ColumnDataSource and pass column names:
source = ColumnDataSource(data=dict(x=a_list, y=an_array))
p.circe(x='x', y='x', source=source, ...)
bokeh.pallettes.BuGn8 is not a color, it's a list of colors. And, as the error states, you can't mix lists and a data source when using glyph methods.
If you need a different color for each line, you can add another column to your data source and pass the name of the column to the color attribute of multi_line glyph function.
A small example:
from bokeh.io import output_file, show
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.palettes import BuGn8
p = figure()
ds = ColumnDataSource(data=dict(xs=[[1, 2, 3], [2, 3, 4]],
ys=[[3, 2, 1], [4, 3, 2]],
color=[BuGn8[0], BuGn8[-1]]))
p.multi_line(xs='xs', ys='ys', color='color', source=ds, line_width=10)
output_file("test.html")
show(p)
I'm trying to generate a bokeh application which allows the user to change the glyphs of a plot. Unfortunately, the glyphs don't change after calling on_change() method of the dropdown button although I'm able to change the axis label in a similar way. However, changing plot.glyph outside of the called function works fine.
from bokeh.layouts import layout
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Dropdown
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.models.markers import Cross, Circle
source=ColumnDataSource(dict(x=[1,2,3],y=[4,5,6]))
fig=figure()
plot=fig.circle(x='x', y='y',source=source)
fig.xaxis.axis_label='This is a label'
#this changes the glyphs from circle to cross
plot.glyph=Cross(x='x', y='y', size=20, line_color='firebrick',
fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3)
def update_plot(attr,old,new):
if dropdown.value=='cross':
#this changes the axis label but not the glyphs
fig.xaxis.axis_label='Label changed'
plot.glyph=Cross(x='x', y='y', size=20, line_color='firebrick',
fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3)
elif dropdown.value=='circle':
#this also only changes the axis label but not the glyphs
fig.xaxis.axis_label='Label changed again'
plot.glyph=Circle(x='x', y='y', size=20, line_color='firebrick',
fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3)
menu=[('Circle','circle'),('Cross', 'cross')]
dropdown=Dropdown(label="Select marker", menu=menu, value='circle')
dropdown.on_change('value', update_plot)
lay_out=layout([fig, dropdown])
curdoc().add_root(lay_out)
I'm not sure about the exact reasons why your approach doesn't work, but this one works:
from bokeh.io import curdoc
from bokeh.layouts import layout
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Dropdown
from bokeh.plotting import figure
source = ColumnDataSource(dict(x=[1, 2, 3], y=[4, 5, 6]))
plot = figure()
renderers = {rn: getattr(plot, rn)(x='x', y='y', source=source,
**extra, visible=False)
for rn, extra in [('circle', dict(size=10)),
('line', dict()),
('cross', dict(size=10)),
('triangle', dict(size=15))]}
def label_fn(item):
return 'Select marker ({})'.format(item)
menu = [('No renderer', None)]
menu.extend((rn.capitalize(), rn) for rn in renderers)
dropdown = Dropdown(label=label_fn(None), menu=menu, value=None)
def update_plot(attr, old, new):
dropdown.label = label_fn(new)
for renderer_name, renderer in renderers.items():
renderer.visible = (renderer_name == new)
dropdown.on_change('value', update_plot)
lay_out = layout([plot, dropdown])
curdoc().add_root(lay_out)
Basically, I create all necessary renderers beforehand, and then just switch visible flag of each one.
Also, note the correct terminology. What you're calling a plot, is not actually a plot but a glyph renderer. And plot and figure are basically the same thing.
Note from maintainers: The specifics of this question concern the bokeh.charts API which is obsolete and was removed several years ago. In modern Bokeh, specify toolbar_location:
p = figure(toolbar_location=None)
OBSOLETE:
I don't seem to be able to remove the toolbar from a bokeh Bar chart. Despite setting the tools argument to None (or False or '') I always end up with the bokeh logo and a grey line, e.g. with this code:
from bokeh.charts import Bar, output_file, show
# prepare some data
data = {"y": [6, 7, 2, 4, 5], "z": [1, 5, 12, 4, 2]}
# output to static HTML file
output_file("bar.html")
# create a new line chat with a title and axis labels
p = Bar(data, cat=['C1', 'C2', 'C3', 'D1', 'D2'], title="Bar example",
xlabel='categories', ylabel='values', width=400, height=400,
tools=None)
# show the results
show(p)
However, when I try the same with a bokeh plot, it works perfectly fine and the toolbar is gone, e.g. with this code:
from bokeh.plotting import figure, output_file, show
output_file("line.html")
p = figure(plot_width=400, plot_height=400, toolbar_location=None)
# add a line renderer
p.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=2)
show(p)
Does anyone know what I'm doing wrong?
If you want to remove the logo and the toolbar you can do:
p.toolbar.logo = None
p.toolbar_location = None
Hope this resolves your problem
On any Bokeh plot object you can set:
p.toolbar_location = None