Bokeh color not appearing on hover tooltip - python

I'm experimenting with Bokeh and running into a frustrating problem with the hovertool. It lists fill color as one of the basic tooltips covered.
http://docs.bokeh.org/en/latest/docs/user_guide/tools.html#hover-tool
I tried a test and the color will not appear on the hovertool. It doesn't even give me the "???" it usually does when you give it a input it doesn't understand, it just ignores it completely. Anyone have a clue as to why it wouldn't display one of the basic tooltips?
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.models import HoverTool
output_file("toolbar.html")
source = ColumnDataSource(
data=dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
desc=['A', 'b', 'C', 'd', 'E'],
)
)
hover = HoverTool(
tooltips=[
("fill color", "$color[hex, swatch]:fill_color"),
("index", "$index"),
("(x,y)", "($x, $y)"),
("desc", "#desc"),
]
)
p = figure(plot_width=400, plot_height=400, tools=[hover],
title="Mouse over the dots")
p.circle('x', 'y', size=20, source=source, fill_color="black")
show(p)

Hover tooltips can only inspect values from actual columns in a column data source. Since you have given a fixed value, i.e. fill_color="black" there is no column to inspect. Additionally, the special hover field $color with hex only understands hex color strings.
Here is your code modified to work:
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.models import HoverTool
output_file("toolbar.html")
source = ColumnDataSource(
data=dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
desc=['A', 'b', 'C', 'd', 'E'],
fill_color=['#88ffaa', '#aa88ff', '#ff88aa', '#2288aa', '#6688aa']
)
)
hover = HoverTool(
tooltips=[
("index", "$index"),
("fill color", "$color[hex, swatch]:fill_color"),
("(x,y)", "($x, $y)"),
("desc", "#desc"),
]
)
p = figure(plot_width=400, plot_height=400, tools=[hover],
title="Mouse over the dots")
p.circle('x', 'y', size=20, source=source, fill_color="fill_color")
show(p)

Related

Bokeh OpenURL does not work with HTML Output File in GCP JuypterLab

I use a Notebook in GCP Jupyter Lab.
Why does this Bokeh example, open an URL by clicking on a glyph, does work in a Jupyter Notebook but not with output_file(eg. "openurl.html")?
https://docs.bokeh.org/en/latest/docs/user_guide/interaction/callbacks.html?highlight=interaction
from bokeh.models import ColumnDataSource, OpenURL, TapTool
from bokeh.plotting import figure, output_file, show
output_file("openurl.html")
p = figure(plot_width=400, plot_height=400,
tools="tap", title="Click the Dots")
source = ColumnDataSource(data=dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
color=["navy", "orange", "olive", "firebrick", "gold"]
))
p.circle('x', 'y', color='color', size=20, source=source)
# use the "color" column of the CDS to complete the URL
# e.g. if the glyph at index 10 is selected, then #color
# will be replaced with source.data['color'][10]
url = "http://www.colors.commutercreative.com/#color/"
taptool = p.select(type=TapTool)
taptool.callback = OpenURL(url=url)
show(p)
On my local machine, the example does work in both cases (in a Notebook and the exported HTML). But not in GCP JupyterLab.
My question is, what is needed that it works in the GCP JupyterLab with HTML Export as well?
Thanks for help.

How can I get the coordinates of a click in a plot on python side?

I have a plot with circles on it and I want users to be able to select circles and then I want to do some stuff on python side depending on the circle.
I have tried JS callbacks but I get the error:
WARNING:bokeh.embed.util: You are generating standalone HTML/JS
output, but trying to use real Python callbacks (i.e. with on_change
or on_event). This combination cannot work. Only JavaScript callbacks
may be used with standalone output. For more information on JavaScript
callbacks with Bokeh, see:
http://docs.bokeh.org/en/latest/docs/user_guide/interaction/callbacks.html
Alternatively, to use real Python callbacks, a Bokeh server
application may be used. For more information on building and running
Bokeh applications, see:
http://docs.bokeh.org/en/latest/docs/user_guide/server.html
Here's some code if you want to try to do it.
from bokeh.plotting import figure, output_file, show
output_file("openurl.html")
p = figure(plot_width=400, plot_height=400, tools="tap", title="Click the Dots")
source = ColumnDataSource(data=dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
color=["navy", "orange", "olive", "firebrick", "gold"]
))
p.circle('x', 'y', color='color', size=20, source=source)```
I didnt quite understand your question, but you can use hover tool to add interaction, or LabelSet to display your x/y along with the dots.
from bokeh.plotting import figure
from bokeh.io import show, output_notebook
output_notebook()
p = figure(plot_width=400, plot_height=400, tools="tap, reset, hover", title="Click
the Dots", tooltips = [('x', '#x'),('y','#y')])
source = ColumnDataSource(data=dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
color=["navy", "orange", "olive", "firebrick", "gold"]
))
p.circle('x', 'y', color='color', size=20, source=source)
show(p)

Bokeh show text on click

I saw this example
from bokeh.models import ColumnDataSource, OpenURL, TapTool
from bokeh.plotting import figure, output_file, show
output_file("openurl.html")
p = figure(plot_width=400, plot_height=400,
tools="tap", title="Click the Dots")
source = ColumnDataSource(data=dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
color=["navy", "orange", "olive", "firebrick", "gold"]
))
p.circle('x', 'y', color='color', size=20, source=source)
# use the "color" column of the CDS to complete the URL
# e.g. if the glyph at index 10 is selected, then #color
# will be replaced with source.data['color'][10]
url = "http://www.colors.commutercreative.com/#color/"
taptool = p.select(type=TapTool)
taptool.callback = OpenURL(url=url)
show(p)
I would like to do something similar, instead of opening the url, I would like to show some text on the right when i click on the circle related to that circle. And the text should change when I click on another circle.
I also saw this: https://docs.bokeh.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-user-interaction-events but I couldn't change the mouse prints with some text based on the circle.
Thank you.
use CustomJS instead of OpenUrl
from bokeh.models import CustomJS
taptool.callback = CustomJS(code="""
var ind = cb_data.index['1d'].indices[0];
var color = cb_obj.source.data['color'][ind];
$('#div_id').text(color);
""")
more explanations see here JavaScript callback to get selected glyph index in Bokeh

Python bokeh apply hovertools only on model not on figure

I want to have a scatter plot and a (base)line on the same figure. And I want to use HoverTool only on the circles of scatter but not on the line. Is it possible?
With the code below I get tooltips with index: 0 and (x, y): (???, ???) when I hover on the line (any part of the line). But the index: 0 data in source is totally different ((x, y): (1, 2))...
df = pd.DataFrame({'a':[1, 3, 6, 9], 'b':[2, 3, 5, 8]})
from bokeh.models import HoverTool
import bokeh.plotting as bplt
TOOLS = ['box_zoom', 'box_select', 'wheel_zoom', 'reset', 'pan', 'resize', 'save']
source = bplt.ColumnDataSource(data=df)
hover = HoverTool(tooltips=[("index", "$index"), ("(x, y)", "(#a, #b)")])
p = bplt.figure(plot_width=600, plot_height=600, tools=TOOLS+[hover],
title="My sample bokeh plot", webgl=True)
p.circle('a', 'b', size=10, source=source)
p.line([0, 10], [0, 10], color='red')
bplt.save(p, 'c:/_teszt.html')
Thank you!!
To limit which renderers you want the HoverTool is active on (by default it's active on all) you can either set a name attr on your glyphs, then specify which names you want your HoverTool to be active on:
p.circle('a', 'b', size=10, name='circle', source=source)
hover = HoverTool(names=['circle'])
docs:
http://docs.bokeh.org/en/latest/docs/reference/models/tools.html#bokeh.models.tools.HoverTool.names
or you can add the renderers to the HoverTool.
circle = p.circle('a', 'b', size=10, source=source)
hover = HoverTool(renderers=['circle'])
docs:
http://docs.bokeh.org/en/latest/docs/reference/models/tools.html#bokeh.models.tools.HoverTool.renderers

Bokeh - How to Click and Drag?

I would like to click-and-drag the scatter points the points of a bokeh scatter plot. Any ideas how to do this?
(edit: this is an example of what I'd like to do)
For an example of a scatter, the code below generates the scatter plot chart found half-way through this page.
from bokeh.plotting import figure, output_file, show
# create a Figure object
p = figure(width=300, height=300, tools="pan,reset,save")
# add a Circle renderer to this figure
p.circle([1, 2.5, 3, 2], [2, 3, 1, 1.5], radius=0.3, alpha=0.5)
# specify how to output the plot(s)
output_file("foo.html")
# display the figure
show(p)
Multi-gesture edit tools are only a recent addition, landing in version 0.12.14. You can find much more information in the Edit Tools section of the User's Guide.
Specifically to be able to move points as described in the OP, use the PointDrawTool:
Here is a complete example you can run that also has a data table showing the updated coordinates of the glyphs as they are moved (you will need to activate the tool in the toolbar first, it is off by default):
from bokeh.plotting import figure, output_file, show, Column
from bokeh.models import DataTable, TableColumn, PointDrawTool, ColumnDataSource
output_file("tools_point_draw.html")
p = figure(x_range=(0, 10), y_range=(0, 10), tools=[],
title='Point Draw Tool')
p.background_fill_color = 'lightgrey'
source = ColumnDataSource({
'x': [1, 5, 9], 'y': [1, 5, 9], 'color': ['red', 'green', 'yellow']
})
renderer = p.scatter(x='x', y='y', source=source, color='color', size=10)
columns = [TableColumn(field="x", title="x"),
TableColumn(field="y", title="y"),
TableColumn(field='color', title='color')]
table = DataTable(source=source, columns=columns, editable=True, height=200)
draw_tool = PointDrawTool(renderers=[renderer], empty_value='black')
p.add_tools(draw_tool)
p.toolbar.active_tap = draw_tool
show(Column(p, table))

Categories