Source code for

"""This is the Bokeh charts interface. It gives you a high level API
to build complex plot is a simple way.

This is the Horizon class which lets you build your Horizon charts
just passing the arguments to the Chart class and calling the proper
# Copyright (c) 2012 - 2014, Anaconda, Inc. All rights reserved.
# Powered by the Bokeh Development Team.
# The full license is in the file LICENSE.txt, distributed with this software.

# Imports
from __future__ import absolute_import

from bokeh.charts.builder import create_and_build
from bokeh.charts.glyphs import HorizonGlyph
from .line_builder import LineBuilder
from import Float, Int, List, string_types, String, Color, Bool
from ..attributes import ColorAttr, IdAttr
from ...models.sources import ColumnDataSource
from ...models.axes import CategoricalAxis
from ...models.ranges import FactorRange, DataRange1d

# Classes and functions

[docs]def Horizon(data=None, x=None, y=None, series=None, **kws): """ Create a horizon chart using :class:`HorizonBuilder <>` to render the geometry from values. Args: data (:ref:`userguide_charts_data_types`): table-like data x (str or list(str), optional): the column label to use for the x dimension y (str or list(str), optional): the column label to use for the y dimension In addition to the parameters specific to this chart, :ref:`userguide_charts_defaults` are also accepted as keyword parameters. Returns: :class:`Chart`: includes glyph renderers that generate the scatter points Examples: .. bokeh-plot:: :source-position: above import pandas as pd from bokeh.charts import Horizon, output_file, show # read in some stock data from the Yahoo Finance API AAPL = pd.read_csv( "", parse_dates=['Date']) MSFT = pd.read_csv( "", parse_dates=['Date']) IBM = pd.read_csv( "", parse_dates=['Date']) data = dict([ ('AAPL', AAPL['Adj Close']), ('Date', AAPL['Date']), ('MSFT', MSFT['Adj Close']), ('IBM', IBM['Adj Close'])] ) hp = Horizon(data, x='Date', plot_width=800, plot_height=300, title="horizon plot using stock inputs") output_file("horizon.html") show(hp) """ kws['x'] = x kws['y'] = y kws['series'] = series tools = kws.get('tools', True) if tools == True: tools = "save,reset" elif isinstance(tools, string_types): tools = tools.replace('pan', '') tools = tools.replace('wheel_zoom', '') tools = tools.replace('box_zoom', '') tools = tools.replace(',,', ',') kws['tools'] = tools chart = create_and_build(HorizonBuilder, data, **kws) # Hide numerical axis chart.left[0].visible = False # Add the series names to the y axis chart.extra_y_ranges = {"series": FactorRange(factors=chart._builders[0].series_names)} chart.add_layout(CategoricalAxis(y_range_name="series"), 'left') return chart
[docs]class HorizonBuilder(LineBuilder): """Produces glyph renderers representing a horizon chart from many input types. The builder handles ingesting the data, deriving settings when not provided, building the renderers, then setting ranges, and modifying the chart as needed. """ # class configuration glyph = HorizonGlyph default_attributes = {'color': ColorAttr(sort=False), 'series': IdAttr(sort=False)} # primary input properties pos_color = Color("#006400", help=""" The color of the positive folds. (default: "#006400") """) neg_color = Color("#6495ed", help=""" The color of the negative folds. (default: "#6495ed") """) num_folds = Int(3, help=""" The number of folds stacked on top of each other. (default: 3) """) flip_neg = Bool(default=True, help="""When True, the negative values will be plotted as their absolute value, then their individual axes is flipped. If False, then the negative values will still be taken as their absolute value, but the base of their shape will start from the same origin as the positive values. """) # derived properties series_count = Int(help="""Count of the unique series names.""") bins = List(Float, help="""The binedges calculated from the number of folds, and the maximum value of the entire source data.""") series_column = String(help="""The column that contains the series names.""") fold_height = Float(help="""The size of the bin.""")
[docs] def setup(self): super(HorizonBuilder, self).setup() # collect series names and columns selected to color by if self.attributes['series'].columns is None: self.series_column = self.attributes['color'].columns[0] else: self.series_column = self.attributes['series'].columns[0] if len(self.series_names) == 0: self.set_series(self.series_column) self.series_count = len(self.series_names)
[docs] def process_data(self): super(HorizonBuilder, self).process_data() # calculate group attributes, useful for each horizon glyph self.fold_height = max(self.y.max, abs(self.y.min))/self.num_folds self.bins = [bin_id * self.fold_height for bin_id in range(self.num_folds + 1)] # manually set attributes to have constant color ds = ColumnDataSource(self._data.df) self.attributes['series'].setup(data=ds, columns=self.series_column) self.attributes['color'].setup(data=ds, columns=self.pos_color)
[docs] def set_ranges(self): super(HorizonBuilder, self).set_ranges() self.x_range = DataRange1d(range_padding=0) self.y_range.start = 0 self.y_range.end = self.y.max