-
Notifications
You must be signed in to change notification settings - Fork 810
Description
Describe the bug
I'm porting a Panel app to Marimo, which so far turns out much simpler than the old code but for plotting I'm using Holoviews plots with streaming and downsampling which don't appear to work.
Upstream docs: https://holoviews.org/user_guide/Streaming_Data.html
timeplot returns a DynamicMap that takes a data and cols parameter via Stream (/Pipe/Buffer), and then renders a Curve with that information. But the plot is not updating at all. Only if you manually rerun the cell does it show the result.
This seems related to #979 but it seems maybe more stuff is needed to make streaming work.
My new backend actually doesn't produce streaming results at the moment Innovoltive/InSpice#5 so as a workaround the current behavior could be implemented purely with Marimo reactivity, by just redrawing the whole plot when the selection or dataframe is updated. But eventually I do want to actually stream data and reactivity seems ill suited for this task.
ps the multiselect loses its state when the options are updated (but not actually different), is there a way to preserve the selection of any keys that are actually the same?
Will you submit a PR?
- Yes
Environment
{
"marimo": "0.13.15",
"OS": "Linux",
"OS Version": "6.15.4-arch2-1",
"Processor": "",
"Python Version": "3.13.5",
"Binaries": {
"Browser": "--",
"Node": "v24.3.0"
},
"Dependencies": {
"click": "8.2.1",
"docutils": "0.21.2",
"itsdangerous": "2.2.0",
"jedi": "0.19.2",
"markdown": "3.8",
"narwhals": "1.41.0",
"packaging": "25.0",
"psutil": "7.0.0",
"pygments": "2.19.1",
"pymdown-extensions": "10.15",
"pyyaml": "6.0.2",
"starlette": "0.46.2",
"tomlkit": "0.13.2",
"typing-extensions": "4.14.0",
"uvicorn": "0.34.3",
"websockets": "15.0.1"
},
"Optional Dependencies": {
"anywidget": "0.9.18",
"nbformat": "5.10.4",
"pandas": "2.3.0",
"loro": "1.5.1"
},
"Experimental Flags": {}
}
Code to reproduce
import marimo
__generated_with = "0.13.15"
app = marimo.App()
@app.cell
def _():
import marimo as mo
import pandas as pd
import numpy as np
from holoviews.streams import Pipe
import holoviews as hv
from holoviews.streams import Buffer, Stream, param
from holoviews.operation.downsample import downsample1d
from bokeh.models import WheelZoomTool
return Pipe, Stream, WheelZoomTool, downsample1d, hv, mo, pd
@app.cell
def _(Stream, WheelZoomTool, downsample1d, hv):
hv.extension('bokeh')
active_traces = Stream.define('traces', cols=[])
def configure_tools(plot, element):
for t in plot.state.toolbar.tools:
if isinstance(t, WheelZoomTool):
t.dimensions = 'width'
def _timeplot(data, cols=[]):
print(data)
print(cols)
traces = {k: hv.Curve(data, 'index', k).redim(**{k:'amplitude', 'index':'time'}) for k in cols}
if not cols: # hack
traces = {"dummy": hv.Scatter([])}
return hv.NdOverlay(traces, kdims='k')
def timeplot(streams):
curve_dmap = hv.DynamicMap(_timeplot, streams=streams)
return downsample1d(curve_dmap).opts(responsive=True, height=500, hooks=[configure_tools])
return active_traces, timeplot
@app.cell
def _(Pipe, active_traces):
cols = active_traces()
data = Pipe(data=[])
return cols, data
@app.cell
def _(mo):
vectors = mo.ui.multiselect(
options=["w3", "w4", "vv1"], label="Vectors"
)
vectors
return (vectors,)
@app.cell
def _(cols, vectors):
cols.update(cols=vectors.value)
return
@app.cell
def _(cols, data, timeplot):
timeplot([data, cols])
return
@app.cell
def _(data, pd):
df = pd.DataFrame({
'w3': [0.0, 0.0006283184893762573, 0.0006811324343870013, 0.000786760318561498, 0.0009980160593977153, 0.0014205273980205679, 0.0022655492390802443, 0.003955587464557044, 0.0073356251938384185, 0.01409541060738668, 0.02761274006356876, 0.054629786326082536, 0.10852432543026826, 0.21520473253314254, 0.41980225397399734, 0.7077707712911883, 0.9598565599380052, 0.9414089343719086, 0.5633750931885622, -0.029848885177676202, -0.6116716039323348, -0.9598565599380053, -0.9414089343719085, -0.5633750931885612, 0.02984888517767697, 0.6116716039323354, 0.9598565599380053, 0.941408934371908, 0.5633750931885605, -0.029848885177677736, -0.611671603932336, -0.9598565599380058, -0.9414089343719081, -0.5633750931885592, 0.02984888517767761, 0.6116716039323359, 0.9598565599380052, 0.9414089343719081, 0.5633750931885636, -0.029848885177675713, -0.611671603932333, -0.9598565599380038, -0.9414089343719105, -0.5633750931885667, -7.347880794884119e-16],
'index': [0.0, 1.0000000000000002e-07, 1.0840560221521613e-07, 1.2521680664564834e-07, 1.5883921550651273e-07, 2.2608403322824154e-07, 3.605736686716991e-07, 6.295529395586144e-07, 1.1675114813324446e-06, 2.2434285648801056e-06, 4.395262731975427e-06, 8.69893106616607e-06, 1.7306267734547355e-05, 3.4520941071309924e-05, 6.895028774483506e-05, 0.00012514952053790742, 0.00020475130333365396, 0.00030475130333365395, 0.00040475130333365395, 0.000504751303333654, 0.000604751303333654, 0.0007047513033336541, 0.0008047513033336541, 0.0009047513033336542, 0.0010047513033336541, 0.0011047513033336542, 0.0012047513033336542, 0.0013047513033336542, 0.0014047513033336543, 0.0015047513033336543, 0.0016047513033336544, 0.0017047513033336544, 0.0018047513033336545, 0.0019047513033336545, 0.0020047513033336546, 0.0021047513033336544, 0.0022047513033336542, 0.002304751303333654, 0.002404751303333654, 0.0025047513033336537, 0.0026047513033336535, 0.0027047513033336534, 0.002804751303333653, 0.002904751303333653, 0.003],
'w4': [0.0, 0.0006276907985776795, 0.0006804475478742661, 0.0007859521723213981, 0.0009969081928569161, 0.0014186073769587879, 0.0022611547686710426, 0.00394284925175787, 0.0072926657746408465, 0.01393823772929393, 0.027014944897339584, 0.05232473286568526, 0.09967759588039364, 0.18210410345185538, 0.30316426112427863, 0.39496198212490097, 0.3503907423660034, 0.10449849707793678, -0.21718972842958528, -0.46787922838735413, -0.5438415552988904, -0.41340382243674395, -0.12550285710151693, 0.21018827508839275, 0.4655454106069564, 0.5430636160387579, 0.4131445093500327, 0.1254164194059461, -0.21021708765358318, -0.46555501479535333, -0.5430668174348899, -0.4131455764820765, -0.1254167751166271, 0.2102169690833568, 0.46555497527194334, 0.54306680426042, 0.4131455720905862, 0.12541677365279735, -0.2102169695712971, -0.46555497543459184, -0.5430668043146356, -0.41314557210865926, -0.12541677365882434, 0.2102169695692877, 0.4562103802787075],
'vv1': [0.0, -6.276907985777215e-06, -6.804475478738858e-06, -7.859521723219132e-06, -9.96908192855972e-06, -1.4186073769587026e-05, -2.2611547686707256e-05, -3.942849251757988e-05, -7.292665774640689e-05, -0.00013938237729294034, -0.00027014944897339743, -0.0005232473286568527, -0.000996775958803934, -0.0018210410345185536, -0.0030316426112427866, -0.003949619821249011, -0.0035039074236600347, -0.0010449849707793676, 0.0021718972842958524, 0.00467879228387354, 0.005438415552988903, 0.004134038224367439, 0.0012550285710151692, -0.0021018827508839273, -0.004655454106069563, -0.005430636160387577, -0.0041314450935003265, -0.0012541641940594607, 0.0021021708765358313, 0.004655550147953531, 0.0054306681743488995, 0.004131455764820765, 0.0012541677511662703, -0.0021021696908335675, -0.004655549752719432, -0.005430668042604199, -0.004131455720905862, -0.0012541677365279728, 0.002102169695712971, 0.0046555497543459175, 0.005430668043146354, 0.004131455721086592, 0.0012541677365882436, -0.0021021696956928767, -0.004562103802787074],
})
data.update(data=df)
return
if __name__ == "__main__":
app.run()