Skip to content

Commit

Permalink
Merge branch 'master' into bokeh_charts
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Dec 19, 2015
2 parents 61b2dce + 22e8b38 commit 2d56070
Show file tree
Hide file tree
Showing 3 changed files with 0 additions and 395 deletions.
235 changes: 0 additions & 235 deletions holoviews/plotting/bokeh/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,238 +227,3 @@ def get_data(self, element, ranges=None, empty=False):
err_xs.append((x, x))
err_ys.append((y - neg, y + pos))
return (dict(xs=err_xs, ys=err_ys), self._mapping)



class SpikesPlot(PathPlot):

color_index = param.Integer(default=1, doc="""
Index of the dimension from which the color will the drawn""")

spike_length = param.Number(default=0.5, doc="""
The length of each spike if Spikes object is one dimensional.""")

position = param.Number(default=0., doc="""
The position of the lower end of each spike.""")

style_opts = (['color', 'cmap', 'palette'] + line_properties)

def get_extents(self, element, ranges):
l, b, r, t = super(SpikesPlot, self).get_extents(element, ranges)
if len(element.dimensions()) == 1:
b, t = self.position, self.position+self.spike_length
return l, b, r, t


def get_data(self, element, ranges=None, empty=False):
style = self.style[self.cyclic_index]
dims = element.dimensions(label=True)

pos = self.position
if empty:
xs, ys, keys = [], [], []
mapping = dict(xs=dims[0], ys=dims[1] if len(dims) > 1 else 'heights')
elif len(dims) > 1:
xs, ys = zip(*(((x, x), (pos, pos+y))
for x, y in element.array()))
mapping = dict(xs=dims[0], ys=dims[1])
keys = (dims[0], dims[1])
else:
height = self.spike_length
xs, ys = zip(*(((x[0], x[0]), (pos, pos+height))
for x in element.array()))
mapping = dict(xs=dims[0], ys='heights')
keys = (dims[0], 'heights')

if not empty and self.invert_axes: keys = keys[::-1]
data = dict(zip(keys, (xs, ys)))

cmap = style.get('palette', style.get('cmap', None))
if self.color_index < len(dims) and cmap:
cdim = dims[self.color_index]
map_key = 'color_' + cdim
mapping['color'] = map_key
if empty:
colors = []
else:
cmap = get_cmap(cmap)
cvals = element.dimension_values(cdim)
crange = ranges.get(cdim, None)
colors = map_colors(cvals, crange, cmap)
data[map_key] = colors

return data, mapping



class SideSpikesPlot(SpikesPlot):
"""
SpikesPlot with useful defaults for plotting adjoined rug plot.
"""

xaxis = param.ObjectSelector(default='top-bare',
objects=['top', 'bottom', 'bare', 'top-bare',
'bottom-bare', None], doc="""
Whether and where to display the xaxis, bare options allow suppressing
all axis labels including ticks and xlabel. Valid options are 'top',
'bottom', 'bare', 'top-bare' and 'bottom-bare'.""")

yaxis = param.ObjectSelector(default='right-bare',
objects=['left', 'right', 'bare', 'left-bare',
'right-bare', None], doc="""
Whether and where to display the yaxis, bare options allow suppressing
all axis labels including ticks and ylabel. Valid options are 'left',
'right', 'bare' 'left-bare' and 'right-bare'.""")

height = param.Integer(default=80, doc="Height of plot")

width = param.Integer(default=80, doc="Width of plot")





class ChartPlot(ElementPlot):


def initialize_plot(self, ranges=None, plot=None, plots=None, source=None):
"""
Initializes a new plot object with the last available frame.
"""
# Get element key and ranges for frame
element = self.hmap.last
key = self.keys[-1]
ranges = self.compute_ranges(self.hmap, key, ranges)
ranges = match_spec(element, ranges)
self.current_ranges = ranges
self.current_frame = element
self.current_key = key

# Initialize plot, source and glyph
if plot is not None:
raise Exception("Can't overlay Bokeh Charts based plot properties")

init_element = element.clone(element.interface.concat(self.hmap.values()))
plot = self._init_chart(init_element, ranges)
self.handles['plot'] = plot
self.handles['glyph_renderers'] = [r for r in plot.renderers
if isinstance(r, GlyphRenderer)]
self._update_chart(element, ranges)

# Update plot, source and glyph
self.drawn = True

return plot

def update_frame(self, key, ranges=None, plot=None, element=None):
"""
Updates an existing plot with data corresponding
to the key.
"""
element = self._get_frame(key)
if not element:
if self.dynamic and self.overlaid:
self.current_key = key
element = self.current_frame
else:
element = self._get_frame(key)
else:
self.current_key = key
self.current_frame = element

self.set_param(**self.lookup_options(element, 'plot').options)
ranges = self.compute_ranges(self.hmap, key, ranges)
ranges = match_spec(element, ranges)
self.current_ranges = ranges

self._update_chart(element, ranges)


def _update_chart(self, element, ranges):
new_chart = self._init_chart(element, ranges)
old_chart = self.handles['plot']
old_renderers = old_chart.select(type=GlyphRenderer)
new_renderers = new_chart.select(type=GlyphRenderer)

old_chart.y_range.update(**new_chart.y_range.properties_with_values())
updated = []
for new_r in new_renderers:
for old_r in old_renderers:
if type(old_r.glyph) == type(new_r.glyph):
old_renderers.pop(old_renderers.index(old_r))
new_props = new_r.properties_with_values()
source = new_props.pop('data_source')
old_r.glyph.update(**new_r.glyph.properties_with_values())
old_r.update(**new_props)
old_r.data_source.data.update(source.data)
updated.append(old_r)
break

for old_r in old_renderers:
if old_r not in updated:
emptied = {k: [] for k in old_r.data_source.data}
old_r.data_source.data.update(emptied)


@property
def current_handles(self):
plot = self.handles['plot']
sources = plot.select(type=ColumnDataSource)
return sources


class BoxPlot(ChartPlot):
"""
BoxPlot generates a box and whisker plot from a BoxWhisker
Element. This allows plotting the median, mean and various
percentiles. Displaying outliers is currently not supported
as they cannot be consistently updated.
"""

def _init_chart(self, element, ranges):
plot = BokehBoxPlot(element.dframe(),
label=element.dimensions('key', True),
values=element.dimensions('value', True)[0])

# Disable outliers for now as they cannot be consistently updated.
plot.renderers = [r for r in plot.renderers
if not (isinstance(r, GlyphRenderer) and
isinstance(r.glyph, Circle))]
return plot


class BarPlot(ChartPlot):
"""
BoxPlot generates a box and whisker plot from a BoxWhisker
Element. This allows plotting the median, mean and various
percentiles. Displaying outliers is currently not supported
as they cannot be consistently updated.
"""

group_index = param.Integer(default=0, doc="""
Index of the dimension in the supplied Bars
Element, which will be laid out into groups.""")

category_index = param.Integer(default=1, doc="""
Index of the dimension in the supplied Bars
Element, which will be laid out into categories.""")

stack_index = param.Integer(default=2, doc="""
Index of the dimension in the supplied Bars
Element, which will stacked.""")

def _init_chart(self, element, ranges):
kdims = element.dimensions('key', True)
vdim = element.dimensions('value', True)[0]
kwargs = {}
if self.group_index < element.ndims:
kwargs['group'] = kdims[self.group_index]
if self.category_index < element.ndims:
kwargs['label'] = kdims[self.category_index]
if self.stack_index < element.ndims:
kwargs['stack'] = kdims[self.stack_index]
crange = Range1d(*ranges.get(vdim))
plot = Bar(element.dframe(), values=vdim,
continuous_range=crange, **kwargs)
return plot

2 changes: 0 additions & 2 deletions holoviews/plotting/mpl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ def grid_selector(grid):
VectorField: VectorFieldPlot,
ErrorBars: ErrorPlot,
Spread: SpreadPlot,
BoxWhisker: BoxPlot,
Spikes: SpikesPlot,

# General plots
GridSpace: GridPlot,
Expand Down
Loading

0 comments on commit 2d56070

Please sign in to comment.