def test_rangexy_framewise_not_reset_if_triggering(self): stream = RangeXY(x_range=(0, 2), y_range=(0, 1)) curve = DynamicMap(lambda z, x_range, y_range: Curve([1, 2, z]), kdims=['z'], streams=[stream]).redim.range(z=(0, 3)) bokeh_server_renderer.get_plot(curve.opts(framewise=True)) stream.event(x_range=(0, 3)) self.assertEqual(stream.x_range, (0, 3))
def test_launch_server_with_stream(self): obj = Curve([]) stream = RangeXY(source=obj) launched = [] def modify_doc(doc): bokeh_renderer(obj, doc=doc) launched.append(True) server.stop() handler = FunctionHandler(modify_doc) app = Application(handler) server = Server({'/': app}, port=0) server.start() url = "http://localhost:" + str(server.port) + "/" pull_session(session_id='Test', url=url, io_loop=server.io_loop) self.assertTrue(len(launched)==1) cb = bokeh_renderer.last_plot.callbacks[0] self.assertIsInstance(cb, RangeXYCallback) self.assertEqual(cb.streams, [stream]) x_range = bokeh_renderer.last_plot.handles['x_range'] self.assertIn(cb.on_change, x_range._callbacks['start']) self.assertIn(cb.on_change, x_range._callbacks['end']) y_range = bokeh_renderer.last_plot.handles['y_range'] self.assertIn(cb.on_change, y_range._callbacks['start']) self.assertIn(cb.on_change, y_range._callbacks['end'])
def test_rangexy_resolves(self): points = Points([1, 2, 3]) RangeXY(source=points) plot = bokeh_server_renderer.get_plot(points) x_range = plot.handles['x_range'] y_range = plot.handles['y_range'] callback = plot.callbacks[0] x0_range_spec = callback.attributes['x0'] x1_range_spec = callback.attributes['x1'] y0_range_spec = callback.attributes['y0'] y1_range_spec = callback.attributes['y1'] resolved = callback.resolve_attr_spec(x0_range_spec, x_range, model=x_range) self.assertEqual(resolved, {'id': x_range.ref['id'], 'value': 0}) resolved = callback.resolve_attr_spec(x1_range_spec, x_range, model=x_range) self.assertEqual(resolved, {'id': x_range.ref['id'], 'value': 2}) resolved = callback.resolve_attr_spec(y0_range_spec, y_range, model=y_range) self.assertEqual(resolved, {'id': y_range.ref['id'], 'value': 1}) resolved = callback.resolve_attr_spec(y1_range_spec, y_range, model=y_range) self.assertEqual(resolved, {'id': y_range.ref['id'], 'value': 3})
def test_launch_server_with_complex_plot(self): dmap = DynamicMap(lambda x_range, y_range: Curve([]), streams=[RangeXY()]) overlay = dmap * HLine(0) static = Polygons([]) * Path([]) * Curve([]) layout = overlay + static _, server = self._launcher(layout) server.stop()
def test_rangexy_framewise_reset(self): stream = RangeXY(x_range=(0, 2), y_range=(0, 1)) curve = DynamicMap(lambda z, x_range, y_range: Curve([1, 2, z]), kdims=['z'], streams=[stream]).redim.range(z=(0, 3)) plot = bokeh_server_renderer.get_plot(curve.opts(framewise=True)) plot.update((1, )) self.assertEqual(stream.y_range, None)
def test_rangexy_shared_axes(self): "Check that stream callbacks are shared on shared axes" c1 = Curve([1, 2, 3], 'x', 'y') c2 = Curve([1, 2, 3], 'x', 'y') stream1 = RangeXY(source=c1) stream2 = RangeXY(source=c2) layout = c1 + c2 plot = bokeh_server_renderer.get_plot(layout) c1p, c2p = [p.subplots['main'] for p in plot.subplots.values()] c1_cb = c1p.callbacks[0] c2_cb = c2p.callbacks[0] assert set(c1_cb.streams) == {stream1, stream2} assert stream1 in c1_cb.handle_ids stream1_handles = c1_cb.handle_ids[stream1] assert stream1_handles['x_range'] == c1p.handles['x_range'].ref['id'] assert stream1_handles['y_range'] == c1p.handles['y_range'].ref['id'] stream2_handles = c1_cb.handle_ids[stream2] assert stream2_handles['x_range'] == c2p.handles['x_range'].ref['id'] assert stream2_handles['y_range'] == c2p.handles['y_range'].ref['id'] assert c2_cb.streams == []
def test_rangexy_datetime(self): curve = Curve(pd.util.testing.makeTimeDataFrame(), 'index', 'C') stream = RangeXY(source=curve) plot = bokeh_server_renderer.get_plot(curve) callback = plot.callbacks[0] callback.on_msg({ "x0": curve.iloc[0, 0], 'x1': curve.iloc[3, 0], "y0": 0.2, 'y1': 0.8 }) self.assertEqual(stream.x_range[0], curve.iloc[0, 0]) self.assertEqual(stream.x_range[1], curve.iloc[3, 0]) self.assertEqual(stream.y_range, (0.2, 0.8))
def test_set_up_linked_change_stream_on_server_doc(self): obj = Curve([]) stream = RangeXY(source=obj) server_doc = bokeh_renderer.server_doc(obj) self.assertEqual(len(bokeh_renderer.last_plot.callbacks), 1) cb = bokeh_renderer.last_plot.callbacks[0] self.assertIsInstance(cb, RangeXYCallback) self.assertEqual(cb.streams, [stream]) x_range = bokeh_renderer.last_plot.handles['x_range'] self.assertIn(cb.on_change, x_range._callbacks['start']) self.assertIn(cb.on_change, x_range._callbacks['end']) y_range = bokeh_renderer.last_plot.handles['y_range'] self.assertIn(cb.on_change, y_range._callbacks['start']) self.assertIn(cb.on_change, y_range._callbacks['end'])
def test_launch_server_with_stream(self): obj = Curve([]) stream = RangeXY(source=obj) _, server = self._launcher(obj) cb = bokeh_renderer.last_plot.callbacks[0] self.assertIsInstance(cb, RangeXYCallback) self.assertEqual(cb.streams, [stream]) x_range = bokeh_renderer.last_plot.handles['x_range'] self.assertIn(cb.on_change, x_range._callbacks['start']) self.assertIn(cb.on_change, x_range._callbacks['end']) y_range = bokeh_renderer.last_plot.handles['y_range'] self.assertIn(cb.on_change, y_range._callbacks['start']) self.assertIn(cb.on_change, y_range._callbacks['end']) server.stop()
def test_launch_server_with_stream(self): el = Curve([]) stream = RangeXY(source=el) obj, _ = bokeh_renderer._validate(el, None) server, _ = self._launcher(obj, port=6002) [(plot, _)] = obj._plots.values() cb = plot.callbacks[0] self.assertIsInstance(cb, RangeXYCallback) self.assertEqual(cb.streams, [stream]) x_range = bokeh_renderer.last_plot.handles['x_range'] self.assertIn(cb.on_change, x_range._callbacks['start']) self.assertIn(cb.on_change, x_range._callbacks['end']) y_range = bokeh_renderer.last_plot.handles['y_range'] self.assertIn(cb.on_change, y_range._callbacks['start']) self.assertIn(cb.on_change, y_range._callbacks['end']) server.stop()
def test_launch_server_with_complex_plot(self): dmap = DynamicMap(lambda x_range, y_range: Curve([]), streams=[RangeXY()]) overlay = dmap * HLine(0) static = Polygons([]) * Path([]) * Curve([]) layout = overlay + static launched = [] def modify_doc(doc): bokeh_renderer(layout, doc=doc) launched.append(True) server.stop() handler = FunctionHandler(modify_doc) app = Application(handler) server = Server({'/': app}, port=0) server.start() url = "http://localhost:" + str(server.port) + "/" pull_session(session_id='Test', url=url, io_loop=server.io_loop) self.assertTrue(len(launched)==1)
def __call__(self, dset, **params): self.p = ParamOverrides(self, params) if self.p.vdim is None: vdim = dset.vdims[0].name else: vdim = self.p.vdim ra_range = (ra0, ra1) = dset.range("ra") if self.p.ra_sampling: xsampling = (ra1 - ra0) / self.p.ra_sampling else: xsampling = None dec_range = (dec0, dec1) = dset.range("dec") if self.p.dec_sampling: ysampling = (dec1 - dec0) / self.p.dec_sampling else: ysampling = None if self.p.aggregator == "mean": aggregator = ds.mean(vdim) elif self.p.aggregator == "std": aggregator = ds.std(vdim) elif self.p.aggregator == "count": aggregator = ds.count() sky_range = RangeXY() if self.p.range_stream: def redim(dset, x_range, y_range): ranges = {} if x_range and all(isfinite(v) for v in x_range): ranges["ra"] = x_range if y_range and all(isfinite(v) for v in x_range): ranges["dec"] = y_range return dset.redim.range(**ranges) if ranges else dset dset = dset.apply(redim, streams=[self.p.range_stream]) link_streams(self.p.range_stream, sky_range) streams = [sky_range, PlotSize()] pts = dset.apply(skypoints, streams=[self.p.filter_stream]) reset = PlotReset(source=pts) reset.add_subscriber(partial(reset_stream, None, [self.p.range_stream])) rasterize_inst = rasterize.instance(aggregator=aggregator, streams=streams, x_sampling=xsampling, y_sampling=ysampling) raster_pts = apply_when( pts, operation=rasterize_inst, predicate=lambda pts: len(pts) > self.p.max_points) return raster_pts.opts( opts.Image( bgcolor="black", colorbar=True, cmap=self.p.cmap, min_height=100, responsive=True, tools=["hover"], symmetric=True, ), opts.Points( color=vdim, cmap=self.p.cmap, framewise=True, size=self.p.decimate_size, tools=["hover"], symmetric=True, ), opts.Overlay(hooks=[ partial(reset_hook, x_range=ra_range, y_range=dec_range) ]), )
def holoview_plot(self, ): """ """ import datashader as ds from holoviews.operation.datashader import aggregate, shade, datashade, dynspread from holoviews.streams import RangeXY self.ds_points = self.datashade( "Value" if len(self._data.data_dims) > 0 else None) self.ds_points = self.ds_points.opts(plot=dict(width=600, height=600)) # Hover and zoom grid tool. self._hover_grid = hv.util.Dynamic( aggregate(self._points, aggregator=ds.mean("Value"), width=15, height=15, streams=[RangeXY(source=self.ds_points)]), operation=hv.QuadMesh).opts(plot=dict(tools=["hover"]), style=dict(alpha=0, hover_alpha=0.2)) # Get the points in tapped rectangle self._posxy = DataShaderSelect(source=self._hover_grid, dataset=self._data.embedding) #self._posxy = hv.streams.Tap(source=self._hover_grid) def _dss_logger(**kwargs): import logging as log log.info("Handling event from datashader select: %s", str(kwargs)) self._posxy.add_subscriber(_dss_logger) # Make layout self.tap_indicators = hv.DynamicMap(self.tap_points, kdims=[], streams=[self._posxy]) self.selected_table = hv.DynamicMap(self.tap_table, streams=[self._posxy]) self.tap_zoom = hv.DynamicMap( self.focus_plot, streams=[self._posxy], kdims=["Counts"]).opts(norm=dict(framewise=True)).redim.values( Counts=self._data.data_dims) def _h(Counts, index, fine_index, **kwargs): #print index, kwargs from holoviews.operation import histogram m = { Counts: "Value", "{}_frequency": "frequency", } if len(index) > 0: d = self._data.embedding.iloc[index] if len(fine_index) > 0: d = d.iloc[fine_index] #print "Trying", Counts label = "{} {} points".format(Counts, len(d)) r = histogram( hv.Points(d), #self.selected_table, dimension=Counts, dynamic=False).redim(**m) else: label = "{} {} points".format(Counts, len(self._data.embedding)) #print "Alt", Counts r = histogram(self._points[Counts], dimension="Value", dynamic=False).redim(Value_frequency="frequency") #print(r) return r.relabel(label) from holoviews import streams self.zoom_selection = streams.Selection1D(source=self.tap_zoom) self.p = hv.DynamicMap( _h, kdims=["Counts"], streams=[ self.zoom_selection.rename(index="fine_index"), self._posxy ]).redim.values(Counts=self._data.data_dims).opts(norm=dict( framewise=True)) self._layout = self.ds_points * self._hover_grid * self.tap_indicators \ + self.selected_table + self.tap_zoom + self.p self._layout = self._layout.cols(2).opts(plot={"shared_axes": False}) return self._layout
selected, kdims=[], vdims=['EventType', 'SUB', 'FEEDER_ID', 'XFMR', 'Phase']) return tab # Map Tiles map_tiles = tiles.opts(style=dict(alpha=1), plot=options) # Create an explorer object and start visualizing data explorer = SagSwellExplorer() #pbk=parambokeh.Widgets(explorer,view_position='right', callback=explorer.event) # Declare points selection mv = hv.DynamicMap(explorer.make_view, streams=[explorer, RangeXY()]) # For Box Select box = streams.BoundsXY(source=mv, bounds=(0, 0, 0, 0)) # For Table to display points selected with box select dt = hv.DynamicMap(explorer.dec_tab, streams=[explorer, RangeXY(), box]) #plot = hv.renderer('bokeh').get_plot(mv*map_tiles+dt, doc=Document()) plot = hv.renderer('bokeh').instance(mode='server').get_plot(mv * map_tiles + dt) #plot = hv.renderer('bokeh').instance(mode='server').get_plot(mv*map_tiles) parambokeh.Widgets(explorer, view_position='right', callback=explorer.event,
imag = min_y + y * pixel_size_y color = mandel(real, imag, iters) image[y, x] = color return image def get_fractal(x_range, y_range): (x0, x1), (y0, y1) = x_range, y_range image = np.zeros((600, 600), dtype=np.uint8) return hv.Image(create_fractal(x0, x1, -y1, -y0, image, 200), bounds=(x0, y0, x1, y1)) # Define stream linked to axis XY-range range_stream = RangeXY(x_range=(-1., 1.), y_range=(-1., 1.)) # Create DynamicMap to compute fractal per zoom range and # adjoin a logarithmic histogram dmap = hv.DynamicMap(get_fractal, label='Manderbrot Explorer', streams=[range_stream]).hist(log=True) # Define styling options options = hv.Store.options('bokeh') options.Image = { 'style': Options(cmap='fire'), 'plot': Options(logz=True, height=600, width=600, xaxis=None, yaxis=None) } options.Histogram = { 'norm': Options(framewise=True),
def create_doc(doc, data_dir): def get_spectrogram(s0=None, s1=None, size=1024, overlap=1. / 8, zfill=1, mode='psd'): s_size = np.dtype(np.complex64).itemsize if s1 is None and s0 is None: ds = None elif s1 is None: ds = None elif s0 is None: ds = np.abs(s1) else: ds = np.abs(s1 - s0) if ds is not None and s0 is not None: flen = getsize(join(data_dir, file)) print("file size: {} bytes".format(flen)) if (ds + s0) * s_size > flen: ds = flen - s0 * s_size samples = np.memmap(join(data_dir, file), dtype='complex64', mode='r', offset=s0 * s_size, shape=(ds, ) if ds else None) if ds is None: ds = len(samples) if ds / size > (res + 0.5) * height: noverlap = -int(float(size) * float(ds) / size / height / res) else: noverlap = size // (1. / overlap) f, t, S = signal.spectrogram(samples, samp_rate, nperseg=size, nfft=int( next_power_of_2(size) * int(zfill)), noverlap=noverlap, return_onesided=False, scaling='density', mode=mode) # f = fftshift(f) S = fftshift(S, axes=(0, )) if mode == 'psd': S = 10 * np.log10(S) return f, t, S, samples def get_spectrogram_img(z_min, z_max, tf_r, zfill, overlap, show_realfreq, freq_unit, x_range, y_range): lock.acquire() show_realfreq = bool(show_realfreq) hv_image = None try: print("y_range:", y_range, type(y_range)) if type(y_range[0]) != float: if np.issubdtype(y_range[0], np.datetime64) and time is not None: y_range = [ (y - np.datetime64(time) ).astype('timedelta64[us]').astype('float') / 1e6 for y in y_range ] #elif np.issubdtype(y0, np.timedelta64): # y0, y1 = [y.astype('timedelta64[s]').astype('float') for y in [y0,y1]] # tranform back to relative frequency if required print(doc.session_context.show_realfreq, x_range) last_freq_unit = doc.session_context.freq_unit x_range = [x * freq_units_names[last_freq_unit] for x in x_range] if doc.session_context.show_realfreq: x_range = [(x - freq) for x in x_range] print(doc.session_context.show_realfreq, "after transform", x_range) (x0, x1), (y0, y1) = x_range, y_range #print("y0 dtype:", y0.dtype) s0, s1 = sorted([ min(max(int(yr * samp_rate), 0), total_samples) for yr in [y0, y1] ]) scale = samp_rate / np.abs(x_range[1] - x_range[0]) size = int(width * scale) # required freq resolution to fulfill zoom level ds = np.abs( s1 - s0) # number of samples covered at the current zoom level if ds / size < height: size = int(np.sqrt(ds * scale * 10**tf_r)) f, t, S, samples = get_spectrogram( s0, s1, size=size, overlap=overlap, mode=mode, zfill=zfill if size < res * width else 1) t += max(min(y0, y1), 0) f_range = (x0 <= f) & (f <= x1) image = S[f_range, :] f = f[f_range] #if ds / size > height: # image = signal.resample(image, height*2, axis=0) print(image.shape) if intp_enabled: ratio = np.array(image.shape, dtype=np.float) / np.array( (height * res, width * res)) if np.min(ratio) < 1: scale = np.max( np.abs(image) ) # normalization factor for image because rescale needs that image = rescale(image / scale, 1. / np.min(ratio), order=1) * scale f = signal.resample(f, image.shape[0]) t = signal.resample(t, image.shape[1]) print("after resampling: ", image.shape) del samples #image = hv.Image(image, bounds=(x0, y0, x1, y1)).redim.range(z=(z_min, z_max)) # TODO get exact values in bounds if show_realtime and time is not None: t = np.datetime64(time) + np.array( t * 1e6).astype('timedelta64[us]') #else: # t = (t*1e6) #.astype('timedelta64[us]') if show_realfreq: f += freq f /= freq_units_names[freq_unit] #image = image.astype('float16') # trying to reduce network bandwidth... print("image dtype:", image.dtype) #hv_image = hv.Image(np.flip(image, axis=1), bounds=(min(f), max(t), max(f), min(t))) \ hv_image = hv.Image(xr.DataArray(image, coords=[f,t], dims=['f','t'], name='z'), ['f','t'], 'z') \ .options( xlabel="Frequency [{}]".format(freq_unit), ylabel="Time " + '[s]' if not show_realtime else '') \ .redim.range(z=(z_min, z_max)) if doc.session_context.show_realfreq != show_realfreq or doc.session_context.freq_unit != freq_unit: hv_image = hv_image \ .redim.range(f=(min(f), max(f))) \ .redim.range(t=(min(t), max(t))) print("redimming axis range") doc.session_context.show_realfreq = show_realfreq doc.session_context.freq_unit = freq_unit except Exception as e: print("Exception in image generation:", e) print(traceback.format_exc()) lock.release() return hv_image def get_param(name, default, t=str): try: args = doc.session_context.request.arguments if t == str: p = str(args.get(name)[0], 'utf-8') else: p = t(args.get(name)[0]) except: p = default return p time = None freq = 0 file = basename(get_param('file', '', str)) skip = get_param('skip', 0, int) keep = get_param('keep', None, int) # low resolution for raspberry width, height = get_param('width', 600, int), get_param('height', 500, int) res = get_param('res', 1.5, float) ds_enabled = get_param('ds', None, str) # datashade option (default: avg) intp_enabled = get_param('intp', 0, int) # interpolation enable flap show_realtime = bool(get_param('rt', 0, int)) # show real time on vertical axis mode = get_param('mode', 'psd', str) t_range = get_param('t', None, str) f_range = get_param('f', None, str) if t_range is not None: try: parts = t_range.split(",") if len(parts) == 2: t_range = list(map(float, parts)) except: pass if f_range is not None: try: parts = f_range.split(",") if len(parts) == 2: f_range = list(map(float, parts)) elif len(parts) == 1: _f = abs(float(parts[0])) f_range = (-_f, _f) except: pass if file.endswith(".meta"): config = ConfigParser() config.read(join(data_dir, file)) file = splitext(file)[0] + ".raw" samp_rate = int(config['main']['samp_rate']) freq = float(config['main']['freq']) time = datetime.fromtimestamp(float(config['main']['time'])) else: samp_rate = get_param('samp_rate', 128000, int) f, t, S, samples = get_spectrogram(s0=skip * samp_rate, s1=keep * samp_rate if keep else None, size=width, mode=mode) total_samples = len(samples) del samples # default is True if show_realtime and time is not None: t = np.datetime64(time) + np.array(t).astype('timedelta64[s]') doc.session_context.show_realfreq = False doc.session_context.freq_unit = freq_units[1000] range_stream = RangeXY(x_range=tuple( x / freq_units_names[doc.session_context.freq_unit] for x in ((min(f_range), max(f_range)) if f_range else (min(f), max(f)))), y_range=(max(t_range), min(t_range)) if t_range else (max(t), min(t))) # transient=True z_range = (np.min(S), np.max(S)) z_init = np.percentile(S, (50, 100)) dmap = hv.DynamicMap( get_spectrogram_img, streams=[range_stream], kdims=[ hv.Dimension('z_min', range=z_range, default=z_init[0]), hv.Dimension('z_max', range=z_range, default=z_init[1]), hv.Dimension('tf_r', label='Time-Frequency pixel ratio', range=(-10., 10.), default=0.), hv.Dimension('zfill', label='Zero-filling factor', range=(1, 10), default=2), hv.Dimension('overlap', label='Overlap factor', range=(-1., 1.), default=1. / 8), #hv.Dimension('show_realtime', label='Show real time on vertical axis', range=(0,1), default=0), hv.Dimension('show_realfreq', label='Show real frequency', range=(0, 1), default=int(doc.session_context.show_realfreq)), hv.Dimension('freq_unit', label='Frequency unit', values=list( map(lambda x: freq_units[x], sorted(freq_units.keys()))), default=doc.session_context.freq_unit), #hv.Dimension('mode', label='Spectrogram mode', values=['psd', 'angle', 'phase', 'magnitude'], default='psd') ]).options( framewise=True, # ??? ) #.redim.range(z=z_init) #dmap = dmap.opts(opts.Image(height=height, width=width)) if ds_enabled != None: print("datashade enabled: yes") if ds_enabled == "" or ds_enabled == "mean": ds_enabled = dsr.mean elif ds_enabled == "max": ds_enabled = dsr.max else: print( "warning: invalid option for datashade. using default value: mean" ) ds_enabled = dsr.mean dmap = regrid(dmap, aggregator=ds_enabled, interpolation='linear', upsample=True, height=height * 2, width=width * 2) # aggregation=dsr.max #dmap = dmap.hist(num_bins=150, normed=False) dmap = dmap.opts( opts.Image( cmap='viridis', framewise=True, colorbar=True, height=height, width=width, tools=['hover'], title='{}, {} {} sps'.format( time.strftime('%Y-%m-%d %H:%M:%S') if time else 'Time unknown', format_freq(freq), samp_rate)), opts.Histogram(framewise=False, width=150)) #plot = renderer.get_plot(hist, doc).state #widget = renderer.get_widget(hist, None, position='right').state #hvobj = layout([plot, widget]) #plot = layout([renderer.get_plot(hist, doc).state]) #doc.add_root(plot) doc = renderer.server_doc(dmap, doc=doc) doc.title = 'Waterfall Viewer'
yaxis=None, bgcolor='black', show_grid=False) opts2 = dict(width=1000, height=600, x_sampling=1, y_sampling=1, dynamic=False) class OSMExplorer(hv.streams.Stream): alpha = param.Magnitude(default=0.75, doc="Map opacity") colormap = param.ObjectSelector(default=cm_n["fire"], objects=cm_n.values()) def make_view(self, x_range, y_range, **kwargs): tiles = map_tiles.options(alpha=self.alpha, **opts1) points = hv.Points(df, ['x', 'y']) return tiles * datashade(points, cmap=self.colormap, x_range=x_range, y_range=y_range, **opts2) explorer = OSMExplorer(name="Open Street Map GPS") dmap = hv.DynamicMap(explorer.make_view, streams=[explorer, RangeXY()]) plot = hv.renderer('bokeh').instance(mode='server').get_plot(dmap) parambokeh.Widgets(explorer, view_position='right', callback=explorer.event, plots=[plot.state], mode='server')
output = parambokeh.view.Plot() def make_view(self, x_range, y_range, alpha, colormap, plot, passengers, **kwargs): map_tiles = tiles(style=dict(alpha=alpha), plot=tile_options) points = hv.Points(df, kdims=[plot + '_x', plot + '_y'], vdims=['passenger_count']) if passengers != passenger_counts: points = points.select(passenger_count=passengers) taxi_trips = datashade(points, x_sampling=1, y_sampling=1, cmap=colormap, dynamic=False, x_range=x_range, y_range=y_range) return map_tiles * taxi_trips selector = NYCTaxiExplorer(name="NYC Taxi Trips") selector.output = hv.DynamicMap(selector.make_view, streams=[selector, RangeXY(), PlotSize()]) doc = parambokeh.Widgets(selector, view_position='right', callback=selector.event, mode='server')
def test_interactive_streams(self): ys = np.arange(10) scatter1 = hv.Scatter(ys) scatter2 = hv.Scatter(ys) scatter3 = hv.Scatter(ys) # Single stream on the first scatter rangexy1 = RangeXY(source=scatter1) # Multiple streams of the same type on second scatter boundsxy2a = BoundsXY(source=scatter2) boundsxy2b = BoundsXY(source=scatter2) # Multiple streams of different types on third scatter rangexy3 = RangeXY(source=scatter3) boundsxy3 = BoundsXY(source=scatter3) selection1d3 = Selection1D(source=scatter3) # Build layout and layout Pane layout = scatter1 + scatter2 + scatter3 layout_pane = pn.pane.HoloViews(layout, backend='plotly') # Get plotly pane reference doc = Document() comm = Comm() layout_pane.get_root(doc, comm) _, plotly_pane = next(iter(layout_pane._plots.values())) # Simulate zoom and check that RangeXY streams updated accordingly plotly_pane.viewport = { 'xaxis.range': [1, 3], 'yaxis.range': [2, 4], 'xaxis2.range': [3, 5], 'yaxis2.range': [4, 6], 'xaxis3.range': [5, 7], 'yaxis3.range': [6, 8], } self.assertEqual(rangexy1.x_range, (1, 3)) self.assertEqual(rangexy1.y_range, (2, 4)) self.assertEqual(rangexy3.x_range, (5, 7)) self.assertEqual(rangexy3.y_range, (6, 8)) plotly_pane.viewport = None self.assertIsNone(rangexy1.x_range) self.assertIsNone(rangexy1.y_range) self.assertIsNone(rangexy3.x_range) self.assertIsNone(rangexy3.y_range) # Simulate box selection and check that BoundsXY and Selection1D streams # update accordingly # Box select on second subplot plotly_pane.selected_data = { 'points': [], 'range': { 'x2': [10, 20], 'y2': [11, 22] } } self.assertEqual(boundsxy2a.bounds, (10, 11, 20, 22)) self.assertEqual(boundsxy2b.bounds, (10, 11, 20, 22)) # Box selecrt on third subplot plotly_pane.selected_data = { 'points': [ {'curveNumber': 2, 'pointNumber': 0}, {'curveNumber': 2, 'pointNumber': 3}, {'curveNumber': 2, 'pointNumber': 7}, ], 'range': { 'x3': [0, 5], 'y3': [1, 6] } } self.assertEqual(boundsxy3.bounds, (0, 1, 5, 6)) self.assertEqual(selection1d3.index, [0, 3, 7]) # bounds streams on scatter 2 are None self.assertIsNone(boundsxy2a.bounds) self.assertIsNone(boundsxy2b.bounds) # Clear selection plotly_pane.selected_data = None self.assertIsNone(boundsxy3.bounds) self.assertIsNone(boundsxy2a.bounds) self.assertIsNone(boundsxy2b.bounds) self.assertEqual(selection1d3.index, [])
size=4, ) return points * tile # Layout and connect template = pn.template.FastListTemplate(title="Load Forecasting - ERCOT", theme="dark") if "dark" in str(template.theme).lower(): tile = gvts.CartoMidnight else: tile = gvts.CartoLight plot = get_station_map(STATIONLIST, tile=tile) stream = RangeXY(source=plot) dataframe_label = pn.pane.Markdown() dataframe_widget = pn.widgets.DataFrame() @param.depends( x=stream.param.x_range, y=stream.param.y_range, top=settings.param.top_stations, watch=True ) def update_bounds(x=None, y=None, top=None): if x and y: x_query = (STATIONLIST["X"] >= x[0]) & (STATIONLIST["X"] <= x[1]) y_query = (STATIONLIST["Y"] >= y[0]) & (STATIONLIST["Y"] <= y[1]) data = STATIONLIST[x_query & y_query] else: data = STATIONLIST if not top:
def __init__(self, store, **param): super().__init__(**param) self.store = store self.overview = create_overview(self.on_overview_selected_tracts_updated, active_tracts=[]) self._clear_metrics_button = pn.widgets.Button(name="Clear", width=30, align="end") self._clear_metrics_button.on_click(self._on_clear_metrics) self._submit_repository = pn.widgets.Button(name="Load Data", width=50, align="end") self._submit_repository.on_click(self._on_load_data_repository) self._submit_comparison = pn.widgets.Button(name="Submit", width=50, align="end") self._submit_comparison.on_click(self._update) self.flag_filter_select = pn.widgets.Select( name="Add Flag Filter", width=160, options=self.store.active_dataset.flags ) self.flag_state_select = pn.widgets.Select(name="Flag State", width=75, options=["True", "False"]) self.flag_submit = pn.widgets.Button(name="Add Flag Filter", width=10, height=30, align="end") self.flag_submit.on_click(self.on_flag_submit_click) self.flag_filter_selected = pn.widgets.Select(name="Active Flag Filters", width=250) self.flag_remove = pn.widgets.Button(name="Remove Flag Filter", width=50, height=30, align="end") self.flag_remove.on_click(self.on_flag_remove_click) self.query_filter_submit = pn.widgets.Button(name="Run Query Filter", width=100, align="end") self.query_filter_submit.on_click(self.on_run_query_filter_click) self.query_filter_clear = pn.widgets.Button(name="Clear", width=50, align="end") self.query_filter_clear.on_click(self.on_query_filter_clear) self.new_column_submit = pn.widgets.Button(name="Define New Column", width=100, align="end") self.new_column_submit.on_click(self.on_define_new_column_click) self.status_message = pn.pane.HTML(sizing_mode="stretch_width", max_height=10) self.adhoc_js = pn.pane.HTML(sizing_mode="stretch_width", max_height=10) self._info = pn.pane.HTML(sizing_mode="stretch_width", max_height=10) self._flags = pn.pane.HTML(sizing_mode="stretch_width", max_height=10) self._metric_panels = [] self._metric_layout = pn.Column() self._switch_view = self._create_switch_view_buttons() self._switch_stack = self._create_switch_datastack_buttons() self._plot_top = pn.Row(sizing_mode="stretch_width", margin=(10, 10, 10, 10)) self._plot_layout = pn.Column(sizing_mode="stretch_width", margin=(10, 10, 10, 10)) self._skyplot_tabs = pn.Tabs(sizing_mode="stretch_both") self.skyplot_layout = pn.Column(sizing_mode="stretch_width", margin=(10, 10, 10, 10)) self._detail_tabs = pn.Tabs(sizing_mode="stretch_both") self.list_layout = pn.Column(sizing_mode="stretch_width") self.detail_plots_layout = pn.Column(sizing_mode="stretch_width") self._coadd_toggles = {} self._filter_streams = {} self._skyplot_range_stream = RangeXY() self._scatter_range_stream = RangeXY() self._visits_selections = {} self._update(None)
def test_rangexy_dynamic_map(self): # Create dynamic map that inputs rangexy, returns scatter on bounds scatter = Scatter([[0, 1], [0, 1]], kdims=["x"], vdims=["y"]) rangexy = RangeXY(source=scatter) def dmap_fn(x_range, y_range): x_range = (0, 1) if x_range is None else x_range y_range = (0, 1) if y_range is None else y_range return Scatter( [[x_range[0], y_range[0]], [x_range[1], y_range[1]]], kdims=["x1"], vdims=["y1"]) dmap = DynamicMap(dmap_fn, streams=[rangexy]) # Convert to Dash components = to_dash(self.app, [scatter, dmap], reset_button=True) # Check returned components self.assertIsInstance(components, DashComponents) self.assertEqual(len(components.graphs), 2) self.assertEqual(len(components.kdims), 0) self.assertIsInstance(components.store, Store) self.assertEqual(len(components.resets), 1) # Get arguments passed to @app.callback decorator decorator_args = list(self.app.callback.call_args_list[0])[0] outputs, inputs, states = decorator_args # Check outputs expected_outputs = [(g.id, "figure") for g in components.graphs] + \ [(components.store.id, "data")] self.assertEqual([(output.component_id, output.component_property) for output in outputs], expected_outputs) # Check inputs expected_inputs = [(g.id, prop) for g in components.graphs for prop in ["selectedData", "relayoutData"] ] + [(components.resets[0].id, "n_clicks")] self.assertEqual( [(ip.component_id, ip.component_property) for ip in inputs], expected_inputs, ) # Check State expected_state = [(components.store.id, "data")] self.assertEqual( [(state.component_id, state.component_property) for state in states], expected_state, ) # Get callback function callback_fn = self.app.callback.return_value.call_args[0][0] # mimic initial callback invocation store_value = encode_store_data( {"streams": { id(rangexy): rangexy.contents }}) with patch.object( CallbackContext, "triggered", [{ "prop_id": components.graphs[0].id + ".relayoutData" }]): [fig1, fig2, new_store] = callback_fn({}, { "xaxis.range[0]": 1, "xaxis.range[1]": 3, "yaxis.range[0]": 2, "yaxis.range[1]": 4 }, {}, {}, None, store_value) # First figure is the scatter trace self.assertEqual(fig1["data"][0]["type"], "scatter") # Second figure holds the bounds element self.assertEqual(len(fig2["data"]), 1) self.assertEqual(list(fig2["data"][0]["x"]), [1, 3]) self.assertEqual(list(fig2["data"][0]["y"]), [2, 4]) # Check updated store self.assertEqual( decode_store_data(new_store), { "streams": { id(rangexy): { 'x_range': (1, 3), 'y_range': (2, 4) } }, "kdims": {} })
location = param.ObjectSelector(default='dropoff', objects=['dropoff', 'pickup']) def make_view(self, x_range, y_range, **kwargs): map_tiles = tiles(style=dict(alpha=self.alpha), plot=tile_options) points = hv.Points(df, kdims=[self.location + '_x', self.location + '_y'], vdims=['dropoff_hour']) if self.hour != (0, 24): points = points.select(dropoff_hour=self.hour) taxi_trips = datashade(points, x_sampling=1, y_sampling=1, cmap=self.colormap, dynamic=False, x_range=x_range, y_range=y_range, width=1000, height=600) return map_tiles * taxi_trips selector = NYCTaxiExplorer(name="NYC Taxi Trips") dmap = hv.DynamicMap(selector.make_view, streams=[selector, RangeXY()]) plot = hv.renderer('bokeh').instance(mode='server').get_plot(dmap) parambokeh.Widgets(selector, view_position='right', callback=selector.event, mode='server', plots=[plot.state])
class skyplot(ParameterizedFunction): """Skyplot of RA/dec switching between rasterized and raw data view. Colormapped by a third dimension. """ aggregator = param.ObjectSelector( default="mean", objects=["mean", "std", "count"], doc=""" Aggregator for datashading.""", ) cmap = param.String( default="coolwarm", doc=""" Colormap to use.""", ) decimate_size = param.Number( default=5, doc=""" Size of (invisible) decimated points.""", ) max_points = param.Integer( default=10000, doc=""" Maximum number of points to display before switching to rasterize.""", ) vdim = param.String( default=None, doc=""" Dimension to use for colormap.""", ) ra_sampling = param.Integer( default=None, doc=""" How densely to sample the rasterized plot along the x-axis.""", ) dec_sampling = param.Integer( default=None, doc=""" How densely to sample the rasterized plot along the y-axis.""", ) filter_stream = param.ClassSelector( default=FilterStream(), class_=FilterStream, doc=""" Filter stream to update plot with currently selected filters.""", ) range_stream = param.ClassSelector( default=RangeXY(), class_=RangeXY, doc=""" Range stream to share between plots to link and persist plot ranges.""", ) flags = param.List(default=[], doc="Flags to select.") bad_flags = param.List(default=[], doc="Flags to ignore") def __call__(self, dset, **params): self.p = ParamOverrides(self, params) if self.p.vdim is None: vdim = dset.vdims[0].name else: vdim = self.p.vdim ra_range = (ra0, ra1) = dset.range("ra") if self.p.ra_sampling: xsampling = (ra1 - ra0) / self.p.ra_sampling else: xsampling = None dec_range = (dec0, dec1) = dset.range("dec") if self.p.dec_sampling: ysampling = (dec1 - dec0) / self.p.dec_sampling else: ysampling = None if self.p.aggregator == "mean": aggregator = ds.mean(vdim) elif self.p.aggregator == "std": aggregator = ds.std(vdim) elif self.p.aggregator == "count": aggregator = ds.count() sky_range = RangeXY() if self.p.range_stream: def redim(dset, x_range, y_range): ranges = {} if x_range and all(isfinite(v) for v in x_range): ranges["ra"] = x_range if y_range and all(isfinite(v) for v in x_range): ranges["dec"] = y_range return dset.redim.range(**ranges) if ranges else dset dset = dset.apply(redim, streams=[self.p.range_stream]) link_streams(self.p.range_stream, sky_range) streams = [sky_range, PlotSize()] pts = dset.apply(skypoints, streams=[self.p.filter_stream]) reset = PlotReset(source=pts) reset.add_subscriber(partial(reset_stream, None, [self.p.range_stream])) rasterize_inst = rasterize.instance(aggregator=aggregator, streams=streams, x_sampling=xsampling, y_sampling=ysampling) raster_pts = apply_when( pts, operation=rasterize_inst, predicate=lambda pts: len(pts) > self.p.max_points) return raster_pts.opts( opts.Image( bgcolor="black", colorbar=True, cmap=self.p.cmap, min_height=100, responsive=True, tools=["hover"], symmetric=True, ), opts.Points( color=vdim, cmap=self.p.cmap, framewise=True, size=self.p.decimate_size, tools=["hover"], symmetric=True, ), opts.Overlay(hooks=[ partial(reset_hook, x_range=ra_range, y_range=dec_range) ]), )
def __call__(self, dset, **params): self.p = ParamOverrides(self, params) if self.p.xdim not in dset.dimensions(): raise ValueError("{} not in Dataset.".format(self.p.xdim)) if self.p.ydim not in dset.dimensions(): raise ValueError("{} not in Dataset.".format(self.p.ydim)) if ("ra" not in dset.dimensions()) or ("dec" not in dset.dimensions()): raise ValueError("ra and/or dec not in Dataset.") # Compute sampling ra_range = (ra0, ra1) = dset.range("ra") if self.p.ra_sampling: ra_sampling = (ra1 - ra0) / self.p.x_sampling else: ra_sampling = None dec_range = (dec0, dec1) = dset.range("dec") if self.p.dec_sampling: dec_sampling = (dec1 - dec0) / self.p.y_sampling else: dec_sampling = None x_range = (x0, x1) = dset.range(self.p.xdim) if self.p.x_sampling: x_sampling = (x1 - x0) / self.p.x_sampling else: x_sampling = None y_range = (y0, y1) = dset.range(self.p.ydim) if self.p.y_sampling: y_sampling = (y1 - y0) / self.p.y_sampling else: y_sampling = None # Set up scatter plot scatter_range = RangeXY() if self.p.scatter_range_stream: def redim_scatter(dset, x_range, y_range): ranges = {} if x_range and all(isfinite(v) for v in x_range): ranges[self.p.xdim] = x_range if y_range and all(isfinite(v) for v in x_range): ranges[self.p.ydim] = y_range return dset.redim.range(**ranges) if ranges else dset dset_scatter = dset.apply(redim_scatter, streams=[self.p.scatter_range_stream]) link_streams(self.p.scatter_range_stream, scatter_range) else: dset_scatter = dset scatter_pts = dset_scatter.apply(filterpoints, streams=[self.p.filter_stream], xdim=self.p.xdim, ydim=self.p.ydim) scatter_streams = [scatter_range, PlotSize()] scatter_rasterize = rasterize.instance(streams=scatter_streams, x_sampling=x_sampling, y_sampling=y_sampling) cmap = (process_cmap(self.p.scatter_cmap)[:250] if self.p.scatter_cmap == "fire" else self.p.scatter_cmap) scatter_rasterized = apply_when( scatter_pts, operation=scatter_rasterize, predicate=lambda pts: len(pts) > self.p.max_points ).opts( opts.Image(clim=(1, np.nan), clipping_colors={"min": "transparent"}, cmap=cmap), opts.Points(clim=(1, np.nan), clipping_colors={"min": "transparent"}, cmap=cmap), opts.Overlay( hooks=[partial(reset_hook, x_range=x_range, y_range=y_range)]), ) # Set up sky plot sky_range = RangeXY() if self.p.sky_range_stream: def redim_sky(dset, x_range, y_range): ranges = {} if x_range and all(isfinite(v) for v in x_range): ranges["ra"] = x_range if y_range and all(isfinite(v) for v in x_range): ranges["dec"] = y_range return dset.redim.range(**ranges) if ranges else dset dset_sky = dset.apply(redim_sky, streams=[self.p.sky_range_stream]) link_streams(self.p.sky_range_stream, sky_range) else: dset_sky = dset sky_pts = dset_sky.apply(filterpoints, xdim="ra", ydim="dec", set_title=False, streams=[self.p.filter_stream]) skyplot_streams = [sky_range, PlotSize()] sky_rasterize = rasterize.instance( aggregator=ds.mean(self.p.ydim), streams=skyplot_streams, x_sampling=ra_sampling, y_sampling=dec_sampling, ) sky_rasterized = apply_when( sky_pts, operation=sky_rasterize, predicate=lambda pts: len(pts) > self.p.max_points).opts( opts.Image(bgcolor="black", cmap=self.p.sky_cmap, symmetric=True), opts.Points(bgcolor="black", cmap=self.p.sky_cmap, symmetric=True), opts.Overlay(hooks=[ partial(reset_hook, x_range=ra_range, y_range=dec_range) ]), ) # Set up BoundsXY streams to listen to box_select events and notify FilterStream scatter_select = BoundsXY(source=scatter_pts) scatter_notifier = partial(notify_stream, filter_stream=self.p.filter_stream, xdim=self.p.xdim, ydim=self.p.ydim) scatter_select.add_subscriber(scatter_notifier) sky_select = BoundsXY(source=sky_pts) sky_notifier = partial(notify_stream, filter_stream=self.p.filter_stream, xdim="ra", ydim="dec") sky_select.add_subscriber(sky_notifier) # Reset reset = PlotReset(source=sky_pts) reset.add_subscriber( partial(reset_stream, self.p.filter_stream, [self.p.sky_range_stream, self.p.scatter_range_stream])) raw_scatterpts = filterpoints(dset, xdim=self.p.xdim, ydim=self.p.ydim) raw_scatter = datashade( raw_scatterpts, cmap=list(Greys9[::-1][:5]), streams=scatter_streams, x_sampling=x_sampling, y_sampling=y_sampling, ) scatter_p = raw_scatter * scatter_rasterized if self.p.show_rawsky: raw_skypts = filterpoints(dset, xdim=self.p.xdim, ydim=self.p.ydim) raw_sky = datashade( rawskypts, cmap=list(Greys9[::-1][:5]), streams=skyplot_streams, x_sampling=ra_sampling, y_sampling=dec_sampling, ) sky_p = raw_sky * sky_rasterized else: sky_p = sky_rasterized if self.p.show_table: table = dset.apply(summary_table, ydim=self.p.ydim, streams=[self.p.filter_stream]) table = table.opts() layout = table + scatter_p + sky_p else: layout = (scatter_p + sky_p).opts(sizing_mode="stretch_width") return layout.opts( opts.Image(colorbar=True, responsive=True, tools=["box_select", "hover"]), opts.Layout(sizing_mode="stretch_width"), opts.Points(color=self.p.ydim, tools=["hover"]), opts.RGB(alpha=0.5), opts.Table(width=200), )