This docs on this page refers to a PREVIOUS VERSION. For the latest stable release, go to https://docs.bokeh.org/

Archived docs for versions <= 1.0.4 have had to be modified from their original published configuration, and may be missing some features (e.g. source listing)

All users are encourage to update to version 1.1 or later, as soon as they are able.

Adding Annotations — Bokeh 0.12.1 documentation

Adding Annotations

Bokeh includes several different types of annotations to allow users to add supplemental information to their visualizations.

Titles

Title annotations allow descriptive text to be rendered around the edges of a plot.

When using bokeh.plotting or bokeh.Charts, the quickest way to add a basic title is to pass the text as the title parameter to Figure or any Chart function:

from bokeh.plotting import figure, show, output_file

p = figure(title="Basic Title", plot_width=300, plot_height=300)
p.circle([1,2], [3,4])

output_file("title.html")

show(p)

          The default title is normally on the top of a plot, aligned to the left. But which side of the plot the default title appears on can be controlled by the title_location parameter:

          from bokeh.plotting import figure, show, output_file
          
          p = figure(title="Left Title", title_location="left",
                     plot_width=300, plot_height=300)
          p.circle([1,2], [3,4])
          
          output_file("title.html")
          
          show(p)
          

                  The default Title is accessible through the Plot.title property. Visual properties for font, border, background, and others can be set directly on .title. Here is an example that sets font and background properties as well as the title text and title alignment using .title:

                  from bokeh.plotting import figure, show, output_file
                  
                  p = figure(plot_width=300, plot_height=300)
                  p.circle([1,2], [3,4])
                  
                  # configure visual properties on a plot's title attribute
                  p.title.text = "Title With Options"
                  p.title.align = "right"
                  p.title.text_color = "orange"
                  p.title.text_font_size = "25px"
                  p.title.background_fill_color = "#aaaaee"
                  
                  output_file("title.html")
                  
                  show(p)
                  

                          Note that the alignment is measured along the direction of text. For example for titles on the left side of a plot “left” will be in the lower corner.

                          In addition to the default title, it is possible to create and add additional Title objects to plots using the add_layout method of Plots:

                          from bokeh.models import Title
                          from bokeh.plotting import figure, show, output_file
                          
                          p = figure(title="Left Title", title_location="left",
                                     plot_width=300, plot_height=300)
                          p.circle([1,2], [3,4])
                          
                          # add extra titles with add_layout(...)
                          p.add_layout(Title(text="Bottom Centered Title", align="center"), "below")
                          
                          output_file("title.html")
                          
                          show(p)
                          

                                  If a title and a sticky toolbar are set to the same side, they will occupy the same space:

                                  from bokeh.plotting import figure, show, output_file
                                  
                                  p = figure(title="Top Title with Toolbar", toolbar_location="above",
                                             plot_width=600, plot_height=300)
                                  p.circle([1,2], [3,4])
                                  
                                  output_file("title.html")
                                  
                                  show(p)
                                  

                                          If the plot size is large enough, this can result in a more compact plot. However if the plot size is not large enough, the title and toolbar may visually overlap in way that is not desirable.

                                          Legends

                                          It is possible to create Legend annotations easily by specifying a legend argument to the glyph methods, when creating a plot.

                                          Note

                                          This example depends on the open source NumPy library in order to more easily generate better data suitable for demonstrating legends.

                                          import numpy as np
                                          from bokeh.plotting import output_file, show, figure
                                          
                                          x = np.linspace(0, 4*np.pi, 100)
                                          y = np.sin(x)
                                          
                                          output_file("legend.html")
                                          
                                          p = figure()
                                          
                                          p.circle(x, y, legend="sin(x)")
                                          p.line(x, y, legend="sin(x)")
                                          
                                          p.line(x, 2*y, legend="2*sin(x)",
                                                 line_dash=[4, 4], line_color="orange", line_width=2)
                                          
                                          p.square(x, 3*y, legend="3*sin(x)", fill_color=None, line_color="green")
                                          p.line(x, 3*y, legend="3*sin(x)", line_color="green")
                                          
                                          show(p)
                                          

                                                  Arrows

                                                  Arrow annotations can be used to connect glyphs and label annotations or to simply highlight plot regions. Arrows are compound annotations, meaning that their``start`` and end attributes are themselves other ArrowHead annotations. By default, the Arrow annotation is one-sided with the end set as an OpenHead-type arrow head (an open-backed wedge style) and the start property set to None. Double-sided arrows can be created by setting both the start and end properties as appropriate ArrowHead subclass instances.

                                                  Arrows have standard line properties to set the color and appearance of the arrow shaft:

                                                  my_arrow.line_color = "blue"
                                                  my_arrow.line_alpha = 0.6
                                                  

                                                  Arrows may also be configured to refer to additional non-default x- or y-ranges with the x_range and y_range properties, in the same way as Twin Axes.

                                                  Additionally any arrow head objects in start or end have a size property to control how big the arrow head is, as well as both line and fill properties. The line properties control the outline of the arrow head, and the fill properties control the interior of the arrow head (if applicable).

                                                  from bokeh.plotting import figure, output_file, show
                                                  from bokeh.models import Arrow, OpenHead, NormalHead, VeeHead
                                                  
                                                  output_file("arrow.html", title="arrow.py example")
                                                  
                                                  p = figure(plot_width=600, plot_height=600)
                                                  
                                                  p.circle(x=[0, 1, 0.5], y=[0, 0, 0.7], radius=0.1,
                                                           color=["navy", "yellow", "red"], fill_alpha=0.1)
                                                  
                                                  p.add_layout(Arrow(end=OpenHead(line_color="firebrick", line_width=4),
                                                                     x_start=0, y_start=0, x_end=1, y_end=0))
                                                  
                                                  p.add_layout(Arrow(end=NormalHead(fill_color="orange"),
                                                                     x_start=1, y_start=0, x_end=0.5, y_end=0.7))
                                                  
                                                  p.add_layout(Arrow(end=VeeHead(size=35), line_color="red",
                                                                     x_start=0.5, y_start=0.7, x_end=0, y_end=0))
                                                  
                                                  show(p)
                                                  

                                                          Box Annotations

                                                          A BoxAnnotation can be linked to either data or screen coordinates in order to emphasize specific plot regions. By default, box annotation dimensions (e.g. left or top) default will extend the annotation to the edge of the plot area.

                                                          from bokeh.sampledata.glucose import data
                                                          from bokeh.plotting import figure, show, output_file
                                                          from bokeh.models import BoxAnnotation
                                                          
                                                          output_file("box_annotation.html", title="box_annotation.py example")
                                                          
                                                          TOOLS = "pan,wheel_zoom,box_zoom,reset,save"
                                                          
                                                          #reduce data size
                                                          data = data.ix['2010-10-06':'2010-10-13']
                                                          
                                                          p = figure(x_axis_type="datetime", tools=TOOLS)
                                                          
                                                          p.line(data.index.to_series(), data['glucose'], line_color="gray", line_width=1, legend="glucose")
                                                          
                                                          low_box = BoxAnnotation(top=80, fill_alpha=0.1, fill_color='red')
                                                          mid_box = BoxAnnotation(bottom=80, top=180, fill_alpha=0.1, fill_color='green')
                                                          high_box = BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color='red')
                                                          
                                                          p.add_layout(low_box)
                                                          p.add_layout(mid_box)
                                                          p.add_layout(high_box)
                                                          
                                                          p.title.text = "Glucose Range"
                                                          p.xgrid[0].grid_line_color=None
                                                          p.ygrid[0].grid_line_alpha=0.5
                                                          p.xaxis.axis_label = 'Time'
                                                          p.yaxis.axis_label = 'Value'
                                                          
                                                          show(p)
                                                          

                                                                    Labels

                                                                    Labels are text elements that can be used to annotate either glyphs or plot regions.

                                                                    To create a single text label, use the Label annotation. This annotation is configured with a text property containing the text to be displayed, as well as x and y properties to set the position (in screen or data space units). Additionally a render mode "canvas" or "css" may be specified. Finally, labels have text, border_line, and background_fill properties. These control the visual appearance of the text, as well as the border and background of the bounding box for the text:

                                                                    Label(x=70, y=70, x_units='screen' text='Some Stuff', render_mode='css',
                                                                          border_line_color='black', border_line_alpha=1.0,
                                                                          background_fill_color='white', background_fill_alpha=1.0)
                                                                    

                                                                    To create several labels at once, possibly to easily annotate another existing glyph, use the LabelSet annotation, which is configured with a data source, with the text and x and y positions are given as column names. LabelSet objects can also have x_offset and y_offset, which specify a distance in screen space units to offset the label positions from x and y. Finally the render level may be controlled with the level property, to place the label above or underneath other renderers:

                                                                    LabelSet(x='x', y='y', text='names', level='glyph',
                                                                             x_offset=5, y_offset=5, source=source)
                                                                    

                                                                    The following example illustrates the use of both:

                                                                    from bokeh.plotting import figure, show, output_file
                                                                    from bokeh.models import ColumnDataSource, Range1d, LabelSet, Label
                                                                    
                                                                    output_file("label.html", title="label.py example")
                                                                    
                                                                    source = ColumnDataSource(data=dict(height=[66, 71, 72, 68, 58, 62],
                                                                                                        weight=[165, 189, 220, 141, 260, 174],
                                                                                                        names=['Mark', 'Amir', 'Matt', 'Greg',
                                                                                                               'Owen', 'Juan']))
                                                                    
                                                                    p = figure(title='Dist. of 10th Grade Students at Lee High',
                                                                               x_range=Range1d(140, 275))
                                                                    p.scatter(x='weight', y='height', size=8, source=source)
                                                                    p.xaxis[0].axis_label = 'Weight (lbs)'
                                                                    p.yaxis[0].axis_label = 'Height (in)'
                                                                    
                                                                    labels = LabelSet(x='weight', y='height', text='names', level='glyph',
                                                                                  x_offset=5, y_offset=5, source=source, render_mode='canvas')
                                                                    
                                                                    citation = Label(x=70, y=70, x_units='screen', y_units='screen',
                                                                                     text='Collected by Luke C. 2016-04-01', render_mode='css',
                                                                                     border_line_color='black', border_line_alpha=1.0,
                                                                                     background_fill_color='white', background_fill_alpha=1.0)
                                                                    
                                                                    p.add_layout(labels)
                                                                    p.add_layout(citation)
                                                                    
                                                                    show(p)
                                                                    
                                                                            Collected by Luke C. 2016-04-01

                                                                            Spans

                                                                            Span annotations are lines that have a single dimension (width or height) and extend to the edge of the plot area.

                                                                            from datetime import datetime as dt
                                                                            import time
                                                                            
                                                                            from bokeh.sampledata.daylight import daylight_warsaw_2013
                                                                            from bokeh.plotting import figure, show, output_file
                                                                            from bokeh.models import Span
                                                                            
                                                                            output_file("span.html", title="span.py example")
                                                                            
                                                                            p = figure(x_axis_type="datetime", y_axis_type="datetime")
                                                                            
                                                                            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")
                                                                            
                                                                            start_date = time.mktime(dt(2013, 3, 31, 2, 0, 0).timetuple())*1000
                                                                            daylight_savings_start = Span(location=start_date,
                                                                                                          dimension='height', line_color='green',
                                                                                                          line_dash='dashed', line_width=3)
                                                                            p.add_layout(daylight_savings_start)
                                                                            
                                                                            end_date = time.mktime(dt(2013, 10, 27, 3, 0, 0).timetuple())*1000
                                                                            daylight_savings_end = Span(location=end_date,
                                                                                                        dimension='height', line_color='red',
                                                                                                        line_dash='dashed', line_width=3)
                                                                            p.add_layout(daylight_savings_end)
                                                                            
                                                                            p.title.text = "2013 Sunrise and Sunset times in Warsaw"
                                                                            p.yaxis.axis_label = 'Time of Day'
                                                                            
                                                                            show(p)