Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding hover tool labels to Spans in Bokeh?

Tags:

python

bokeh

I know you can add custom labels to plots using the Label() function, but you have to specify an (x,y) cordinate to put the label.

I have a few annotations for some timeseries data that I am adding to the plot using Span(), but what I'd really love is if I could add the labels to those Span annotations that would show up whenever you hover over the Span object. It seems like something that would be simple, but I'm really struggling.

Here is the sample code I've been working on to troubleshoot this:

p = figure(x_axis_type='datetime', y_axis_type='datetime', tools='hover')

p.line(daylight_warsaw_2013.Date,daylight_warsaw_2013.Sunset, line_dash='solid', line_width=2, legend="Sunset")
p.line(daylight_warsaw_2013.Date,daylight_warsaw_2013.Sunrise, line_dash='dotted', line_width=2, legend="Sunrise")


annotations = {
    'start':{'timestamp':dt(2013, 3, 31,2,0,0),'desc':"start of daylight savings time"},
    'end':{'timestamp':dt(2013, 10, 27, 3, 0, 0),'desc':"end of daylight savings time"}
}

def auto_annotate(df,plot):
    for row in df.values(): 
        xloc = time.mktime(row['timestamp'].timetuple())*1000 
        span = Span(location=xloc, dimension='height', line_width=2, line_dash='dashed',line_color='green')
        label = Label(x=xloc, y=5000000, text=row['desc'])
        plot.add_layout(label)
        plot.add_layout(span)

auto_annotate(annotations,p)
show(p)

Keep in mind I have no idea how to use javascript.

like image 615
AustinM Avatar asked Oct 30 '22 10:10

AustinM


1 Answers

Considering that you comment that you do not know how to use JS, I propose the following solution as a possible way to implement what you want.

from bokeh.io import show, output_notebook
from bokeh.plotting import figure

from bokeh.core.properties import value
from bokeh.models import Span, HoverTool

output_notebook()

fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ["2015", "2016", "2017"]
colors = ["#c9d9d3", "#718dbf", "#e84d60"]

data = {'fruits' : fruits,
        '2015'   : [2, 1, 4, 3, 2, 4],
        '2016'   : [5, 3, 4, 2, 4, 6],
        '2017'   : [3, 2, 4, 4, 5, 3]}

p = figure(x_range=fruits, plot_height=250, title="Fruit Counts by Year",
           toolbar_location=None, tools="")

p.vbar_stack(years, x='fruits', width=0.9, color=colors, source=data,
             legend=[value(x) for x in years])

constant_line = [2.5, 2.5, 2.5, 2.5, 2.5, 2.5]
partial = p.line(fruits, constant_line, line_width=0.01, line_color='green', line_dash='dashed')

p.add_tools(HoverTool(renderers = [partial],tooltips=[("Value Constant", str(constant_line[0]))]))

daylight_savings_start = Span(location=2.5,
                              dimension='width', line_color='green',
                              line_dash='dashed', line_width=3)
p.add_layout(daylight_savings_start)


p.y_range.start = 0
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.axis.minor_tick_line_color = None
p.outline_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"
show(p)

You can run directly the previous code on a jupyter notebook only install bokeh.

The problem is that if you only paint a line it does not extend from -infinity to infinity.

enter image description here

If you add a Span on the line you will get the following result.

enter image description here

like image 110
Gerardo Gonzalez - Nemis Avatar answered Nov 11 '22 08:11

Gerardo Gonzalez - Nemis