def test_dynamic_groupby_kdims_and_streams(self): def plot_function(mydim, data): return Scatter(data[data[:, 2]==mydim]) buff = Buffer(data=np.empty((0, 3))) dmap = DynamicMap(plot_function, streams=[buff], kdims='mydim').redim.values(mydim=[0, 1, 2]) ndlayout = dmap.groupby('mydim', container_type=NdLayout) self.assertIsInstance(ndlayout[0], DynamicMap) data = np.array([(0, 0, 0), (1, 1, 1), (2, 2, 2)]) buff.send(data) self.assertEqual(ndlayout[0][()], Scatter([(0, 0)])) self.assertEqual(ndlayout[1][()], Scatter([(1, 1)])) self.assertEqual(ndlayout[2][()], Scatter([(2, 2)]))
class BokehApp: def __init__(self): self.switch_key = 'peak_8' self.maxlen = 1000000 # Initialize buffers self.b_th_peak = Buffer(pd.DataFrame({ 'peak': [], 'lowerbound': [], 'higherbound': [] }), length=1000000) # Initialize callbacks self.callback_id_th_b = None def clear_buffer(self): """ Modified version of hv.buffer.clear() since original appears to be buggy Clear buffer/graph whenever switch is toggled """ with util.disable_constant(self.b_th_peak): self.b_th_peak.data = self.b_th_peak.data.iloc[:0] self.b_th_peak.send( pd.DataFrame({ 'peak': [], 'lowerbound': [], 'higherbound': [] })) def produce_timehistory(self, context, doc): """ Create timetool data timehistory Parameters ---------- context = zmq.Context() Creates zmq socket to receive data doc: bokeh.document (I think) Bokeh document to be displayed on webpage """ # Port to connect to master port = 5000 socket = context.socket(zmq.SUB) # MUST BE FROM SAME MACHINE, CHANGE IF NECESSARY!!! socket.connect("tcp://localhost:%d" % port) socket.setsockopt(zmq.SUBSCRIBE, b"") # Dynamic Maps plot_peak_b = hv.DynamicMap( partial(hv.Points, kdims=['index', 'peak']), streams=[self.b_th_peak]).options( width=1000, finalize_hooks=[apply_formatter ]).redim.label(index='Time in UTC') plot_peak_std_low = hv.DynamicMap( partial(hv.Curve, kdims=['index', 'lowerbound']), streams=[self.b_th_peak]).options( line_alpha=0.5, line_color='gray').redim.label(index='Time in UTC') plot_peak_std_high = hv.DynamicMap( partial(hv.Curve, kdims=['index', 'higherbound']), streams=[self.b_th_peak]).options( line_alpha=0.5, line_color='gray').redim.label(index='Time in UTC') # Decimate and datashade pointTest = decimate(plot_peak_b, streams=[hv.streams.PlotSize]) test1 = datashade(plot_peak_std_low, streams=[hv.streams.PlotSize], normalization='linear').options( width=1000, finalize_hooks=[apply_formatter]) test2 = datashade(plot_peak_std_high, streams=[hv.streams.PlotSize], normalization='linear') plot = (pointTest * test1 * test2) # Use bokeh to render plot hvplot = renderer.get_plot(plot, doc) def push_data(stream): """ Push data to timetool time history graph """ median = pd.DataFrame({'peak': []}) lowerbound = pd.DataFrame({'peak': []}) higherbound = pd.DataFrame({'peak': []}) # Maybe fix this for stopping no data coming in? And switching issue? (Right now it's a feature) if socket.poll(timeout=0): data_dict = socket.recv_pyobj() peakDict = data_dict['peakDict'] peakTSDict = data_dict['peakTSDict'] TS_key = self.switch_key + '_TS' data = list(peakDict[self.switch_key]) timestamp = list(peakTSDict[TS_key]) times = [1000 * time for time in timestamp] dataSeries = pd.Series(data, index=times) zipped = basic_event_builder(peak=dataSeries) median = zipped.rolling(120, min_periods=1).median() std = zipped.rolling(120, min_periods=1).std() lowerbound = median - std higherbound = median + std df = pd.DataFrame({ 'peak': median['peak'], 'lowerbound': lowerbound['peak'], 'higherbound': higherbound['peak'] }) stream.send(df) def switch(attr, old, new): """ Update drop down menu value """ self.switch_key = select.value self.clear_buffer() print("Yes!") def play_graph(): """ Provide play and pause functionality to the graph """ if startButton.label == '► Play': startButton.label = '❚❚ Pause' self.callback_id_th_b = doc.add_periodic_callback( partial(push_data, stream=self.b_th_peak), 1000) else: startButton.label = '► Play' doc.remove_periodic_callback(self.callback_id_th_b) peak_list = [ 'peak_8', 'peak_9', 'peak_10', 'peak_11', 'peak_12', 'peak_13', 'peak_14', 'peak_15' ] select = Select(title='Peak:', value='peak_8', options=peak_list) select.on_change('value', switch) startButton = Button(label='❚❚ Pause') startButton.on_click(play_graph) self.callback_id_th_b = doc.add_periodic_callback( partial(push_data, stream=self.b_th_peak), 1000) plot = column(select, startButton, hvplot.state) doc.title = "Time History Graphs" doc.add_root(plot)
def _process_data(self, kind, data, x, y, by, groupby, row, col, use_dask, persist, backlog, label, value_label, hover_cols, kwds): gridded = kind in self._gridded_types gridded_data = False # Validate DataSource self.data_source = data self.is_series = is_series(data) if self.is_series: data = data.to_frame() if is_intake(data): data = process_intake(data, use_dask or persist) if groupby is not None and not isinstance(groupby, list): groupby = [groupby] if by is not None and not isinstance(by, list): by = [by] streaming = False if isinstance(data, pd.DataFrame): self.data = data if is_geopandas(data) and kind is None: geom_types = set( [gt[5:] if 'Multi' in gt else gt for gt in data.geom_type]) if len(geom_types) > 1: raise ValueError( 'The GeopandasInterface can only read dataframes which ' 'share a common geometry type') geom_type = list(geom_types)[0] if geom_type == 'Point': kind = 'points' elif geom_type == 'Polygon': kind = 'polygons' elif geom_type in ('LineString', 'LineRing'): kind = 'paths' elif is_dask(data): self.data = data.persist() if persist else data elif is_streamz(data): self.data = data.example self.stream_type = data._stream_type streaming = True self.cb = data if data._stream_type == 'updating': self.stream = Pipe(data=self.data) else: self.stream = Buffer(data=self.data, length=backlog, index=False) data.stream.gather().sink(self.stream.send) elif is_xarray(data): import xarray as xr z = kwds.get('z') if z is None and isinstance(data, xr.Dataset): z = list(data.data_vars)[0] if gridded and isinstance(data, xr.Dataset) and not isinstance(z, list): data = data[z] ignore = (groupby or []) + (by or []) dims = [ c for c in data.coords if data[c].shape != () and c not in ignore ] if kind is None and (not (x or y) or all(c in data.coords for c in (x, y))): if len(dims) == 1: kind = 'line' elif len(dims) == 2 or (x and y): kind = 'image' gridded = True else: kind = 'hist' if gridded: gridded_data = True data, x, y, by_new, groupby_new = process_xarray( data, x, y, by, groupby, use_dask, persist, gridded, label, value_label) if kind not in self._stats_types: if by is None: by = by_new if groupby is None: groupby = groupby_new if groupby: groupby = [g for g in groupby if g not in (row, col)] self.data = data else: raise ValueError('Supplied data type %s not understood' % type(data).__name__) # Validate data and arguments if by is None: by = [] if groupby is None: groupby = [] if gridded: if not gridded_data: raise ValueError('%s plot type requires gridded data, ' 'e.g. a NumPy array or xarray Dataset, ' 'found %s type' % (kind, type(self.data).__name__)) not_found = [g for g in groupby if g not in data.coords] data_vars = list(data.data_vars) if isinstance( data, xr.Dataset) else [data.name] indexes = list(data.coords) self.variables = list(data.coords) + data_vars if groupby and not_found: raise ValueError('The supplied groupby dimension(s) %s ' 'could not be found, expected one or ' 'more of: %s' % (not_found, list(data.coords))) else: # Determine valid indexes if isinstance(self.data, pd.DataFrame): if self.data.index.names == [None]: indexes = [self.data.index.name or 'index'] else: indexes = list(self.data.index.names) else: indexes = [ c for c in self.data.reset_index().columns if c not in self.data.columns ] if len(indexes) == 2 and not (x or y or by): if kind == 'heatmap': x, y = indexes elif kind in ('bar', 'barh'): x, by = indexes # Rename non-string columns renamed = { c: str(c) for c in data.columns if not isinstance(c, hv.util.basestring) } if renamed: self.data = self.data.rename(columns=renamed) self.variables = indexes + list(self.data.columns) # Reset groupby dimensions groupby_index = [g for g in groupby if g in indexes] if groupby_index: self.data = self.data.reset_index(groupby_index) not_found = [ g for g in groupby if g not in list(self.data.columns) + indexes ] if groupby and not_found: raise ValueError('The supplied groupby dimension(s) %s ' 'could not be found, expected one or ' 'more of: %s' % (not_found, list(self.data.columns))) # Set data-level options self.x = x self.y = y self.kind = kind or 'line' self.gridded = gridded self.use_dask = use_dask self.indexes = indexes if isinstance(by, (np.ndarray, pd.Series)): self.data['by'] = by self.by = ['by'] elif not by: self.by = [] else: self.by = by if isinstance(by, list) else [by] self.groupby = groupby self.streaming = streaming self.hover_cols = hover_cols
def get_stream(data): return Buffer(data, length=buffer_length, index=index)
def produce_correlation_graphs(doc, diode_t_dict, diode_dict): """ Produce correlation graphs and push them onto the web page document. Parameters ---------- doc: bokeh.document (I think) Bokeh document to be displayed on webpage diode_t_dict: dictionary diciontary with deques containing timestamps of the diode readings diode_dict: dictionary dictionary with deques containing diode readins """ # Initialize formatting variables buffer_length = 40000 width = 500 # Initialize Streams b_dcc_dco = Buffer(pd.DataFrame({ 'x_diode': [], 'y_diode': [] }), length=buffer_length) b_t4d_dd = Buffer(pd.DataFrame({ 'x_diode': [], 'y_diode': [] }), length=buffer_length) b_do_di = Buffer(pd.DataFrame({ 'x_diode': [], 'y_diode': [] }), length=buffer_length) b_t4d_dco = Buffer(pd.DataFrame({ 'x_diode': [], 'y_diode': [] }), length=buffer_length) # Initialize dynamic maps hvPoint_dcc_dco = hv.DynamicMap( partial(hv.Scatter, kdims=['x_diode', 'y_diode'], group='DCC vs DCO'), streams=[b_dcc_dco]).options(width=width).redim.label(x_diode='DCC', y_diode='DCO') hvPoint_t4d_dd = hv.DynamicMap( partial(hv.Scatter, kdims=['x_diode', 'y_diode'], group='T4D vs DD'), streams=[b_t4d_dd]).options(width=width).redim.label(x_diode='T4D', y_diode='DD') hvPoint_do_di = hv.DynamicMap( partial(hv.Scatter, kdims=['x_diode', 'y_diode'], group='DO vs DI'), streams=[b_do_di]).options(width=width).redim.label(x_diode='DO', y_diode='DI') hvPoint_t4d_dco = hv.DynamicMap( partial(hv.Scatter, kdims=['x_diode', 'y_diode'], group='T4D vs DCO'), streams=[b_t4d_dco]).options(width=width).redim.label(x_diode='T4D', y_diode='DCO') plots_col = (hvPoint_dcc_dco + hvPoint_t4d_dco + hvPoint_do_di + hvPoint_t4d_dd).cols(2) # Render plot with bokeh hvplot = renderer.get_plot(plots_col, doc) # Initialize callbacks cb_id_dcc_dco = None cb_id_t4d_dd = None cb_id_do_di = None cb_id_t4d_dco = None # Push data into buffers def push_data(x_diode, y_diode, x_diode_t, y_diode_t, buffer): """ Push data from x and y diode into buffer to be graphed. """ x_diode_data = pd.Series(x_diode, index=x_diode_t) y_diode_data = pd.Series(y_diode, index=y_diode_t) zipped = basic_event_builder(x_diode=x_diode_data, y_diode=y_diode_data) buffer.send(zipped) # def play_graph(): """ Provide play and pause functionality to the graph """ nonlocal cb_id_dcc_dco, cb_id_t4d_dd, cb_id_do_di, cb_id_t4d_dco cb_time = 1000 if startButton.label == '► Play': startButton.label = '❚❚ Pause' cb_id_dcc_dco = doc.add_periodic_callback( partial(push_data, x_diode=diode_dict['dcc_d'], y_diode=diode_dict['dco_d'], x_diode_t=diode_t_dict['dcc_t'], y_diode_t=diode_t_dict['dco_t'], buffer=b_dcc_dco), cb_time) cb_id_t4d_dd = doc.add_periodic_callback( partial(push_data, x_diode=diode_dict['t4d_d'], y_diode=diode_dict['dd_d'], x_diode_t=diode_t_dict['t4d_t'], y_diode_t=diode_t_dict['dd_t'], buffer=b_t4d_dd), cb_time) cb_id_do_di = doc.add_periodic_callback( partial(push_data, x_diode=diode_dict['do_d'], y_diode=diode_dict['di_d'], x_diode_t=diode_t_dict['do_t'], y_diode_t=diode_t_dict['di_t'], buffer=b_do_di), cb_time) cb_id_t4d_dco = doc.add_periodic_callback( partial(push_data, x_diode=diode_dict['t4d_d'], y_diode=diode_dict['dco_d'], x_diode_t=diode_t_dict['t4d_t'], y_diode_t=diode_t_dict['dco_t'], buffer=b_t4d_dco), cb_time) else: startButton.label = '► Play' doc.remove_periodic_callback(cb_id_dcc_dco) doc.remove_periodic_callback(cb_id_t4d_dd) doc.remove_periodic_callback(cb_id_do_di) doc.remove_periodic_callback(cb_id_t4d_dco) # Create widgets startButton = Button(label='► Play') startButton.on_click(play_graph) plot = layout([startButton, row([hvplot.state])]) doc.title = "Correlation Graphs" doc.add_root(plot)
def __init__(self, data, kind=None, by=None, width=700, height=300, shared_axes=False, columns=None, grid=False, legend=True, rot=None, title=None, xlim=None, ylim=None, xticks=None, yticks=None, fontsize=None, colormap=None, stacked=False, logx=False, logy=False, loglog=False, hover=True, style_opts={}, plot_opts={}, use_index=False, value_label='value', group_label='Group', colorbar=False, streaming=False, backlog=1000, timeout=1000, persist=False, use_dask=False, datashade=False, **kwds): # Validate DataSource if not isinstance(data, DataSource): raise TypeError('Can only plot intake DataSource types') elif data.container != 'dataframe': raise NotImplementedError('Plotting interface currently only ' 'supports DataSource objects with ' 'dataframe container.') self.data_source = data self.streaming = streaming self.use_dask = use_dask if streaming: self.data = data.read() self.stream = Buffer(self.data, length=backlog) if gen is None: raise ImportError('Streaming support requires tornado.') @gen.coroutine def f(): self.stream.send(data.read()) self.cb = PeriodicCallback(f, timeout) elif (use_dask or persist) and dd is not None: ddf = data.to_dask() self.data = ddf.persist() if persist else ddf else: self.data = data.read() # High-level options self.by = by or [] self.columns = columns self.stacked = stacked self.use_index = use_index self.kwds = kwds self.value_label = value_label self.group_label = group_label self.datashade = datashade # Process style options if 'cmap' in kwds and colormap: raise TypeError("Only specify one of `cmap` and `colormap`.") elif 'cmap' in kwds: cmap = kwds.pop('cmap') else: cmap = colormap self._style_opts = dict(**style_opts) if cmap: self._style_opts['cmap'] = cmap if 'size' in kwds: self._style_opts['size'] = kwds.pop('size') if 'alpha' in kwds: self._style_opts['alpha'] = kwds.pop('alpha') # Process plot options plot_options = dict(plot_opts) plot_options['logx'] = logx or loglog plot_options['logy'] = logy or loglog plot_options['show_grid'] = grid plot_options['shared_axes'] = shared_axes plot_options['show_legend'] = legend if xticks: plot_options['xticks'] = xticks if yticks: plot_options['yticks'] = yticks if width: plot_options['width'] = width if height: plot_options['height'] = height if fontsize: plot_options['fontsize'] = fontsize if colorbar: plot_options['colorbar'] = colorbar if self.kwds.get('vert', False): plot_options['invert_axes'] = True if rot: if (kind == 'barh' or kwds.get('orientation') == 'horizontal' or kwds.get('vert')): axis = 'yrotation' else: axis = 'xrotation' plot_options[axis] = rot if hover: plot_options['tools'] = ['hover'] self._hover = hover self._plot_opts = plot_options self._relabel = {'label': title} self._dim_ranges = { 'x': xlim or (None, None), 'y': ylim or (None, None) } self._norm_opts = {'framewise': True}
class HoloViewsConverter(object): def __init__(self, data, kind=None, by=None, width=700, height=300, shared_axes=False, columns=None, grid=False, legend=True, rot=None, title=None, xlim=None, ylim=None, xticks=None, yticks=None, fontsize=None, colormap=None, stacked=False, logx=False, logy=False, loglog=False, hover=True, style_opts={}, plot_opts={}, use_index=False, value_label='value', group_label='Group', colorbar=False, streaming=False, backlog=1000, timeout=1000, persist=False, use_dask=False, datashade=False, **kwds): # Validate DataSource if not isinstance(data, DataSource): raise TypeError('Can only plot intake DataSource types') elif data.container != 'dataframe': raise NotImplementedError('Plotting interface currently only ' 'supports DataSource objects with ' 'dataframe container.') self.data_source = data self.streaming = streaming self.use_dask = use_dask if streaming: self.data = data.read() self.stream = Buffer(self.data, length=backlog) if gen is None: raise ImportError('Streaming support requires tornado.') @gen.coroutine def f(): self.stream.send(data.read()) self.cb = PeriodicCallback(f, timeout) elif (use_dask or persist) and dd is not None: ddf = data.to_dask() self.data = ddf.persist() if persist else ddf else: self.data = data.read() # High-level options self.by = by or [] self.columns = columns self.stacked = stacked self.use_index = use_index self.kwds = kwds self.value_label = value_label self.group_label = group_label self.datashade = datashade # Process style options if 'cmap' in kwds and colormap: raise TypeError("Only specify one of `cmap` and `colormap`.") elif 'cmap' in kwds: cmap = kwds.pop('cmap') else: cmap = colormap self._style_opts = dict(**style_opts) if cmap: self._style_opts['cmap'] = cmap if 'size' in kwds: self._style_opts['size'] = kwds.pop('size') if 'alpha' in kwds: self._style_opts['alpha'] = kwds.pop('alpha') # Process plot options plot_options = dict(plot_opts) plot_options['logx'] = logx or loglog plot_options['logy'] = logy or loglog plot_options['show_grid'] = grid plot_options['shared_axes'] = shared_axes plot_options['show_legend'] = legend if xticks: plot_options['xticks'] = xticks if yticks: plot_options['yticks'] = yticks if width: plot_options['width'] = width if height: plot_options['height'] = height if fontsize: plot_options['fontsize'] = fontsize if colorbar: plot_options['colorbar'] = colorbar if self.kwds.get('vert', False): plot_options['invert_axes'] = True if rot: if (kind == 'barh' or kwds.get('orientation') == 'horizontal' or kwds.get('vert')): axis = 'yrotation' else: axis = 'xrotation' plot_options[axis] = rot if hover: plot_options['tools'] = ['hover'] self._hover = hover self._plot_opts = plot_options self._relabel = {'label': title} self._dim_ranges = { 'x': xlim or (None, None), 'y': ylim or (None, None) } self._norm_opts = {'framewise': True} @streaming def table(self, x=None, y=None, data=None): allowed = ['width', 'height'] opts = {k: v for k, v in self._plot_opts.items() if k in allowed} data = self.data if data is None else data return Table(data, self.columns, []).opts(plot=opts) def __call__(self, kind, x, y): return getattr(self, kind)(x, y) def single_chart(self, element, x, y, data=None): opts = { element.__name__: dict(plot=self._plot_opts, norm=self._norm_opts, style=self._style_opts) } ranges = {y: self._dim_ranges['y']} if x: ranges[x] = self._dim_ranges['x'] data = self.data if data is None else data ys = [y] if 'c' in self.kwds and self.kwds['c'] in data.columns: ys += [self.kwds['c']] if self.by: chart = Dataset(data, [self.by, x], ys).to(element, x, ys, self.by).overlay() else: chart = element(data, x, ys) return chart.redim.range(**ranges).relabel(**self._relabel).opts(opts) def chart(self, element, x, y, data=None): "Helper method for simple x vs. y charts" if x and y: return self.single_chart(element, x, y, data) # Note: Loading dask dataframe into memory due to rename bug data = (self.data if data is None else data) if self.use_dask: data = data.compute() opts = dict(plot=dict(self._plot_opts, labelled=['x']), norm=self._norm_opts, style=self._style_opts) if self.use_index or x: if self.use_index is not None and isinstance(self.use_index, bool): x = x or data.index.name or 'index' else: x = self.use_index columns = self.columns or data.columns charts = {} for c in columns: chart = element(data, x, c).redim(**{c: self.value_label}) ranges = {x: self._dim_ranges['x'], c: self._dim_ranges['y']} charts[c] = (chart.relabel(**self._relabel).redim.range( **ranges).opts(**opts)) return NdOverlay(charts) else: raise ValueError('Could not determine what to plot. Expected ' 'either x and y parameters to be declared ' 'or use_index to be enabled.') @datashading @streaming def line(self, x, y, data=None): return self.chart(Curve, x, y, data) @datashading @streaming def scatter(self, x, y, data=None): scatter = self.chart(Scatter, x, y, data) if 'c' in self.kwds: color_opts = { 'Scatter': { 'colorbar': self.kwds.get('colorbar', False), 'color_index': self.kwds['c'] } } return scatter.opts(plot=color_opts) return scatter @streaming def area(self, x, y, data=None): areas = self.chart(Area, x, y, data) if self.stacked: areas = areas.map(Area.stack, NdOverlay) return areas def _category_plot(self, element, data=None): """ Helper method to generate element from indexed dataframe. """ data = self.data if data is None else data if isinstance(self.use_index, bool): index = data.index.name or 'index' else: index = self.use_index kdims = [index, self.group_label] id_vars = [index] invert = not self.kwds.get('vert', True) opts = { 'plot': dict(self._plot_opts, labelled=[]), 'norm': self._norm_opts } ranges = {self.value_label: self._dim_ranges['y']} if self.columns: data = data[self.columns + id_vars] if dd and isinstance(data, dd.DataFrame): data = data.compute() df = pd.melt(data, id_vars=id_vars, var_name=self.group_label, value_name=self.value_label) return (element(df, kdims, self.value_label).redim.range( **ranges).relabel(**self._relabel).opts(**opts)) def _stats_plot(self, element, y, data=None): """ Helper method to generate element from indexed dataframe. """ data = self.data if data is None else data opts = { 'plot': dict(self._plot_opts, labelled=[]), 'norm': self._norm_opts, 'style': self._style_opts } if y: ranges = {y: self._dim_ranges['y']} kdims = [self.by] if self.by else [] return (element( data, kdims, y).redim.range(**ranges).relabel(**self._relabel).opts(**opts)) kdims = [self.group_label] ranges = {self.value_label: self._dim_ranges['y']} if self.columns: data = data[self.columns] if dd and isinstance(data, dd.DataFrame): data = data.compute() df = pd.melt(data, var_name=self.group_label, value_name=self.value_label) return (element(df, kdims, self.value_label).redim.range( **ranges).relabel(**self._relabel).opts(**opts)) @streaming def bar(self, x, y, data=None): if x and y: return self.single_chart(Bars, x, y, data) elif self.use_index: stack_index = 1 if self.stacked else None opts = {'Bars': {'stack_index': stack_index}} return self._category_plot(Bars, data).opts(plot=opts) else: raise ValueError('Could not determine what to plot. Expected ' 'either x and y parameters to be declared ' 'or use_index to be enabled.') @streaming def barh(self, x, y, data=None): return self.bar(x, y, data).opts(plot={'Bars': dict(invert_axes=True)}) @streaming def box(self, x, y, data=None): return self._stats_plot(BoxWhisker, y, data) @streaming def violin(self, x, y, data=None): try: from holoviews.element import Violin except ImportError: raise ImportError('Violin plot requires HoloViews version >=1.10') return self._stats_plot(Violin, y, data) @streaming def hist(self, x, y, data=None): plot_opts = dict(self._plot_opts) invert = self.kwds.get('orientation', False) == 'horizontal' opts = dict(plot=dict(plot_opts, labelled=['x'], invert_axes=invert), style=self._style_opts, norm=self._norm_opts) hist_opts = { 'num_bins': self.kwds.get('bins', 10), 'bin_range': self.kwds.get('bin_range', None), 'normed': self.kwds.get('normed', False) } data = self.data if data is None else data ds = Dataset(data) if y and self.by: return histogram(ds.to(Dataset, [], y, self.by), **hist_opts).\ overlay().opts({'Histogram': opts}) elif y: return histogram(ds, dimension=y, **hist_opts).\ opts({'Histogram': opts}) hists = {} columns = self.columns or data.columns for col in columns: hist = histogram(ds, dimension=col, **hist_opts) ranges = {hist.vdims[0].name: self._dim_ranges['y']} hists[col] = (hist.redim.range(**ranges).relabel( **self._relabel).opts(**opts)) return NdOverlay(hists) @streaming def kde(self, x, y, data=None): data = self.data if data is None else data plot_opts = dict(self._plot_opts) invert = self.kwds.get('orientation', False) == 'horizontal' opts = dict(plot=dict(plot_opts, invert_axes=invert), style=self._style_opts, norm=self._norm_opts) opts = { 'Distribution': opts, 'Area': opts, 'NdOverlay': { 'plot': dict(plot_opts, legend_limit=0) } } if y and self.by: ds = Dataset(data) return ds.to(Distribution, y, [], self.by).overlay().opts(opts) elif y: return Distribution(data, y, []).opts(opts) if self.columns: data = data[self.columns] df = pd.melt(data, var_name=self.group_label, value_name=self.value_label) ds = Dataset(df) if len(df): overlay = ds.to(Distribution, self.value_label).overlay() else: vdim = self.value_label + ' Density' overlay = NdOverlay({0: Area([], self.value_label, vdim)}, [self.group_label]) return overlay.relabel(**self._relabel).opts(opts) @streaming def heatmap(self, x, y, data=None): data = data or self.data if not x: x = data.columns[0] if not y: y = data.columns[1] z = self.kwds.get('C', data.columns[2]) opts = dict(plot=self._plot_opts, norm=self._norm_opts, style=self._style_opts) hmap = HeatMap(data, [x, y], z).opts(**opts) if 'reduce_function' in self.kwds: return hmap.aggregate(function=self.kwds['reduce_function']) return hmap