Skip to content

Holoviews streaming plots don't update #5529

@pepijndevos

Description

@pepijndevos

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()

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions