Bokeh - multilines with hover tool

Hello all,

Im trying to generate multiline chart with cycles in the points (example only with 2 lines) and let bokeh display multiple information from ColumnDataSource , but unfortuna telly Im not able to let display cycle “y Coordinates” for each line separatelly.

Bokeh version: latest
Python: 3.11

from bokeh.plotting import show, figure
from bokeh.models import DataRange1d
from bokeh.models import CrosshairTool, Span
from bokeh.models import HoverTool
from bokeh.models import ColumnDataSource
import pandas

# Defaults
Figure_sizing_mode = "stretch_width"
Figure_height=350
X_Seris_Format = "linear"  
X_Series_Column = "TAH_Order" 


# ToolTip
ToolTip = [
    ("Category", "@Category"), 
    ("Date", "@TAH_Date{%F}"), 
    ("Value", "@y{0.00}")]

ToolTip_Format = {
    "@Category": "numeral",
    "@TAH_Date": "datetime",
    "@y": "numeral"}

# Data
Value_dict = {
    "TAH_Order": [1,2,3,4,5,6,7,8,9,10],
    "TAH_Date": ["2023-06-01","2023-06-01","2023-06-02","2023-06-02","2023-06-03","2023-06-03","2023-06-04","2023-06-04","2023-06-05","2023-06-05"],
    "Category": ["CAT1","CAT1","CAT1","CAT1","CAT1","CAT1","CAT1","CAT1","CAT1","CAT1"],
    "Max_value": [44,11,29,32,29,43,49,35,29,50],
    "Min_value": [1,3,9,4,12,11,3,7,10,17]}
Value_df = pandas.DataFrame(data=Value_dict)
DataSource = ColumnDataSource(data = Value_df)

# Tools

# Hover Tool
Hover_Tool = HoverTool()
Hover_Tool.tooltips = ToolTip
Hover_Tool.muted_policy = "ignore"
Hover_Tool.formatters = ToolTip_Format
Hover_Tool.mode = "vline"

# Crosshair
Span_height = Span(dimension="height", line_dash="dashed", line_width=2, line_color="#878787")
Crosshair_Tool = CrosshairTool(overlay=Span_height)

# Chart
Chart = figure(sizing_mode = Figure_sizing_mode, height=Figure_height, toolbar_location="below", x_axis_type=X_Seris_Format)

# Chart - Lines
GS_Line_Max = Chart.line(x=Value_df["TAH_Order"], y=Value_df["Max_value"], line_width= 1, line_color = "red", line_join = "round", legend_label="Maximal", muted_alpha=0.2)
GS_Line_Min = Chart.line(x=Value_df["TAH_Order"], y=Value_df["Min_value"], line_width= 1, line_color = "green", line_join = "round", legend_label="Minimal", muted_alpha=0.2)

# Chart - Cycles --> ment to be in Hover Tool
GS_Cycles_Max = Chart.circle(source=DataSource, x=X_Series_Column, y="Max_value", size=10, fill_color = "white", line_color="red", hover_fill_color="red", legend_label="Maximal", muted_alpha=0.2)
GS_Cycles_Min = Chart.circle(source=DataSource, x=X_Series_Column, y="Min_value", size=10, fill_color = "white", line_color="green", hover_fill_color="green", legend_label="Minimal", muted_alpha=0.2)

Chart.add_tools(Hover_Tool)
Chart.add_tools(Crosshair_Tool)
Chart.hover.renderers = [GS_Cycles_Min,GS_Cycles_Max]

show(Chart)


→ always has three question marks “???”
→ at the point there shoudl be values:
for red line: “Value: 32”
for greenline: “Value: 4”

If I use column name of ColumnDataSource then in displais same value for both lines:

# ToolTip
ToolTip = [
    ("Category", "@Category"), 
    ("Date", "@TAH_Date{%F}"), 
    ("Value", "@Max_value{0.00}")]

ToolTip_Format = {
    "@Category": "numeral",
    "@TAH_Date": "datetime",
    "@Max_value": "numeral"}


→ wrong for green line

Do you have any idea how to get it?

Need to add that this is simplest example I have also chart with 15 lines and mode depending on variables.

Thank you

Jan Vaško

Additionally it worked when I didnt used “ColumnDataSource” and insted of it I used directly pandas DataFrame:

# Chart - Cycles --> ment to be in Hover Tool
GS_Cycles_Max = Chart.circle(x=Value_df["TAH_Order"], y=Value_df["Max_value"], size=10, fill_color = "white", line_color="red", hover_fill_color="red", legend_label="Maximal", muted_alpha=0.2)
GS_Cycles_Min = Chart.circle(x=Value_df["TAH_Order"], y=Value_df["Min_value"], size=10, fill_color = "white", line_color="green", hover_fill_color="green", legend_label="Minimal", muted_alpha=0.2)

and Tooltip was like:

# ToolTip
ToolTip = [
    ("Value", "@y{0.00}")]

ToolTip_Format = {
    "@y": "numeral"}

→ but in this case I was not able to apply pandas different column from dataframe into HoverTool.

Would $y get the job done instead? That’s usually what I end up resorting to, but have gone to complicated CustomJSHovers as well…

Hello,

the “$y” is not working as it display the Y co-ordinance in chart not related to glyph but to are it self.

ToolTip = [
    ("Category", "@Category"), 
    ("Date", "@TAH_Date{%F}"), 
    ("Value", "$y{0.00}")]

Link to youtube: https://youtu.be/viMVcPXamNs

Dont you have any other idea?

Thank you

Jan

That’s because when you don’t provide a CDS, Bokeh creates one internally (there is always a CDS) and gives it generic column names like “y” for the y-coordinate. In your CDS, you name the columns whatever you like, and you do not have a “y” column in your CDS. That is why @y shows ???. A display of ??? always means only one thing: the column you asked to reference does not exist in the CDS.

For this specific case, I can only think of two options:

  • Use two separate hover tools (with their renderers appropriately restricted to one glyph) to show a different column for each separate glyph
  • Use one multi_line instead of separate line calls so that there is only one column for a single hover tool to need to reference.

It might also be possible to use a CustomJSHover to conditionally display one field or the other in some way (perhaps via $glyph_view) but this is speculation, I don’t have any concrete examples to provide.

Hello Bryan,

thank you for your answer, which is great as usual. unforutnatelly I cannot use “multi_line” beucase hover tool should work based on “circle” glyphs - any idea how to solve it?

I was about to thig recreate the original Pandas Dataframe to use only one column with both informaiton inside, but this will lead to unability to mute one of the line.

Bryan this is the easier example I have, as I can have also multi lines like 7 or more with mute function.

Thank you

Jan

I cannot use “multi_line” beucase hover tool should work based on “circle” glyphs

A “multi-scatter” was recently proposed, but it has not yet been implemented.

[FEATURE] MultiScatter · Issue #12367 · bokeh/bokeh · GitHub

I think your options are multiple hover tools (one per line/marker combo) or to try to coax CustomJSHover to do what you need. I’d refer you to this PR

New vars and cleanup for hover tooltips by bryevdv · Pull Request #12147 · bokeh/bokeh · GitHub

That added special_vars.glyph_view to the collection of “special” values that a CustomJSHover can access. You might have luck using, e.g. special_vars.glyph._y to get the y-coords specifically for the glyph being hovered over. Note this is currently a private attr, we have not had a chance to discuss changes to make it public. Alternatively, you could probably dig through special_vars.glyph.model to look up the y column name, and then use that to conditionally show the right column. I don’t have any concrete code to share beyond these suggestions, however.

Hello Bryan,

thank you. I temporary solved by adding charts generation into for loop and create ColumnDataSource in ieach step + adding new “virtuall” column caled “Y_Values” which is with every loop overwritten by different column from DataFrame. So the column “Y_Values” is assigned everytime to “y” so it let me have one columnt name for HoverTool in multiple lines / Circles charts.

Thank you

Jan

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.