6

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.

1 Answer 1

3

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.