How to use BoundsX or Selection1D on a stream

Hello everyone.
I would like to calculate the mean value of a time series from a data stream.

So far I could only find examples using a static curve as a source, e.g. in BoundsX — HoloViews v1.15.0. My trails always ran into errors.

  1. Is it possible at all?
  2. Do I have to use another approach, e.g. use the bokeh API → selection Module — HoloViews v1.15.0?

Example:

import pandas as pd
import numpy as np
import holoviews as hv
from holoviews import streams
hv.extension('bokeh')

n = 200
xs = np.linspace(0, 1, n)
ys = np.cumsum(np.random.randn(n))
df = pd.DataFrame({'x': xs, 'y': ys})
curve = hv.Curve(df)  # Stream possible? (https://holoviews.org/user_guide/Streaming_Data.html?highlight=stream#buffer)

def make_from_boundsx(boundsx):
    # Question: df must be defined as `global`?
    sub = df.set_index('x').loc[boundsx[0]:boundsx[1]]
    return hv.Table(sub.describe().reset_index().values, 'stat', 'value')

dmap = hv.DynamicMap(make_from_boundsx, streams=[streams.BoundsX(source=curve, boundsx=(0,0))])

curve.opts(tools=['xbox_select']) + dmap

Thanks for any feedback.

Please try hv.Points.
You could add hv.Curve to it by * on top ot points if you need to keep curve too.

1 Like

Hi @WolframStrauss

I believe something like the below might be used as inspiration.

streaming-bounds

import holoviews as hv
import numpy as np
import panel as pn
import pandas as pd
from holoviews.streams import Buffer, BoundsX

pn.extension()
hv.extension('bokeh')

buffer = Buffer(np.zeros((0, 2)), length=50)

def update_buffer():
    buffer.send(np.array([[pd.Timestamp.now(), np.random.rand()]]))
   
update_buffer() # Needed to tell the streaming_curve that the x data type is datetime64[ns]

pn.state.add_periodic_callback(update_buffer, period=500)

streaming_curve = hv.DynamicMap(hv.Curve, streams=[buffer]).opts(padding=0.1, width=600)

def make_from_boundsx(boundsx):
    # Question: df must be defined as `global`?
    start, end = boundsx
    
    try:
        df = pd.DataFrame(buffer.data, columns=["x", "y"])
        df = df[((df.x>=start) & (df.x<=end))]
    except:
        df = pd.DataFrame({}, columns=["x", "y"])
    
    table = hv.Table(df)
    return table

boundsx_table = hv.DynamicMap(make_from_boundsx, streams=[BoundsX(source=streaming_curve, boundsx=(0,0))])

plot = streaming_curve.opts(tools=['xbox_select']) + boundsx_table


pn.pane.HoloViews(plot).servable()
panel serve script.py
1 Like