holoviz / holoviews

With Holoviews, your data visualizes itself.
https://holoviews.org
BSD 3-Clause "New" or "Revised" License
2.66k stars 396 forks source link

Buffer does not work as dict argument to Dynamic Map #6229

Closed MarcSkovMadsen closed 1 month ago

MarcSkovMadsen commented 1 month ago

holoviews==1.18.3

In https://discourse.holoviz.org/t/combining-periodic-and-widget-stream-to-update-plot-fails-for-widget-changes/7221 mcav has a hard time using a Buffer as one of two arguments to a dict stream. I believe its a bug.

Minimum Reproducible Example

import pandas as pd
import numpy as np
import hvplot.pandas
import holoviews as hv

columns = list('XYZ')

data = pd.DataFrame(columns=columns,data=np.random.randn(20,3))

dfstream = hv.streams.Buffer(data=pd.DataFrame(columns=columns),length=90,index=False)
dfstream.send(data)

def plot(data):
    return data.hvplot.scatter(x='X',y='Y',xlim=(-5,5),ylim=(-5,5),grid=True)    

dmap = hv.DynamicMap(plot, streams=dict(data=dfstream))
python script.py
/home/jovyan/repos/private/panel/.venv/lib/python3.11/site-packages/holoviews/streams.py:641: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.
  data = pd.concat([prev_chunk, data])
Traceback (most recent call last):
  File "/home/jovyan/repos/private/panel/script.py", line 16, in <module>
    dmap = hv.DynamicMap(plot, streams=dict(data=dfstream))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jovyan/repos/private/panel/.venv/lib/python3.11/site-packages/holoviews/core/spaces.py", line 775, in __init__
    streams = streams_list_from_dict(streams)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jovyan/repos/private/panel/.venv/lib/python3.11/site-packages/holoviews/streams.py", line 61, in streams_list_from_dict
    raise TypeError(f'Cannot handle value {v!r} in streams dictionary')
TypeError: Cannot handle value Buffer(data=           X         Y         Z
0   0.545012 -0.155991 -1.426602
1   0.537701 -0.169578  0.168053
2  -1.053150  1.221620  0.366327
3   1.004792  0.094682  0.674967
4  -1.095100  0.390450 -0.567742
5  -0.289402 -0.573703 -0.594339
6  -0.623238  0.840135 -1.103545
7   0.471718  0.496780  0.979582
8  -0.163835  0.882186 -0.040379
9  -0.171724  1.403075 -0.809851
10  0.080173  1.319898  0.627089
11 -1.183964  1.132092  1.947823
12 -0.917599  1.360780 -0.814286
13  0.363805 -1.581902  0.425970
14  1.379269 -0.619846  1.105789
15 -1.743800 -0.416551  0.257888
16 -2.148472  0.428031 -0.840506
17  1.112445  0.322527  0.842056
18  0.952212 -0.504896 -1.073879
19 -0.371066 -0.880454  0.236723) in streams dictionary

Workaround

use dict(data=dfstream.param.data) instead of dict(data=dfstream).

hoxbro commented 1 month ago

I think we should register it as a custom transform. Maybe add more if needed.


import param

def streams_transform(obj):
    if isinstance(obj, hv.streams.Buffer):
        return obj.param.data
    return obj

param.reactive.register_reference_transform(streams_transform)