I’m not sure if this should be one bug report or many, and how to best provide reproducers, so I’m posting here first to workshop the problem into something the maintainers can hopefully work with.
Bug 1: plot bounds don’t update when new data arrives. You can mess with the streams, but then it no longer rerenders when you zoom in.
Bug 2: NdOverlay can’t have zero traces, or it’ll give TypeError: issubclass() arg 1 must be a class
Bug 3: Sometimes calling .clear()
on the Buffer
after it has been plotted causes IndexError: iloc cannot enlarge its target object
on the Holoviews side.
Bug 4: Plotting a single row can cause ValueError: cannot convert float NaN to integer
when using the count_cat
aggregator.
Bug 5: If you try to plot different columns from the dataframe it throws KeyError: "Dimension('foo') not found."
Bug 6: I’m probably forgetting stuff I’ve already worked around somehow…
All of these issues can be reproduces by fiddling around with the following code a bit. Use a different aggregator, plot a bit of data, plot a bit more data, clear the data, select different traces, etc.
import holoviews as hv
import datashader as ds
import pandas as pd
import numpy as np
from holoviews.streams import Buffer, Stream, param
from holoviews.operation.datashader import datashade, shade, dynspread, spread, rasterize
hv.extension('plotly')
active_traces = Stream.define('traces', cols=[])
def _timeplot(data, cols=[]):
traces = {k: hv.Curve((data.index, data[k]), 'time', 'amplitude') for k in cols}
#traces = {k: hv.Curve(data, 'index', k) for k in cols}
# if not traces:
# traces = {"dummy": hv.Curve([])}
return hv.NdOverlay(traces, kdims='k')
def timeplot(streams):
curve_dmap = hv.DynamicMap(_timeplot, streams=streams)
# return spread(datashade(curve_dmap, aggregator=ds.by('k', ds.any())))
# return spread(datashade(curve_dmap, aggregator=ds.by('k', ds.count()), width=1000, height=1000))
return spread(datashade(curve_dmap, aggregator=ds.count_cat('k'), width=1000, height=1000))
n=100
m=1000
def stream(streamdict):
"""
Stream simulation data into a Streamz DataFrame
Takes an optional document to stream in `add_next_tick_callback` or
a cell handle to invoke `push_notebook` on.
"""
for i in range(n):
res = {"stuff": pd.DataFrame({'foo': np.random.rand(m), 'bar': np.random.rand(m)+0.8, 'baz': np.random.rand(m)-0.8}, index=np.arange(m)+m*i)}
for k, v in res.items():
#print(list(v.columns), list(streamdict[k].data.columns))
if k in streamdict and list(v.columns) == list(streamdict[k].data.columns):
streamdict[k].send(v)
else:
buf = Buffer(v, length=int(1e9), index=False)
streamdict[k] = buf
yield
cols = active_traces(cols=['foo', 'bar', 'baz'])
Things to play with:
d = {}
it = stream(d)
next(it)
timeplot([d['stuff'], cols])
cols.event(cols=[])
d['stuff'].clear()