Example #1
0
def make_plot():
    source = ColumnDataSource(
        dict(
            dates=[date(2014, 3, i) for i in [1, 2, 3, 4, 5]],
            downloads=[100, 27, 54, 64, 75],
        ))

    xdr = DataRange1d(sources=[source.columns("dates")])
    ydr = DataRange1d(sources=[source.columns("downloads")])

    plot = Plot(title="Product downloads",
                x_range=xdr,
                y_range=ydr,
                plot_width=400,
                plot_height=400)

    line = Line(x="dates", y="downloads", line_color="blue")
    plot.add_glyph(source, line)

    circle = Circle(x="dates", y="downloads", fill_color="red")
    plot.add_glyph(source, circle)

    xaxis = DatetimeAxis()
    plot.add_layout(xaxis, 'below')

    yaxis = LinearAxis()
    plot.add_layout(yaxis, 'left')

    plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker))
    plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker))

    plot.add_tools(HoverTool(tooltips=dict(downloads="@downloads")))

    return plot, source
Example #2
0
    def update_source(self):

        sort_relevant, sort_crawled, sort_frontier = self.generate_data()

        # Sorted by Relevance
        # Generate the column that calculates the center of the rectangle for the rect glyph.
        sort_relevant['relevant_rect'] = sort_relevant['relevant_count'].map(lambda x: x/2)
        sort_relevant['frontier_rect'] = sort_relevant['frontier_count'].map(lambda x: x/2)
        sort_relevant['crawled_rect'] = sort_relevant['crawled_count'].map(lambda x: x/2)

        sort_relevant_source = ColumnDataSource(sort_relevant)

        # Sorted by Frontier
        # Generate the column that calculates the center of the rectangle for the rect glyph.
        sort_frontier['relevant_rect'] = sort_frontier['relevant_count'].map(lambda x: x/2)
        sort_frontier['frontier_rect'] = sort_frontier['frontier_count'].map(lambda x: x/2)
        sort_frontier['crawled_rect'] = sort_frontier['crawled_count'].map(lambda x: x/2)
        sort_frontier_source = ColumnDataSource(sort_frontier)

        # Sorted by Crawled
        # Generate the column that calculates the center of the rectangle for the rect glyph.
        sort_crawled['relevant_rect'] = sort_crawled['relevant_count'].map(lambda x: x/2)
        sort_crawled['frontier_rect'] = sort_crawled['frontier_count'].map(lambda x: x/2)
        sort_crawled['crawled_rect'] = sort_crawled['crawled_count'].map(lambda x: x/2)
        sort_crawled_source = ColumnDataSource(sort_crawled)

        return sort_relevant_source, sort_crawled_source, sort_frontier_source
Example #3
0
def make_plot():
    source = ColumnDataSource(
        dict(
            dates=[ date(2014, 3, i) for i in [1, 2, 3, 4, 5] ],
            downloads=[100, 27, 54, 64, 75],
        )
    )

    xdr = DataRange1d(sources=[source.columns("dates")])
    ydr = DataRange1d(sources=[source.columns("downloads")])

    plot = Plot(title="Product downloads", x_range=xdr, y_range=ydr, plot_width=400, plot_height=400)

    line = Line(x="dates", y="downloads", line_color="blue")
    plot.add_glyph(source, line)

    circle = Circle(x="dates", y="downloads", fill_color="red")
    plot.add_glyph(source, circle)

    xaxis = DatetimeAxis()
    plot.add_layout(xaxis, 'below')

    yaxis = LinearAxis()
    plot.add_layout(yaxis, 'left')

    plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker))
    plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker))

    plot.add_tools(HoverTool(tooltips=dict(downloads="@downloads")))

    return plot, source
Example #4
0
def trail_map(data):
    lon = (min(data.lon) + max(data.lon))/2
    lat = (min(data.lat) + max(data.lat))/2

    map_options = GMapOptions(lng=lon, lat=lat, zoom=13)
    plot = GMapPlot(title="%s - Trail Map" % title, map_options=map_options, plot_width=800, plot_height=800)

    xaxis = LinearAxis()
    plot.add_layout(xaxis, 'below')

    yaxis = LinearAxis()
    plot.add_layout(yaxis, 'left')

    xgrid = Grid(plot=plot, dimension=0, ticker=xaxis.ticker, grid_line_dash="dashed", grid_line_color="gray")
    ygrid = Grid(plot=plot, dimension=1, ticker=yaxis.ticker, grid_line_dash="dashed", grid_line_color="gray")
    plot.renderers.extend([xgrid, ygrid])

    hover = HoverTool(tooltips=dict(distance="@dist"))
    plot.add_tools(hover, PanTool(), WheelZoomTool(), ResetTool(), BoxSelectTool())

    line_source = ColumnDataSource(dict(x=data.lon, y=data.lat, dist=data.dist))

    line = Line(x="x", y="y", line_color="blue", line_width=2)
    plot.add_glyph(line_source, line)

    plot.x_range = DataRange1d(sources=[line_source.columns("x")])
    plot.y_range = DataRange1d(sources=[line_source.columns("y")])

    return plot
Example #5
0
def make_plot():
    source = ColumnDataSource(
        dict(
            dates=[date(2014, 3, i) for i in [1, 2, 3, 4, 5]],
            downloads=[100, 27, 54, 64, 75],
        ))
    xdr = DataRange1d(sources=[source.columns("dates")])
    ydr = DataRange1d(sources=[source.columns("downloads")])
    plot = Plot(title="Product downloads",
                data_sources=[source],
                x_range=xdr,
                y_range=ydr,
                width=400,
                height=400)
    line = Line(x="dates", y="downloads", line_color="blue")
    line_glyph = Glyph(data_source=source,
                       xdata_range=xdr,
                       ydata_range=ydr,
                       glyph=line)
    plot.renderers.append(line_glyph)
    circle = Circle(x="dates", y="downloads", fill_color="red")
    circle_glyph = Glyph(data_source=source,
                         xdata_range=xdr,
                         ydata_range=ydr,
                         glyph=circle)
    plot.renderers.append(circle_glyph)
    hover = HoverTool(plot=plot, tooltips=dict(downloads="@downloads"))
    plot.tools.append(hover)
    xaxis = DatetimeAxis(plot=plot, dimension=0)
    yaxis = LinearAxis(plot=plot, dimension=1)
    xgrid = Grid(plot=plot, dimension=0, axis=xaxis)
    ygrid = Grid(plot=plot, dimension=1, axis=yaxis)
    return plot, source
Example #6
0
def large_plot(n):
    from bokeh.objects import (Plot, PlotContext, LinearAxis, Grid, Glyph,
        ColumnDataSource, DataRange1d, PanTool, WheelZoomTool, BoxZoomTool,
        BoxSelectTool, BoxSelectionOverlay, ResizeTool, PreviewSaveTool,
        ResetTool)
    from bokeh.glyphs import Line

    context = PlotContext()
    objects = set([context])

    for i in xrange(n):
        source = ColumnDataSource(data=dict(x=[0, i+1], y=[0, i+1]))
        xdr = DataRange1d(sources=[source.columns("x")])
        ydr = DataRange1d(sources=[source.columns("y")])
        plot = Plot(x_range=xdr, y_range=ydr, data_sources=[source])
        xaxis = LinearAxis(plot=plot, dimension=0)
        yaxis = LinearAxis(plot=plot, dimension=1)
        xgrid = Grid(plot=plot, dimension=0)
        ygrid = Grid(plot=plot, dimension=1)
        renderer = Glyph(data_source=source, xdata_range=xdr, ydata_range=ydr, glyph=Line(x='x', y='y'))
        plot.renderers.append(renderer)
        pan = PanTool(plot=plot, dataranges=[xdr, ydr])
        wheel_zoom = WheelZoomTool(plot=plot, dataranges=[xdr, ydr])
        box_zoom = BoxZoomTool(plot=plot)
        box_select = BoxSelectTool(plot=plot)
        box_selection = BoxSelectionOverlay(tool=box_select)
        resize = ResizeTool(plot=plot)
        previewsave = PreviewSaveTool(plot=plot, dataranges=[xdr, ydr])
        reset = ResetTool(plot=plot)
        tools = [pan, wheel_zoom, box_zoom, box_select, box_selection, resize, previewsave, reset]
        plot.tools.append(tools)
        context.children.append(plot)
        objects |= set([source, xdr, ydr, plot, xaxis, yaxis, xgrid, ygrid, renderer] + tools)

    return context, objects
Example #7
0
    def create(self, doc):
        self.modelform = InstallersModel()
        self.modelform.create_inputs(doc)

        self.downloads_source = ColumnDataSource(dict(
            dates=[],
            downloads=[],
        ))
        self.punchcard_source = ColumnDataSource(
            dict(
                counts=[],
                percentages=[],
                hours=sum([[str(hour)] * 7 for hour in xrange(0, 24)], []),
                days=[
                    "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
                    "Saturday", "Sunday"
                ] * 24,
            ))
        self.update_data()

        self.downloads_plot = self.make_downloads_plot(self.downloads_source)
        self.punchcard_plot = self.make_punchcard_plot(self.punchcard_source)

        self.children.append(self.modelform)
        self.children.append(
            VBox(children=[self.downloads_plot, self.punchcard_plot]))
Example #8
0
    def __init__(self, **kw):
        super(RadialGraph, self).__init__(**kw)
        self._node_source = ColumnDataSource(dict(id=[], time=[],
                                                  relevance=[]))
        self._edge_source = ColumnDataSource(dict(parent=[], child=[]))

        self._session = Session()
        self._doc = Document()
Example #9
0
def make_plot():

    from numpy import pi, arange, sin, cos
    import numpy as np

    from bokeh.objects import (
        Plot, DataRange1d, LinearAxis, 
        ColumnDataSource, GlyphRenderer,
        PanTool, PreviewSaveTool)

    from bokeh.glyphs import Circle
    from bokeh import session

    x = arange(-2*pi, 2*pi, 0.1)
    y = sin(x)
    z = cos(x)
    widths = np.ones_like(x) * 0.02
    heights = np.ones_like(x) * 0.2

    source = ColumnDataSource(data=dict(x=x,y=y,z=z,widths=widths,
                                    heights=heights))

    xdr = DataRange1d(sources=[source.columns("x")])
    ydr = DataRange1d(sources=[source.columns("y")])

    circle = Circle(x="x", y="y", fill="red", radius=5, line_color="black")

    glyph_renderer = GlyphRenderer(
        data_source = source,
        xdata_range = xdr,
        ydata_range = ydr,
        glyph = circle)

    pantool = PanTool(dataranges = [xdr, ydr], dimensions=["width","height"])
    previewtool = PreviewSaveTool(dataranges=[xdr,ydr], dimensions=("width","height"))

    plot = Plot(x_range=xdr, y_range=ydr, data_sources=[source],
                border= 80)
    xaxis = LinearAxis(plot=plot, dimension=0)
    yaxis = LinearAxis(plot=plot, dimension=1)

    plot.renderers.append(glyph_renderer)
    plot.tools = [pantool, previewtool]

    sess = session.PlotServerSession(
        username="******",
        serverloc="http://localhost:5006", userapikey="nokey")
    sess.use_doc("glyph2")
    sess.add(plot, glyph_renderer, xaxis, yaxis, # xgrid, ygrid,
             source,  xdr, ydr, pantool, previewtool)
    sess.plotcontext.children.append(plot)
    sess.plotcontext._dirty = True
    # not so nice.. but set the model doens't know
    # that we appended to children
    sess.store_all()
    return plot
Example #10
0
def add_gauge(radius, max_value, length, direction, color, major_step, minor_step):
    major_angles, minor_angles = [], []
    major_labels, minor_labels = [], []

    total_angle = start_angle - end_angle

    major_angle_step = float(major_step)/max_value*total_angle
    minor_angle_step = float(minor_step)/max_value*total_angle

    major_angle = 0

    while major_angle <= total_angle:
        major_angles.append(start_angle - major_angle)
        major_angle += major_angle_step

    minor_angle = 0

    while minor_angle <= total_angle:
        minor_angles.append(start_angle - minor_angle)
        minor_angle += minor_angle_step

    major_labels = [ major_step*i for i, _ in enumerate(major_angles) ]
    minor_labels = [ minor_step*i for i, _ in enumerate(minor_angles) ]

    n = major_step/minor_step
    minor_angles = [ x for i, x in enumerate(minor_angles) if i % n != 0 ]
    minor_labels = [ x for i, x in enumerate(minor_labels) if i % n != 0 ]

    glyph = Arc(x=0, y=0, radius=radius, start_angle=start_angle, end_angle=end_angle, direction="clock", line_color=color, line_width=2)
    add_glyph(glyph, global_source)

    rotation = 0 if direction == 1 else -pi

    x, y = zip(*[ polar_to_cartesian(radius, angle) for angle in major_angles ])
    angles = [ angle + rotation for angle in major_angles ]
    source = ColumnDataSource(dict(x=x, y=y, angle=angles))
    plot.data_sources.append(source)

    glyph = Ray(x="x", y="y", length=length, angle="angle", line_color=color, line_width=2)
    add_glyph(glyph, source)

    x, y = zip(*[ polar_to_cartesian(radius, angle) for angle in minor_angles ])
    angles = [ angle + rotation for angle in minor_angles ]
    source = ColumnDataSource(dict(x=x, y=y, angle=angles))
    plot.data_sources.append(source)

    glyph = Ray(x="x", y="y", length=length/2, angle="angle", line_color=color, line_width=1)
    add_glyph(glyph, source)

    x, y = zip(*[ polar_to_cartesian(radius+2*length*direction, angle) for angle in major_angles ])
    text_angles = [ angle - pi/2 for angle in major_angles ]
    source = ColumnDataSource(dict(x=x, y=y, angle=text_angles, text=major_labels))
    plot.data_sources.append(source)

    glyph = Text(x="x", y="y", angle="angle", text="text", text_align="center", text_baseline="middle")
    add_glyph(glyph, source)
Example #11
0
def make_box_violin_plot(data, num_bins, maxwidth=0.9):
    """ 
    data: dict[Str -> List[Number]]
    maxwidth: float
        Maximum width of tornado plot within each factor/facet

    Returns the plot object 
    """


    df = pd.DataFrame(columns=["group", "centers", "width", "height", "texts"])
    bar_height = 50
    bins = [0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6]
    # Compute histograms, while keeping track of max Y values and max counts
    for i, (group, vals) in enumerate(data.iteritems()):
        hist, edges = np.histogram(vals, bins)
        df = df.append(pd.DataFrame(dict(
            group = group,
            centers = np.arange(len(hist))*bar_height,
            width = np.log10(hist),
            height = np.ones(hist.shape)*bar_height,
            texts = map(str,hist),
            )))
            
    df.replace(-np.inf, 0)

    # Normalize the widths
    df["width"] *= (maxwidth / df["width"].max())
    
    ds = ColumnDataSource(df)

    xdr = FactorRange(factors=sorted(df["group"].unique()))
    ydr = DataRange1d(sources=[ds.columns("centers")])

    plot = Plot(data_sources=[ds], x_range=xdr, y_range=ydr,
                title="Degree Distribution",
                plot_width=750, plot_height=600, 
                tools=[])
    xaxis = CategoricalAxis(plot=plot, location="bottom", axis_label="number of nodes")
    #yaxis = LogAxis(plot=plot, location="left", axis_label="degree")
    plot.below.append(xaxis)
    #plot.above.append(yaxis)

    #xgrid = Grid(plot=plot, dimension=0, axis=xaxis)
    #ygrid = Grid(plot=plot, dimension=1, axis=yaxis)

    glyph = Rect(x="group", y="centers", width="width", height="height")
    text_glyph = Text(x="group", y="centers", text="texts", text_baseline="middle", text_align="center")
    plot.renderers.append(Glyph(data_source=ds, xdata_range=xdr, ydata_range=ydr,
                                 glyph=glyph))
    plot.renderers.append(Glyph(data_source=ds, xdata_range=xdr, ydata_range=ydr, glyph=text_glyph))

    return plot
Example #12
0
    def __init__(self):
        from bokeh.objects import ColumnDataSource
        from bokeh.document import Document
        from bokeh.session import Session
        from bokeh.sampledata.population import load_population

        self.document = Document()
        self.session = Session()
        self.session.use_doc('population')
        self.session.load_document(self.document)

        self.df = load_population()
        self.source_pyramid = ColumnDataSource(data=dict())
Example #13
0
def plot_circle_density(nodes, degrees, plot_width=800, plot_height=800):
    print("Plotting circle density graph")
    TOOLS="hover,pan,wheel_zoom,box_zoom,reset,click,previewsave"    
    plt.figure(plot_width=plot_width, plot_height=plot_height, tools=TOOLS)
    theta = np.random.uniform(0, 2*np.pi, size=len(nodes))
    max_d, min_d = np.max(degrees), np.min(degrees)
    scale = 1.0/np.log(degrees) - 1.0/np.log(max_d)
    xs = np.cos(theta)*scale
    ys = np.sin(theta)*scale
    source_dict = dict(
        xs = xs,
        ys = ys,
        degrees = degrees,
        nodes = nodes,
        alphas = np.log(degrees)/np.log(max(degrees)),
    )
    source = ColumnDataSource(source_dict)
    plt.hold(True)
    plt.circle('xs', 'ys', source=source,
               radius=0.0025,
               fill_alpha='alphas',
               x_axis_type=None, y_axis_type=None, 
               title="Density Distribution of Degrees")
    plt.text([max(xs), max(xs)], 
             [.95*max(ys), .85*max(ys)], 
             ["distance from center = 1 / log(deg)",
              "angle = random"], 
             angle=0,
             text_baseline="bottom", text_align="right")
    hover = [t for t in plt.curplot().tools if isinstance(t, HoverTool)][0]
    hover.tooltips = OrderedDict([
        ('node', '@nodes'), ('degree', '@degrees')
    ])
    plt.hold(False)
    return plt.curplot()
Example #14
0
def sample_gear():
    xdr = Range1d(start=-30, end=30)
    ydr = Range1d(start=-30, end=30)

    source = ColumnDataSource(data=dict(dummy=[0]))
    plot = Plot(title=None,
                data_sources=[source],
                x_range=xdr,
                y_range=ydr,
                width=800,
                height=800)
    plot.tools.extend(
        [PanTool(plot=plot),
         WheelZoomTool(plot=plot),
         ResetTool(plot=plot)])

    glyph = Gear(x=0,
                 y=0,
                 module=5,
                 teeth=8,
                 angle=0,
                 shaft_size=0.2,
                 fill_color=fill_color[2],
                 line_color=line_color)
    renderer = Glyph(data_source=source,
                     xdata_range=xdr,
                     ydata_range=ydr,
                     glyph=glyph)
    plot.renderers.append(renderer)

    return plot
Example #15
0
	def to_data_source(self, df):
		index = self.reorder_dendogram(df)
		# col = lambda v: self.color(v)
		print self._color(0.2)
		_names = df.columns.tolist()
	    
		names = [_names[i] for i in index]
		xnames = []
		ynames = []
		values = []
		colors = []
		for n in names:
			xnames.extend([n] * len(names))
			ynames.extend(names)
			v = df.loc[n, names].tolist()
			values.extend(values)
			colors.extend([ self._color(x) for x in v])
		# alphas = np.abs(df.values).flatten()
		self.column_source = ColumnDataSource(
			data=dict(
				xname = xnames,
				yname = ynames,
				colors= colors,
				values= values,
			)
		)
		return self, names
Example #16
0
def classical_gear(module, large_teeth, small_teeth):
    xdr = Range1d(start=-300, end=150)
    ydr = Range1d(start=-100, end=100)

    source = ColumnDataSource(data=dict(dummy=[0]))
    plot = Plot(
        title=None,
        x_range=xdr, y_range=ydr,
        plot_width=800, plot_height=800
    )
    plot.add_tools(PanTool(), WheelZoomTool(), ResetTool())

    radius = pitch_radius(module, large_teeth)
    angle = 0
    glyph = Gear(
        x=-radius, y=0,
        module=module, teeth=large_teeth, angle=angle,
        fill_color=fill_color[0], line_color=line_color
    )
    plot.add_glyph(source, glyph)

    radius = pitch_radius(module, small_teeth)
    angle = half_tooth(small_teeth)
    glyph = Gear(
        x=radius, y=0,
        module=module, teeth=small_teeth, angle=angle,
        fill_color=fill_color[1], line_color=line_color
    )
    plot.add_glyph(source, glyph)

    return plot
Example #17
0
def large_plot(n):
    from bokeh.objects import (Plot, PlotContext, LinearAxis, Grid, Glyph,
                               ColumnDataSource, DataRange1d, PanTool,
                               WheelZoomTool, BoxZoomTool, BoxSelectTool,
                               BoxSelectionOverlay, ResizeTool,
                               PreviewSaveTool, ResetTool)
    from bokeh.glyphs import Line

    context = PlotContext()
    objects = set([context])

    for i in xrange(n):
        source = ColumnDataSource(data=dict(x=[0, i + 1], y=[0, i + 1]))
        xdr = DataRange1d(sources=[source.columns("x")])
        ydr = DataRange1d(sources=[source.columns("y")])
        plot = Plot(x_range=xdr, y_range=ydr, data_sources=[source])
        xaxis = LinearAxis(plot=plot, dimension=0)
        yaxis = LinearAxis(plot=plot, dimension=1)
        xgrid = Grid(plot=plot, dimension=0)
        ygrid = Grid(plot=plot, dimension=1)
        tickers = [
            xaxis.ticker, xaxis.formatter, yaxis.ticker, yaxis.formatter
        ]
        renderer = Glyph(data_source=source,
                         xdata_range=xdr,
                         ydata_range=ydr,
                         glyph=Line(x='x', y='y'))
        plot.renderers.append(renderer)
        pan = PanTool(plot=plot)
        wheel_zoom = WheelZoomTool(plot=plot)
        box_zoom = BoxZoomTool(plot=plot)
        box_select = BoxSelectTool(plot=plot)
        box_selection = BoxSelectionOverlay(tool=box_select)
        resize = ResizeTool(plot=plot)
        previewsave = PreviewSaveTool(plot=plot)
        reset = ResetTool(plot=plot)
        tools = [
            pan, wheel_zoom, box_zoom, box_select, box_selection, resize,
            previewsave, reset
        ]
        plot.tools.append(tools)
        context.children.append(plot)
        objects |= set(
            [source, xdr, ydr, plot, xaxis, yaxis, xgrid, ygrid, renderer] +
            tickers + tools)

    return context, objects
Example #18
0
def test_Column_data_source():
    pytest.importorskip('bokeh')
    from bokeh.objects import ColumnDataSource

    cds = into(ColumnDataSource(), data_table)

    assert isinstance(cds, ColumnDataSource)
    assert set(cds.column_names) == set(data_table.fields)
Example #19
0
    def __init__(self):
        self.document = Document()
        self.session = Session()
        self.session.use_doc('data_tables_server')
        self.session.load_document(self.document)

        self.manufacturer_filter = None
        self.model_filter = None
        self.transmission_filter = None
        self.drive_filter = None
        self.class_filter = None

        self.source = ColumnDataSource()
        self.update_data()

        self.document.add(self.create())
        self.session.store_document(self.document)
Example #20
0
def make_continuous_bar_source(df, x_field, y_field, agg):
    labels, edges = pd.cut(df[x_field], 50, retbins=True, labels=False)
    centers = pd.rolling_mean(edges, 2)[1:]
    labels = centers[labels]
    df[x_field] = labels

    group = df.groupby(x_field)[y_field]
    aggregate = getattr(group, agg)
    result = aggregate().reset_index()

    return ColumnDataSource(data=result)
Example #21
0
def sample_gear():
    xdr = Range1d(start=-30, end=30)
    ydr = Range1d(start=-30, end=30)

    source = ColumnDataSource(data=dict(dummy=[0]))
    plot = Plot(title=None, x_range=xdr, y_range=ydr, plot_width=800, plot_height=800)
    plot.add_tools(PanTool(), WheelZoomTool(), ResetTool())

    glyph = Gear(x=0, y=0, module=5, teeth=8, angle=0, shaft_size=0.2, fill_color=fill_color[2], line_color=line_color)
    plot.add_glyph(source, glyph)

    return plot
Example #22
0
def make_plot():
    source = ColumnDataSource(dict(
        dates  = [ date(2014, 3, i) for i in [1, 2, 3, 4, 5] ],
        downloads = [100, 27, 54, 64, 75],
    ))
    xdr = DataRange1d(sources=[source.columns("dates")])
    ydr = DataRange1d(sources=[source.columns("downloads")])
    plot = Plot(title="Product downloads", data_sources=[source], x_range=xdr, y_range=ydr, width=400, height=400)
    line = Line(x="dates", y="downloads", line_color="blue")
    line_glyph = Glyph(data_source=source, xdata_range=xdr, ydata_range=ydr, glyph=line)
    plot.renderers.append(line_glyph)
    circle = Circle(x="dates", y="downloads", fill_color="red")
    circle_glyph = Glyph(data_source=source, xdata_range=xdr, ydata_range=ydr, glyph=circle)
    plot.renderers.append(circle_glyph)
    hover = HoverTool(plot=plot, tooltips=dict(downloads="@downloads"))
    plot.tools.append(hover)
    xaxis = DatetimeAxis(plot=plot, dimension=0)
    yaxis = LinearAxis(plot=plot, dimension=1)
    xgrid = Grid(plot=plot, dimension=0, axis=xaxis)
    ygrid = Grid(plot=plot, dimension=1, axis=yaxis)
    return plot, source
Example #23
0
    def create(cls):
        """
        This function is called once, and is responsible for
        creating all objects (plots, datasources, etc)
        """
        obj = cls()

        obj.source = ColumnDataSource(data=dict(x=[], y=[]))

        obj.text = TextInput(title="title", name='title', value='my sin wave')

        obj.offset = Slider(title="offset",
                            name='offset',
                            value=0.0,
                            start=-5.0,
                            end=5.0)
        obj.amplitude = Slider(title="amplitude",
                               name='amplitude',
                               value=1.0,
                               start=-5.0,
                               end=5.0)
        obj.phase = Slider(title="phase",
                           name='phase',
                           value=0.0,
                           start=0.0,
                           end=2 * np.pi)
        obj.freq = Slider(title="frequency",
                          name='frequency',
                          value=1.0,
                          start=0.1,
                          end=5.1)

        obj.plot = line('x',
                        'y',
                        source=obj.source,
                        plot_width=400,
                        plot_height=400,
                        line_width=3,
                        line_alpha=0.6,
                        title=obj.text.value,
                        x_range=[0, 4 * np.pi],
                        y_range=[-2.5, 2.5])

        obj.update_data()

        obj.inputs = VBoxForm(children=[
            obj.text, obj.offset, obj.amplitude, obj.phase, obj.freq
        ])

        obj.children.append(obj.inputs)
        obj.children.append(obj.plot)

        return obj
Example #24
0
def altitude_profile(data):
    plot = Plot(title="%s - Altitude Profile" % title,
                plot_width=800,
                plot_height=400)

    xaxis = LinearAxis(axis_label="Distance (km)")
    plot.add_layout(xaxis, 'below')

    yaxis = LinearAxis(axis_label="Altitude (m)")
    plot.add_layout(yaxis, 'left')

    xgrid = Grid(plot=plot, dimension=0, ticker=xaxis.ticker)
    ygrid = Grid(plot=plot, dimension=1, ticker=yaxis.ticker)
    plot.renderers.extend([xgrid, ygrid])

    plot.add_tools(PanTool(), WheelZoomTool(), ResetTool(), BoxSelectTool())

    X, Y = data.dist, data.alt
    y0 = min(Y)

    patches_source = ColumnDataSource(
        dict(xs=[[X[i], X[i + 1], X[i + 1], X[i]] for i in range(len(X[:-1]))],
             ys=[[y0, y0, Y[i + 1], Y[i]] for i in range(len(Y[:-1]))],
             color=data.colors[:-1]))

    patches = Patches(xs="xs", ys="ys", fill_color="color", line_color="color")
    plot.add_glyph(patches_source, patches)

    line_source = ColumnDataSource(dict(
        x=data.dist,
        y=data.alt,
    ))

    line = Line(x='x', y='y', line_color="black", line_width=1)
    plot.add_glyph(line_source, line)

    plot.x_range = DataRange1d(sources=[line_source.columns("x")])
    plot.y_range = DataRange1d(sources=[line_source.columns("y")])

    return plot
Example #25
0
    def __init__(self):
        from bokeh.objects import ColumnDataSource
        from bokeh.document import Document
        from bokeh.session import Session
        from bokeh.sampledata.population import load_population

        self.document = Document()
        self.session = Session()
        self.session.use_doc('population_reveal')
        self.session.load_document(self.document)

        self.df = load_population()
        self.source_pyramid = ColumnDataSource(data=dict())
Example #26
0
File: trail.py Project: Afey/bokeh
def altitude_profile(data):
    plot = Plot(title="%s - Altitude Profile" % title, plot_width=800, plot_height=400)

    xaxis = LinearAxis(axis_label="Distance (km)")
    plot.add_layout(xaxis, 'below')

    yaxis = LinearAxis(axis_label="Altitude (m)")
    plot.add_layout(yaxis, 'left')

    xgrid = Grid(plot=plot, dimension=0, ticker=xaxis.ticker)
    ygrid = Grid(plot=plot, dimension=1, ticker=yaxis.ticker)
    plot.renderers.extend([xgrid, ygrid])

    plot.add_tools(PanTool(), WheelZoomTool(), ResetTool(), BoxSelectTool())

    X, Y = data.dist, data.alt
    y0 = min(Y)

    patches_source = ColumnDataSource(dict(
        xs = [ [X[i], X[i+1], X[i+1], X[i]] for i in range(len(X[:-1])) ],
        ys = [ [y0,   y0,     Y[i+1], Y[i]] for i in range(len(Y[:-1])) ],
        color = data.colors[:-1]
    ))

    patches = Patches(xs="xs", ys="ys", fill_color="color", line_color="color")
    plot.add_glyph(patches_source, patches)

    line_source = ColumnDataSource(dict(
        x = data.dist,
        y = data.alt,
    ))

    line = Line(x='x', y='y', line_color="black", line_width=1)
    plot.add_glyph(line_source, line)

    plot.x_range = DataRange1d(sources=[line_source.columns("x")])
    plot.y_range = DataRange1d(sources=[line_source.columns("y")])

    return plot
def line_advanced():

    source = ColumnDataSource(data=dict(x=x,y=y,z=z,widths=widths,
                heights=heights))
    
    xdr = DataRange1d(sources=[source.columns("x")])
    xdr2 = DataRange1d(sources=[source.columns("x")])
    ydr = DataRange1d(sources=[source.columns("y")])
    ydr2 = DataRange1d(sources=[source.columns("y")])
    
    line_glyph = Line(x="x", y="y", line_color="blue")
    
    renderer = GlyphRenderer(data_source = source,  xdata_range = xdr,
            ydata_range = ydr, glyph = line_glyph)
    pantool = PanTool(dataranges = [xdr, ydr], dimensions=["width","height"])
    zoomtool = ZoomTool(dataranges=[xdr,ydr], dimensions=("width","height"))
    
    plot = Plot(x_range=xdr, y_range=ydr, data_sources=[source], 
            border=50)
    plot.tools = [pantool, zoomtool]
    plot.renderers.append(renderer)
    
    #notice that these two have a differen y data range
    renderer2 = GlyphRenderer(data_source = source, xdata_range = xdr,
            ydata_range = ydr2, glyph = line_glyph)
    
    plot2 = Plot(x_range=xdr, y_range=ydr2, data_sources=[source], 
            border=50)
    
    plot2.renderers.append(renderer2)
    
    #notice that these two have a differen y data range
    renderer3 = GlyphRenderer(data_source = source, xdata_range = xdr2,
            ydata_range = ydr, glyph = line_glyph)
    
    plot3 = Plot(x_range=xdr2, y_range=ydr, data_sources=[source], 
            border=50)
    
    plot3.renderers.append(renderer3)
    
    #this is a dummy plot with no renderers
    plot4 = Plot(x_range=xdr2, y_range=ydr, data_sources=[source], 
            border=50)
    
    
    sess = session.HTMLFileSession("line_linked_advanced.html")
    sess.add(plot, renderer, source, xdr, ydr, pantool, zoomtool)
    
    sess.add(plot2, renderer2, ydr2, xdr2, renderer3, plot3, plot4)
    grid = GridPlot(children=[[plot, plot2], [plot3, plot4 ]], name="linked_advanced")
    
    sess.add(grid)
    sess.plotcontext.children.append(grid)
    
    
    sess.save(js="relative", css="relative", rootdir=os.path.abspath("."))
    print "Wrote line_linked_advanced.html"
    
        webbrowser.open("file://" + os.path.abspath("line_linked_advanced.html"))
Example #28
0
def make_plot():
    sess = session()
    data = pd.DataFrame({'a': np.random.randn(100), 'b': np.random.randn(100)})
    source = ColumnDataSource(data=data)
    scatter_plot = circle(source=source,
                          x='a',
                          y='b',
                          plot_width=500,
                          plot_height=500)
    app = App(data_source=source,
              scatter_plot=scatter_plot,
              stats=str(data.describe()))
    return app
Example #29
0
def make_box_violin_plot(data, maxwidth=0.9):
    """ 
    data: dict[Str -> List[Number]]
    maxwidth: float
        Maximum width of tornado plot within each factor/facet

    Returns the plot object 
    """
    print("Plotting box violin graph")
    plot_width = 500
    plot_height = 350
    df = pd.DataFrame(columns=["group", "width", "height", "texts", "cats"])
    bar_height = 50
    bins = [0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e10]
    # Compute histograms, while keeping track of max Y values and max counts
    for i, (group, vals) in enumerate(data.iteritems()):
        hist, edges = np.histogram(vals, bins)
        df = df.append(pd.DataFrame(dict(
            group = group,
            width = np.log2(hist[1:]),
            height = np.ones(len(hist) - 1),
            texts = ["%d Nodes" % i for i in hist[1:-1]] + ["%d" % hist[-1]],
            cats = [">10^%d" % np.log10(bin) for bin in bins[1:-1]],
            )))
            
    df.replace(-np.inf, 0)

    # Normalize the widths
    df["width"] *= (maxwidth / df["width"].max())
    
    ds = ColumnDataSource(df)

    xdr = FactorRange(factors=sorted(df["group"].unique()))
    ydr = FactorRange(factors=list(df["cats"]))

    plot = Plot(data_sources=[ds], x_range=xdr, y_range=ydr,
                title="Degree Distribution (log scale)",
                plot_width=plot_width, plot_height=plot_height, 
                tools=[])
    yaxis = CategoricalAxis(plot=plot, location="left", axis_label="degree")
    plot.left.append(yaxis)
    
    glyph = Rect(x="group", y="cats", width="width", height="height",
                 fill_color="#3366ff")
    text_glyph = Text(x="group", y="cats", text="texts", text_baseline="middle",
                      text_align="center", angle=0)
    plot.renderers.append(Glyph(data_source=ds, xdata_range=xdr, ydata_range=ydr,
                                 glyph=glyph))
    plot.renderers.append(Glyph(data_source=ds, xdata_range=xdr, ydata_range=ydr,
                                glyph=text_glyph))
    return plot
Example #30
0
 def update_data(self):
     df = mpg
     if self.manufacturer_filter:
         df = df[df["manufacturer"] == self.manufacturer_filter]
     if self.model_filter:
         df = df[df["model"] == self.model_filter]
     if self.transmission_filter:
         df = df[df["trans"] == self.transmission_filter]
     if self.drive_filter:
         df = df[df["drv"] == self.drive_filter]
     if self.class_filter:
         df = df[df["class"] == self.class_filter]
     self.source.data = ColumnDataSource.from_df(df)
     self.session.store_document(self.document)
Example #31
0
def cds():
    pytest.importorskip('bokeh')
    from bokeh.objects import ColumnDataSource
    cds = ColumnDataSource({
        'id': [1, 2, 3],
        'name': ['Alice', 'Bob', 'Charlie'],
        'amount': [100, 200, 300],
        'timestamp': [
            datetime(2000, 12, 25, 0, 0, 1),
            datetime(2001, 12, 25, 0, 0, 1),
            datetime(2002, 12, 25, 0, 0, 1)
        ]
    })
    return cds
Example #32
0
 def update_data(self):
     df = mpg
     if self.manufacturer_filter:
         df = df[df["manufacturer"] == self.manufacturer_filter]
     if self.model_filter:
         df = df[df["model"] == self.model_filter]
     if self.transmission_filter:
         df = df[df["trans"] == self.transmission_filter]
     if self.drive_filter:
         df = df[df["drv"] == self.drive_filter]
     if self.class_filter:
         df = df[df["class"] == self.class_filter]
     self.source.data = ColumnDataSource.from_df(df)
     self.session.store_document(self.document)
Example #33
0
def classical_gear(module, large_teeth, small_teeth):
    xdr = Range1d(start=-300, end=150)
    ydr = Range1d(start=-100, end=100)

    source = ColumnDataSource(data=dict(dummy=[0]))
    plot = Plot(title=None,
                data_sources=[source],
                x_range=xdr,
                y_range=ydr,
                width=800,
                height=800)
    plot.tools.extend(
        [PanTool(plot=plot),
         WheelZoomTool(plot=plot),
         ResetTool(plot=plot)])

    radius = pitch_radius(module, large_teeth)
    angle = 0
    glyph = Gear(x=-radius,
                 y=0,
                 module=module,
                 teeth=large_teeth,
                 angle=angle,
                 fill_color=fill_color[0],
                 line_color=line_color)
    renderer = Glyph(data_source=source,
                     xdata_range=xdr,
                     ydata_range=ydr,
                     glyph=glyph)
    plot.renderers.append(renderer)

    radius = pitch_radius(module, small_teeth)
    angle = half_tooth(small_teeth)
    glyph = Gear(x=radius,
                 y=0,
                 module=module,
                 teeth=small_teeth,
                 angle=angle,
                 fill_color=fill_color[1],
                 line_color=line_color)
    renderer = Glyph(data_source=source,
                     xdata_range=xdr,
                     ydata_range=ydr,
                     glyph=glyph)
    plot.renderers.append(renderer)

    return plot
Example #34
0
    def __init__(self):
        self.document = Document()
        self.session = Session()
        self.session.use_doc('data_tables_server')
        self.session.load_document(self.document)

        self.manufacturer_filter = None
        self.model_filter = None
        self.transmission_filter = None
        self.drive_filter = None
        self.class_filter = None

        self.source = ColumnDataSource()
        self.update_data()

        self.document.add(self.create())
        self.session.store_document(self.document)
Example #35
0
 def create(self, doc):
     """
     This function is called once, and is responsible for
     creating all objects (plots, datasources, etc)
     """
     self.modelform = MyModel()
     self.modelform.create_inputs(doc)
     self.source = ColumnDataSource(data={'x': [], 'y': []})
     self.update_data()
     self.plot = line('x',
                      'y',
                      source=self.source,
                      plot_width=400,
                      plot_height=400,
                      title=self.modelform.title)
     self.children.append(self.modelform)
     self.children.append(self.plot)
Example #36
0
def epicyclic_gear(module, sun_teeth, planet_teeth):
    xdr = Range1d(start=-150, end=150)
    ydr = Range1d(start=-150, end=150)

    source = ColumnDataSource(data=dict(dummy=[0]))
    plot = Plot(
        title=None,
        x_range=xdr, y_range=ydr,
        plot_width=800, plot_height=800
    )
    plot.add_tools(PanTool(), WheelZoomTool(), ResetTool())

    annulus_teeth = sun_teeth + 2*planet_teeth

    glyph = Gear(
        x=0, y=0,
        module=module, teeth=annulus_teeth, angle=0,
        fill_color=fill_color[0], line_color=line_color, internal=True
    )
    plot.add_glyph(source, glyph)

    glyph = Gear(
        x=0, y=0,
        module=module, teeth=sun_teeth, angle=0,
        fill_color=fill_color[2], line_color=line_color
    )
    plot.add_glyph(source, glyph)

    sun_radius = pitch_radius(module, sun_teeth)
    planet_radius = pitch_radius(module, planet_teeth)

    radius = sun_radius + planet_radius
    angle = half_tooth(planet_teeth)

    for i, j in [(+1, 0), (0, +1), (-1, 0), (0, -1)]:
        glyph = Gear(
            x=radius*i, y=radius*j,
            module=module, teeth=planet_teeth, angle=angle,
            fill_color=fill_color[1], line_color=line_color
        )
        plot.add_glyph(source, glyph)

    return plot
Example #37
0
    def create(cls):
        """
        This function is called once, and is responsible for
        creating all objects (plots, datasources, etc)
        """
        obj = cls()
        obj.pretext = PreText(text="", width=500, height=80)
        obj.inputs = VBoxForm()
        obj.outputs = VBox()

        #inputs
        obj.source = ColumnDataSource(data=dict(xs=[], ys=[]))
        obj.make_inputs()
        # outputs
        obj.make_data()
        obj.make_line_plot()
        obj.make_stats(err=None)
        obj.set_children()

        return obj
Example #38
0
def large_plot():
    source = ColumnDataSource(data=dict(x=[0, 1], y=[0, 1]))

    xdr = Range1d(start=0, end=1)
    xdr.tags.append("foo")
    xdr.tags.append("bar")

    ydr = Range1d(start=10, end=20)
    ydr.tags.append("foo")

    plot = Plot(x_range=xdr, y_range=ydr)

    ydr2 = Range1d(start=0, end=100)
    plot.extra_y_ranges = {"liny": ydr2}

    circle = Circle(x="x", y="y", fill_color="red", size=5, line_color="black")
    plot.add_glyph(source, circle, name="mycircle")

    line = Line(x="x", y="y")
    plot.add_glyph(source, line, name="myline")

    rect = Rect(x="x", y="y", width=1, height=1, fill_color="green")
    plot.add_glyph(source, rect, name="myrect")

    plot.add_layout(DatetimeAxis(), 'below')
    plot.add_layout(LogAxis(), 'left')
    plot.add_layout(LinearAxis(y_range_name="liny"), 'left')

    plot.add_layout(Grid(dimension=0), 'left')
    plot.add_layout(Grid(dimension=1), 'left')

    plot.add_tools(
        BoxZoomTool(),
        PanTool(),
        PreviewSaveTool(),
        ResetTool(),
        ResizeTool(),
        WheelZoomTool(),
    )

    return plot
Example #39
0
from bokeh.objects import (
    Plot, DataRange1d, LinearAxis, Rule,
    ColumnDataSource, GlyphRenderer, ObjectArrayDataSource,
    PanTool, ZoomTool)
from bokeh.glyphs import Circle
from bokeh import session

x = arange(-2*pi, 2*pi, 0.1)
y = sin(x)
z = (cos(x)+1) * 6 + 6
widths = np.ones_like(x) * 0.02
heights = np.ones_like(x) * 0.2


source = ColumnDataSource(data=dict(x=x,y=y,z=z,widths=widths,
            heights=heights))
#source = ObjectArrayDataSource(
#    data = [
#        {'x' : 1, 'y' : 5, 'z':3},
#        {'x' : 2, 'y' : 4, 'z':3, 'radius':10},
#        {'x' : 3, 'y' : 3, 'z':3, 'fill':"blue"},
#        {'x' : 4, 'y' : 2, 'z':3},
#        {'x' : 5, 'y' : 1, 'z':3},
#        ])

xdr = DataRange1d(sources=[source.columns("x")])
ydr = DataRange1d(sources=[source.columns("y")])

circle = Circle(x="x", y="y", fill="red", radius="z", line_color="black")

glyph_renderer = GlyphRenderer(
Example #40
0
from bokeh.sampledata.iris import flowers
from bokeh.objects import (
    Plot, DataRange1d, LinearAxis, Grid, ColumnDataSource, Glyph, PanTool, WheelZoomTool
)
from bokeh.glyphs import Circle
from bokeh import session

colormap = {'setosa': 'red', 'versicolor': 'green', 'virginica': 'blue'}

flowers['color'] = flowers['species'].map(lambda x: colormap[x])

source = ColumnDataSource(
    data=dict(
        petal_length=flowers['petal_length'],
        petal_width=flowers['petal_width'],
        sepal_length=flowers['sepal_length'],
        sepal_width=flowers['sepal_width'],
        color=flowers['color']
    )
)

xdr = DataRange1d(sources=[source.columns("petal_length")])
ydr = DataRange1d(sources=[source.columns("petal_width")])

circle = Circle(x="petal_length", y="petal_width", fill_color="color", fill_alpha=0.2, size=10, line_color="color")

glyph_renderer = Glyph(
        data_source = source,
        xdata_range = xdr,
        ydata_range = ydr,
        glyph = circle,
Example #41
0
# The plot server must be running

import numpy as np
from bokeh.plotting import *
import bokeh.plotting as plotting
from bokeh.objects import ColumnDataSource, DataRangeBoxSelectionTool, BoxSelectionOverlay

x = np.linspace(-7, 7, 100)
y = np.sin(x)

# Go to http://localhost:5006/bokeh to view this plot
output_server("data select example")

source = ColumnDataSource()
source.add(x, name="x")
source.add(y, name="y")
source.add(2 * y, name="2y")
source.add(3 * y, name="3y")

hold()
scatter("x", "y", source=source, tools="pan,zoom,resize")
scatter("x", "2y", source=source, tools="pan,zoom,resize")
scatter("x", "3y", source=source, color="green", tools="pan,zoom,resize")

plot = curplot()

tool = DataRangeBoxSelectionTool(plot=plot)
overlay = BoxSelectionOverlay(tool=tool)
plot.renderers.append(overlay)
plot.tools.append(tool)
plot._dirty = True
Example #42
0
from bokeh.objects import (
    Plot, DataRange1d, LinearAxis, ColumnDataSource, Glyph, PanTool, WheelZoomTool, ResizeTool
)
from bokeh.glyphs import Patches
from bokeh import session

us_states = us_states.data.copy()
us_counties = us_counties.data
unemployment = unemployment.data

del us_states['HI']
del us_states['AK']

state_source = ColumnDataSource(
    data=dict(
        state_xs=[us_states[code]['lons'] for code in us_states],
        state_ys=[us_states[code]['lats'] for code in us_states],
    )
)

colors = ["#F1EEF6", "#D4B9DA", "#C994C7", "#DF65B0", "#DD1C77", "#980043"]

county_colors = []
for county_id in us_counties:
    if us_counties[county_id]['state'] in ['ak', 'hi', 'pr', 'gu', 'vi', 'mp', 'as']:
        continue
    try:
        rate = unemployment[county_id]
        idx = min(int(rate/2), 5)
        county_colors.append(colors[idx])
    except KeyError:
        county_colors.append("black")
Example #43
0
from bokeh.browserlib import view
from bokeh.document import Document
from bokeh.embed import file_html
from bokeh.glyphs import Patch, Line, Text
from bokeh.objects import (
    ColumnDataSource, DataRange1d, DatetimeAxis, DatetimeTickFormatter,
    Glyph, Grid, Legend, Plot
)
from bokeh.resources import INLINE
from bokeh.sampledata import daylight

df = daylight.daylight_warsaw_2013

source = ColumnDataSource(dict(
    dates = df.Date,
    sunrises = df.Sunrise,
    sunsets = df.Sunset,
))

patch1_source = ColumnDataSource(dict(
    dates = np.concatenate((df.Date, df.Date[::-1])),
    times = np.concatenate((df.Sunrise, df.Sunset[::-1]))
))

summer = df[df.Summer == 1]

patch2_source = ColumnDataSource(dict(
    dates = np.concatenate((summer.Date, summer.Date[::-1])),
    times = np.concatenate((summer.Sunrise, summer.Sunset[::-1]))
))
Example #44
0
import os.path
import time

from bokeh.objects import (Plot, DataRange1d, LinearAxis, DatetimeAxis,
        ColumnDataSource, GlyphRenderer, PanTool, ZoomTool)
from bokeh.glyphs import Circle
from bokeh import session

x = arange(-2 * pi, 2 * pi, 0.1)
y = sin(x)

# Create an array of times, starting at the current time, and extending
# for len(x) number of hours.
times = np.arange(len(x)) * 3600000 + time.time()

source = ColumnDataSource(data=dict(x=x, y=y, times=times))

xdr = DataRange1d(sources=[source.columns("times")])
ydr = DataRange1d(sources=[source.columns("y")])

circle = Circle(x="times", y="y", fill_color="red", radius=5, line_color="black")

glyph_renderer = GlyphRenderer(
    data_source=source,
    xdata_range=xdr,
    ydata_range=ydr,
    glyph=circle,
)

plot = Plot(x_range=xdr, y_range=ydr, data_sources=[source],
            border=80)
Example #45
0
def generate_embed_test():
    """this generates a new plot and uses the script inject to put it
    into a page running this repeatedly will fill up your redis DB
    quickly, but it allows quick iteration

    """

    from numpy import pi, arange, sin, cos
    import numpy as np

    from bokeh.objects import (
        Plot, DataRange1d, LinearAxis, Rule,
        ColumnDataSource, GlyphRenderer, 
        PanTool, ZoomTool, PreviewSaveTool)

    from bokeh.glyphs import Circle
    from bokeh import session

    x = arange(-2*pi, 2*pi, 0.1)
    y = sin(x)
    z = cos(x)
    widths = np.ones_like(x) * 0.02
    heights = np.ones_like(x) * 0.2


    source = ColumnDataSource(data=dict(x=x,y=y,z=z,widths=widths,
                                    heights=heights))

    xdr = DataRange1d(sources=[source.columns("x")])
    ydr = DataRange1d(sources=[source.columns("y")])

    circle = Circle(x="x", y="y", fill="red", radius=5, line_color="black")

    glyph_renderer = GlyphRenderer(
        data_source = source,
        xdata_range = xdr,
        ydata_range = ydr,
        glyph = circle)


    pantool = PanTool(dataranges = [xdr, ydr], dimensions=["width","height"])
    #zoomtool = ZoomTool(dataranges=[xdr,ydr], dimensions=("width","height"))
    previewtool = PreviewSaveTool(dataranges=[xdr,ydr], dimensions=("width","height"))

    plot = Plot(x_range=xdr, y_range=ydr, data_sources=[source],
                border= 80)
    xaxis = LinearAxis(plot=plot, dimension=0)
    yaxis = LinearAxis(plot=plot, dimension=1)
    xgrid = Rule(plot=plot, dimension=0)
    ygrid = Rule(plot=plot, dimension=1)

    plot.renderers.append(glyph_renderer)
    plot.tools = [pantool, previewtool]

    sess = session.PlotServerSession(
        username="******", 
        serverloc="http://localhost:5006", userapikey="nokey")
    sess.use_doc("glyph2")
    sess.add(plot, glyph_renderer, xaxis, yaxis, xgrid, ygrid, source, 
             xdr, ydr, pantool, previewtool)
    sess.plotcontext.children.append(plot)
    sess.plotcontext._dirty = True
    # not so nice.. but set the model doens't know
    # that we appended to children
    sess.store_all()

    if app.debug:
        slug = hemlib.slug_json()
        static_js = hemlib.slug_libs(app, slug['libs'])
        hemsource = os.path.join(app.static_folder, "coffee")
        hem_js = hemlib.coffee_assets(hemsource, "localhost", 9294)
        hemsource = os.path.join(app.static_folder, "vendor",
                                 "bokehjs", "coffee")
        hem_js += hemlib.coffee_assets(hemsource, "localhost", 9294)
    else:
        static_js = ['/bokeh/static/js/application.js']
        hem_js = []
    return render_template("generate_embed_test.html", jsfiles=static_js, hemfiles=hem_js, 
                           plot_scr=plot.script_inject())
Example #46
0
class StockApp(VBox):
    extra_generated_classes = [["StockApp", "StockApp", "VBox"]]
    jsmodel = "VBox"

    # text statistics
    pretext = Instance(PreText)

    # plots
    plot = Instance(Plot)
    line_plot1 = Instance(Plot)
    line_plot2 = Instance(Plot)
    hist1 = Instance(Plot)
    hist2 = Instance(Plot)

    # data source
    source = Instance(ColumnDataSource)

    # layout boxes
    mainrow = Instance(HBox)
    histrow = Instance(HBox)
    statsbox = Instance(VBox)

    # inputs
    ticker1 = String(default="AAPL")
    ticker2 = String(default="GOOG")
    ticker1_select = Instance(Select)
    ticker2_select = Instance(Select)
    input_box = Instance(VBoxForm)

    def __init__(self, *args, **kwargs):
        super(StockApp, self).__init__(*args, **kwargs)
        self._dfs = {}

    @classmethod
    def create(cls):
        """
        This function is called once, and is responsible for
        creating all objects (plots, datasources, etc)
        """
        # create layout widgets
        obj = cls()
        obj.mainrow = HBox()
        obj.histrow = HBox()
        obj.statsbox = VBox()
        obj.input_box = VBoxForm()

        # create input widgets
        obj.make_inputs()

        # outputs
        obj.pretext = PreText(text="", width=500)
        obj.make_source()
        obj.make_plots()
        obj.make_stats()

        # layout
        obj.set_children()
        return obj

    def make_inputs(self):
        self.ticker1_select = Select(
            name='ticker1',
            value='AAPL',
            options=['AAPL', 'GOOG', 'INTC', 'BRCM', 'YHOO']
        )
        self.ticker2_select = Select(
            name='ticker2',
            value='GOOG',
            options=['AAPL', 'GOOG', 'INTC', 'BRCM', 'YHOO']
        )

    @property
    def selected_df(self):
        pandas_df = self.df
        selected = self.source.selected
        if selected:
            pandas_df = pandas_df.iloc[selected, :]
        return pandas_df

    def make_source(self):
        self.source = ColumnDataSource(data=self.df)

    def line_plot(self, ticker, x_range=None):
        plot = circle(
            'date', ticker,
            title=ticker,
            size=2,
            x_range=x_range,
            x_axis_type='datetime',
            source=self.source,
            title_text_font_size="10pt",
            plot_width=1000, plot_height=200,
            nonselection_alpha=0.02,
            tools="pan,wheel_zoom,select"
        )
        return plot

    def hist_plot(self, ticker):
        global_hist, global_bins = np.histogram(self.df[ticker + "_returns"], bins=50)
        hist, bins = np.histogram(self.selected_df[ticker + "_returns"], bins=50)
        width = 0.7 * (bins[1] - bins[0])
        center = (bins[:-1] + bins[1:]) / 2
        start = global_bins.min()
        end = global_bins.max()
        top = hist.max()
        return rect(
            center, hist/2.0, width, hist,
            title="%s hist" % ticker,
            plot_width=500, plot_height=200,
            tools="",
            title_text_font_size="10pt",
            x_range=[start, end],
            y_range=[0, top],
        )

    def make_plots(self):
        ticker1 = self.ticker1
        ticker2 = self.ticker2
        self.plot = circle(
            ticker1 + "_returns", ticker2 + "_returns",
            size=2,
            title="%s vs %s" %(ticker1, ticker2),
            source=self.source,
            plot_width=400, plot_height=400,
            tools="pan,wheel_zoom,select",
            title_text_font_size="10pt",
            nonselection_alpha=0.02,
        )
        self.line_plot1 = self.line_plot(ticker1)
        self.line_plot2 = self.line_plot(ticker2, self.line_plot1.x_range)
        self.hist_plots()

    def hist_plots(self):
        ticker1 = self.ticker1
        ticker2 = self.ticker2
        self.hist1 = self.hist_plot(ticker1)
        self.hist2 = self.hist_plot(ticker2)

    def set_children(self):
        self.children = [self.mainrow, self.histrow, self.line_plot1, self.line_plot2]
        self.mainrow.children = [self.input_box, self.plot, self.statsbox]
        self.input_box.children = [self.ticker1_select, self.ticker2_select]
        self.histrow.children = [self.hist1, self.hist2]
        self.statsbox.children = [self.pretext]

    def input_change(self, obj, attrname, old, new):
        if obj == self.ticker2_select:
            self.ticker2 = new
        if obj == self.ticker1_select:
            self.ticker1 = new
        self.make_source()
        self.make_plots()
        self.set_children()
        curdoc().add(self)

    def setup_events(self):
        super(StockApp, self).setup_events()
        if self.source:
            self.source.on_change('selected', self, 'selection_change')
        if self.ticker1_select:
            self.ticker1_select.on_change('value', self, 'input_change')
        if self.ticker2_select:
            self.ticker2_select.on_change('value', self, 'input_change')

    def make_stats(self):
        stats = self.selected_df.describe()
        self.pretext.text = str(stats)

    def selection_change(self, obj, attrname, old, new):
        self.make_stats()
        self.hist_plots()
        self.set_children()
        curdoc().add(self)

    @property
    def df(self):
        return get_data(self.ticker1, self.ticker2)
Example #47
0
class DataTables(object):

    def __init__(self):
        self.document = Document()
        self.session = Session()
        self.session.use_doc('data_tables_server')
        self.session.load_document(self.document)

        self.manufacturer_filter = None
        self.model_filter = None
        self.transmission_filter = None
        self.drive_filter = None
        self.class_filter = None

        self.source = ColumnDataSource()
        self.update_data()

        self.document.add(self.create())
        self.session.store_document(self.document)

    def create(self):
        manufacturers = sorted(mpg["manufacturer"].unique())
        models = sorted(mpg["model"].unique())
        transmissions = sorted(mpg["trans"].unique())
        drives = sorted(mpg["drv"].unique())
        classes = sorted(mpg["class"].unique())

        manufacturer_select = Select(title="Manufacturer:", value="All", options=["All"] + manufacturers)
        manufacturer_select.on_change('value', self.on_manufacturer_change)
        model_select = Select(title="Model:", value="All", options=["All"] + models)
        model_select.on_change('value', self.on_model_change)
        transmission_select = Select(title="Transmission:", value="All", options=["All"] + transmissions)
        transmission_select.on_change('value', self.on_transmission_change)
        drive_select = Select(title="Drive:", value="All", options=["All"] + drives)
        drive_select.on_change('value', self.on_drive_change)
        class_select = Select(title="Class:", value="All", options=["All"] + classes)
        class_select.on_change('value', self.on_class_change)

        columns = [
            TableColumn(field="manufacturer", header="Manufacturer", type="autocomplete", source=manufacturers),
            TableColumn(field="model", header="Model", type="autocomplete", source=models),
            TableColumn(field="displ", header="Displacement", type="numeric", format="0.00"),
            TableColumn(field="year", header="Year", type="numeric"),
            TableColumn(field="cyl", header="Cylinders", type="numeric"),
            TableColumn(field="trans", header="Transmission", type="dropdown", strict=True, source=transmissions),
            TableColumn(field="drv", header="Drive", type="autocomplete", strict=True, source=drives),
            TableColumn(field="class", header="Class", type="autocomplete", strict=True, source=classes),
            TableColumn(field="cty", header="City MPG", type="numeric"),
            TableColumn(field="hwy", header="Highway MPG", type="numeric"),
        ]
        handson_table = HandsonTable(source=self.source, columns=columns, sorting=True)

        xdr = DataRange1d(sources=[self.source.columns("index")])
        #xdr = FactorRange(factors=manufacturers)
        ydr = DataRange1d(sources=[self.source.columns("cty"), self.source.columns("hwy")])
        plot = Plot(title=None, data_sources=[self.source], x_range=xdr, y_range=ydr, plot_width=800, plot_height=300)
        xaxis = LinearAxis(plot=plot)
        plot.below.append(xaxis)
        yaxis = LinearAxis(plot=plot)
        ygrid = Grid(plot=plot, dimension=1, ticker=yaxis.ticker)
        plot.left.append(yaxis)
        cty = Glyph(data_source=self.source, glyph=Circle(x="index", y="cty", fill_color="green"))
        hwy = Glyph(data_source=self.source, glyph=Circle(x="index", y="hwy", fill_color="red"))
        select_tool = BoxSelectTool(renderers=[cty, hwy], select_y=False)
        plot.tools.append(select_tool)
        overlay = BoxSelectionOverlay(tool=select_tool)
        plot.renderers.extend([cty, hwy, ygrid, overlay])

        controls = VBox(children=[manufacturer_select, model_select, transmission_select, drive_select, class_select], width=200)
        top_panel = HBox(children=[controls, plot])
        layout = VBox(children=[top_panel, handson_table])

        return layout

    def on_manufacturer_change(self, obj, attr, _, value):
        self.manufacturer_filter = None if value == "All" else value
        self.update_data()

    def on_model_change(self, obj, attr, _, value):
        self.model_filter = None if value == "All" else value
        self.update_data()

    def on_transmission_change(self, obj, attr, _, value):
        self.transmission_filter = None if value == "All" else value
        self.update_data()

    def on_drive_change(self, obj, attr, _, value):
        self.drive_filter = None if value == "All" else value
        self.update_data()

    def on_class_change(self, obj, attr, _, value):
        self.class_filter = None if value == "All" else value
        self.update_data()

    def update_data(self):
        df = mpg
        if self.manufacturer_filter:
            df = df[df["manufacturer"] == self.manufacturer_filter]
        if self.model_filter:
            df = df[df["model"] == self.model_filter]
        if self.transmission_filter:
            df = df[df["trans"] == self.transmission_filter]
        if self.drive_filter:
            df = df[df["drv"] == self.drive_filter]
        if self.class_filter:
            df = df[df["class"] == self.class_filter]
        self.source.data = ColumnDataSource.from_df(df)
        self.session.store_document(self.document)

    def run(self, poll_interval=0.5):
        link = self.session.object_link(self.document.context)
        print("Please visit %s to see the plots (press ctrl-C to exit)" % link)

        try:
            while True:
                self.session.load_document(self.document)
                time.sleep(poll_interval)
        except KeyboardInterrupt:
            print()
        except ConnectionError:
            print("Connection to bokeh-server was terminated")
Example #48
0
def iris_splom():
    colormap = {'setosa': 'red', 'versicolor': 'green', 'virginica': 'blue'}

    flowers['color'] = flowers['species'].map(lambda x: colormap[x])


    source = ColumnDataSource(
        data=dict(
            petal_length=flowers['petal_length'],
            petal_width=flowers['petal_width'],
            sepal_length=flowers['sepal_length'],
            sepal_width=flowers['sepal_width'],
            color=flowers['color']
        )
    )
    
    text_source = ColumnDataSource(
        data=dict(center=[125])
    )
    
    xdr = DataRange1d(sources=[source.columns("petal_length", "petal_width", "sepal_length", "sepal_width")])
    ydr = DataRange1d(sources=[source.columns("petal_length", "petal_width", "sepal_length", "sepal_width")])
    
    pan = PanTool(dataranges=[xdr,ydr], dimensions=["x","y"])
    zoom = ZoomTool(dataranges=[xdr,ydr], dimensions=["x","y"])
    
    def make_plot(xname, yname, xax=False, yax=False, text=None):
        plot = Plot(
            x_range=xdr, y_range=ydr, data_sources=[source], background_fill="#ffeedd",
            width=250, height=250, border_fill='white', title="", border_symmetry="", min_border=2)
        objs = []
        if xax:
            xaxis = LinearAxis(plot=plot, dimension=0, location="bottom")
            objs.append(xaxis)
        if yax:
            yaxis = LinearAxis(plot=plot, dimension=1, location="left")
            objs.append(yaxis)
        xgrid = Grid(plot=plot, dimension=0)
        ygrid = Grid(plot=plot, dimension=1)
        circle = Circle(x=xname, y=yname, fill_color="color", fill_alpha=0.2, radius=2, line_color="color")
        circle_renderer = GlyphRenderer(
            data_source = source,
            xdata_range = xdr,
            ydata_range = ydr,
            glyph = circle,
        )
        plot.renderers.append(circle_renderer)
        plot.tools = [pan, zoom]
        if text:
            text = " ".join(text.split('_'))
            text = Text(
                x={'field':'center', 'units':'screen'}, 
                y={'field':'center', 'units':'screen'}, 
                text=text, angle=pi/4, text_font_style="bold", text_baseline="top",
                text_color="#ffaaaa", text_alpha=0.5, text_align="center", text_font_size="28pt")
            text_renderer = GlyphRenderer(
                data_source=text_source,
                xdata_range = xdr,
                ydata_range = ydr,
                glyph = text,
            )
            plot.data_sources.append(text_source)
            plot.renderers.append(text_renderer)
            objs.append(text_renderer)
            objs.append(text_source)
        return plot, objs + [circle_renderer, xgrid, ygrid]
    
    sess = session.HTMLFileSession("iris_splom.html")
    attrs = ["petal_length", "petal_width", "sepal_width", "sepal_length"]
    
    plots = []
    for y in attrs:
        row = []
        for x in attrs:
            xax = (y == attrs[-1])
            yax = (x == attrs[0])
            text = x if (x==y) else None
            plot, objs = make_plot(x, y, xax, yax, text)
            sess.add(plot, *objs)
            row.append(plot)
        plots.append(row)
    
    grid = GridPlot(children=plots, name="iris_splom")
    
    sess.add(source, xdr, ydr, pan, zoom)
    sess.add(grid)
    sess.plotcontext.children.append(grid)
    sess.save(js="relative", css="relative", rootdir=os.path.abspath("."))
    return grid
Example #49
0
# The plot server must be running
# Go to http://localhost:5006/bokeh to view this plot

import numpy as np
from bokeh.plotting import *
from bokeh.objects import ColumnDataSource, DataSlider

x = np.linspace(-7, 7, 100)
y = np.sin(x)

output_server("slider.py example")

source = ColumnDataSource()
source.add(x, name='x')
source.add(y, name='y')
source.add(2*y, name='2y')
source.add(3*y, name='3y')

hold()

scatter('x','y', source=source, tools="pan,zoom,resize")
scatter('x','2y', source=source, tools="pan,zoom,resize")
plot = scatter('x','3y', source=source, color="green", tools="pan,zoom,resize")
slider_x = DataSlider(plot=plot, data_source=source, field='x')
slider_y = DataSlider(plot=plot, data_source=source, field='y')

plot.tools.append(slider_x)
plot.tools.append(slider_y)

# This ugly line will be fixed and made unnecessary in a future release
plot._dirty = True
Example #50
0
 def make_source(self, ticker1, ticker2):
     df = self.get_data(ticker1, ticker2)
     self.source = ColumnDataSource(data=df)
Example #51
0
class StockApp(BokehApplet):
    plot = Instance(Plot, has_ref=True)
    source = Instance(ColumnDataSource, has_ref=True)
    pretext = Instance(PreText, has_ref=True)
    
    def get_data(self, ticker1, ticker2):
        fname = join(data_dir, "table_%s.csv" % ticker1.lower())
        data1 = pd.read_csv(fname, 
                            names=['date', 'foo', 'o', 'h', 'l', 'c', 'v'], 
                            header=False,
                            parse_dates=['date'])
        data1 = data1.set_index('date')
        fname = join(data_dir, "table_%s.csv" % ticker2.lower())        
        data2 = pd.read_csv(fname, 
                            names=['date', 'foo', 'o', 'h', 'l', 'c', 'v'], 
                            header=False,
                            parse_dates=['date'])
        data2 = data2.set_index('date')
        data = pd.DataFrame({ticker1 : data1.c, ticker2 : data2.c})
        data[ticker1 + "_returns"] = data[ticker1].diff()
        data[ticker2 + "_returns"] = data[ticker2].diff()
        data = data.dropna()
        return data
        
    def create(self, session):
        """
        This function is called once, and is responsible for 
        creating all objects (plots, datasources, etc)
        """
        self.modelform = StockInputModel()
        self.modelform.create_inputs(session)
        ticker1 = self.modelform.ticker1
        ticker2 = self.modelform.ticker2
        self.pretext = PreText(text="")
        self.make_source(ticker1, ticker2)
        self.make_plots(ticker1, ticker2)
        self.make_stats()
        self.set_children()
        self.add_all(session)
        
    def make_source(self, ticker1, ticker2):
        df = self.get_data(ticker1, ticker2)
        self.source = ColumnDataSource(data=df)
        
    def make_plots(self, ticker1, ticker2):
        self.plot = circle(ticker1 + "_returns", ticker2 + "_returns", 
                           title="%s vs %s" %(ticker1, ticker2),
                           source=self.source,
                           plot_width=400, plot_height=400,
                           tools="pan,wheel_zoom,select"
        )
        session().plotcontext.children=[self]
        session().plotcontext._dirty = True
        
    def set_children(self):
        self.children = [self.modelform, self.plot, self.pretext]

    def input_change(self, obj, attrname, old, new):
        """
        This function is called whenever the input form changes
        This is responsible for updating the plot, or whatever
        you want.  The signature is 
        obj : the object that changed
        attrname : the attr that changed
        old : old value of attr
        new : new value of attr
        """
        if attrname in ("ticker1", "ticker2"):
            ticker1 = self.modelform.ticker1
            ticker2 = self.modelform.ticker2
            self.make_source(ticker1, ticker2)
            self.make_plots(ticker1, ticker2)
            self.set_children()
            
    def setup_events(self):
        super(StockApp, self).setup_events()
        if self.source:
            self.source.on_change('selected', self, 'selection_change')
            
    def make_stats(self):
        pandas_df = pd.DataFrame(self.source.data)
        selected = self.source.selected
        if selected:
            pandas_df = pandas_df.iloc[selected, :]
        stats = pandas_df.describe()
        self.pretext.text = str(stats)
        
    def selection_change(self, obj, attrname, old, new):
        self.make_stats()
Example #52
0
session.load_document(document)

days_of_week = {
    0: "Monday",
    1: "Tuesday",
    2: "Wednesday",
    3: "Thursday",
    4: "Friday",
    5: "Saturday",
    6: "Sunday"
}
bounds_start = datetime.date(2012, 11, 1)
bounds_end = datetime.date(2013, 12, 30)
start = datetime.date(2013, 5, 26)
end = datetime.date(2013, 7, 5)
source_country = ColumnDataSource(data=dict())
source_dow = ColumnDataSource(data=dict())
source_jobtype = ColumnDataSource(data=dict())
source_par = Paragraph()
country_choices = [
    "Dominican Republic___________________",
    "Colombia_____________________________",
    "Mexico_______________________________",
    "Peru_________________________________",
    "Argentina____________________________"
]

countries = [
    "Brazil", "Canada", "Italy", "Panama", "Costa Rica", "Saint Martin",
    "Peru", "Argentina", "Bolivia", "Venezuela", "Ecuador", "El Salvador",
    "China", "Chile", "Puerto Rico", "Dominican Republic", "Spain", "Dubai",
Example #53
0
 def make_source(self):
     self.source = ColumnDataSource(data=self.df)
Example #54
0
import time
from bokeh.objects import (Plot, DataRange1d, LinearAxis, 
        ObjectArrayDataSource, ColumnDataSource, Glyph,
        PanTool, ZoomTool)
from bokeh.glyphs import Line
from bokeh import session

x = np.linspace(-2*pi, 2*pi, 1000)
x_static = np.linspace(-2*pi, 2*pi, 1000)
y = sin(x)
z = cos(x)
widths = np.ones_like(x) * 0.02
heights = np.ones_like(x) * 0.2

source = ColumnDataSource(
    data=dict(x=x, y=y, z=z, x_static=x_static,
              widths=widths, heights=heights))

xdr = DataRange1d(sources=[source.columns("x")])
xdr_static = DataRange1d(sources=[source.columns("x_static")])
ydr = DataRange1d(sources=[source.columns("y")])

line_glyph = Line(x="x", y="y", line_color="blue")
line_glyph2 = Line(x="x", y="z", line_color="red")
renderer = Glyph(
        data_source = source,
        xdata_range = xdr,
        ydata_range = ydr,
        glyph = line_glyph
        )
renderer2 = Glyph(
Example #55
0
class Population(object):

    year = 2010
    location = "World"

    def __init__(self):
        from bokeh.objects import ColumnDataSource
        from bokeh.document import Document
        from bokeh.session import Session
        from bokeh.sampledata.population import load_population

        self.document = Document()
        self.session = Session()
        self.session.use_doc('population_reveal')
        self.session.load_document(self.document)

        self.df = load_population()
        self.source_pyramid = ColumnDataSource(data=dict())

    def render(self):
        self.pyramid_plot()
        self.create_layout()
        self.document.add(self.layout)
        self.update_pyramid()

    def pyramid_plot(self):
        from bokeh.objects import (Plot, DataRange1d, LinearAxis, Grid, Glyph,
                                   Legend, SingleIntervalTicker)
        from bokeh.glyphs import Quad

        xdr = DataRange1d(sources=[self.source_pyramid.columns("male"),
                                   self.source_pyramid.columns("female")])
        ydr = DataRange1d(sources=[self.source_pyramid.columns("groups")])

        self.plot = Plot(title="Widgets", x_range=xdr, y_range=ydr, plot_width=600, plot_height=600)

        xaxis = LinearAxis(plot=self.plot)
        self.plot.below.append(xaxis)
        yaxis = LinearAxis(plot=self.plot, ticker=SingleIntervalTicker(interval=5))
        self.plot.left.append(yaxis)

        xgrid = Grid(plot=self.plot, dimension=0, ticker=xaxis.ticker)
        ygrid = Grid(plot=self.plot, dimension=1, ticker=yaxis.ticker)

        male_quad = Quad(left="male", right=0, bottom="groups", top="shifted", fill_color="blue")
        male_quad_glyph = Glyph(data_source=self.source_pyramid,
                                xdata_range=xdr, ydata_range=ydr, glyph=male_quad)
        self.plot.renderers.append(male_quad_glyph)

        female_quad = Quad(left=0, right="female", bottom="groups", top="shifted",
                           fill_color="violet")
        female_quad_glyph = Glyph(data_source=self.source_pyramid,
                                  xdata_range=xdr, ydata_range=ydr, glyph=female_quad)
        self.plot.renderers.append(female_quad_glyph)

        legend = Legend(plot=self.plot, legends=dict(Male=[male_quad_glyph],
                        Female=[female_quad_glyph]))
        self.plot.renderers.append(legend)

    def on_year_change(self, obj, attr, old, new):
        self.year = int(new)
        self.update_pyramid()

    def on_location_change(self, obj, attr, old, new):
        self.location = new
        self.update_pyramid()

    def create_layout(self):
        from bokeh.widgetobjects import Select, HBox, VBox

        years = list(map(str, sorted(self.df.Year.unique())))
        locations = sorted(self.df.Location.unique())

        year_select = Select(title="Year:", value="2010", options=years)
        location_select = Select(title="Location:", value="World", options=locations)

        year_select.on_change('value', self.on_year_change)
        location_select.on_change('value', self.on_location_change)

        controls = HBox(children=[year_select, location_select])
        self.layout = VBox(children=[controls, self.plot])

    def update_pyramid(self):
        pyramid = self.df[(self.df.Location == self.location) & (self.df.Year == self.year)]

        male = pyramid[pyramid.Sex == "Male"]
        female = pyramid[pyramid.Sex == "Female"]

        total = male.Value.sum() + female.Value.sum()

        male_percent = -male.Value / total
        female_percent = female.Value / total

        groups = male.AgeGrpStart.tolist()
        shifted = groups[1:] + [groups[-1] + 5]

        self.source_pyramid.data = dict(
            groups=groups,
            shifted=shifted,
            male=male_percent,
            female=female_percent,
        )
        self.session.store_document(self.document)