marimo-team / marimo

A reactive notebook for Python — run reproducible experiments, execute as a script, deploy as an app, and version with git.
https://marimo.io
Apache License 2.0
5.35k stars 156 forks source link

Holoviews HoloMap and DynamicMap don't work #979

Open mgunyho opened 3 months ago

mgunyho commented 3 months ago

Describe the bug

If I try to display a Holoviews HoloMap or DynamicMap, I get blank/textual output instead of an interactive plot (example code taken from Holoviews docs):

marimo-holoviews-text

See here how it should look like: https://holoviews.org/reference/containers/bokeh/HoloMap.html

I would like to use Holoviews with HoloMap/DynamicMap to visualize multidimensional data using sliders, which I currently do very often in Jupyter. I understand that this is a bit redundant since marimo has it's own slider widget, but I couldn't find a better way to do this kind of slicing through multidimensional data (I tried Altair, but there the sliders cannot handle values that are not evenly spaced).

This can probably be fixed by adding one of the superclasses of HoloMap to HoloviewsFormatter._show_chart here. Here's the inheritance hierarchy of HoloMap:

(<class 'holoviews.core.spaces.HoloMap'>,
 <class 'holoviews.core.layout.Layoutable'>,
 <class 'holoviews.core.ndmapping.UniformNdMapping'>,
 <class 'holoviews.core.ndmapping.NdMapping'>,
 <class 'holoviews.core.ndmapping.MultiDimensionalMapping'>,
 <class 'holoviews.core.dimension.Dimensioned'>,
 <class 'holoviews.core.dimension.LabelledData'>,
 <class 'param.parameterized.Parameterized'>,
 <class 'holoviews.core.overlay.Overlayable'>,
 <class 'object'>)

I'm not familiar enough with the internals of holoviews to say which of these should be added to _show_chart. DynamicMap is a subclass of HoloMap.

As a bonus, if I convert the HoloMap to a layout with hv.Layout(hv.HoloMap(...)), the cell grows indefinitely (similar to #978):

https://github.com/marimo-team/marimo/assets/20118130/3d316294-ea77-4f73-8a88-839bc65f6e02

I'm using a virtualenv with pip install marimo matplotlib tornado holoviews. Here's the full output of pip list: Click to show

Package             Version    
------------------- -----------
anyio               4.3.0      
black               24.3.0     
bleach              6.1.0      
bokeh               3.1.1      
certifi             2024.2.2   
charset-normalizer  3.3.2      
click               8.1.7      
colorcet            3.1.0      
contourpy           1.1.1      
cycler              0.12.1     
docutils            0.20.1     
exceptiongroup      1.2.0      
fonttools           4.50.0     
h11                 0.14.0     
holoviews           1.17.1     
idna                3.6        
importlib-metadata  7.1.0      
importlib-resources 6.4.0      
jedi                0.19.1     
Jinja2              3.1.3      
kiwisolver          1.4.5      
linkify-it-py       2.0.3      
marimo              0.3.3      
Markdown            3.6        
markdown-it-py      3.0.0      
MarkupSafe          2.1.5      
matplotlib          3.7.5      
mdit-py-plugins     0.4.0      
mdurl               0.1.2      
mypy-extensions     1.0.0      
numpy               1.24.4     
packaging           24.0       
pandas              2.0.3      
panel               1.2.3      
param               2.0.2      
parso               0.8.3      
pathspec            0.12.1     
pillow              10.2.0     
pip                 20.0.2     
pkg-resources       0.0.0      
platformdirs        4.2.0      
pygments            2.17.2     
pymdown-extensions  10.7.1     
pyparsing           3.1.2      
python-dateutil     2.9.0.post0
pytz                2024.1     
pyviz-comms         3.0.1      
PyYAML              6.0.1      
requests            2.31.0     
setuptools          44.0.0     
six                 1.16.0     
sniffio             1.3.1      
starlette           0.37.2     
tomli               2.0.1      
tomlkit             0.12.4     
tornado             6.4        
tqdm                4.66.2     
typing-extensions   4.10.0     
tzdata              2024.1     
uc-micro-py         1.0.3      
urllib3             2.2.1      
uvicorn             0.29.0     
webencodings        0.5.1      
websockets          12.0       
xyzservices         2023.10.1  
zipp                3.18.1     

I am using Python 3.8 with Ubuntu 20.04 on Firefox 123.0.1

Environment

{
  "marimo": "0.3.3",
  "OS": "Linux",
  "OS Version": "5.15.0-100-generic",
  "Processor": "x86_64",
  "Python Version": "3.8.10",
  "Binaries": {
    "Chrome": "123.0.6312.58",
    "Node": "--"
  },
  "Requirements": {
    "black": "24.3.0",
    "click": "8.1.7",
    "jedi": "0.19.1",
    "pygments": "2.17.2",
    "pymdown-extensions": "10.7.1",
    "starlette": "0.37.2",
    "tomlkit": "0.12.4",
    "uvicorn": "0.29.0"
  }
}

Code to reproduce

import marimo

__generated_with = "0.3.3"
app = marimo.App()

@app.cell
def __():
    import numpy as np
    import holoviews as hv
    hv.extension("bokeh")
    return hv, np

@app.cell
def __(hv, np):
    _t = np.linspace(0, 10, 101)
    hv.HoloMap(
        {f: hv.Curve((_t, np.sin(f * _t))) for f in [0.5, 0.75, 1.0]},
        kdims="frequency",
    )
    return

@app.cell
def __(hv, np):
    _t = np.linspace(0, 10, 101)
    _hm = hv.HoloMap(
        {f: hv.Curve((_t, np.sin(f * _t))) for f in [0.5, 0.75, 1.0]}, 
        kdims="frequency"
    )
    hv.Layout(_hm)
    return

@app.cell
def __(hv):
    from pprint import pprint
    pprint(hv.HoloMap.__mro__)
    return pprint,

if __name__ == "__main__":
    app.run()
mgunyho commented 1 month ago

Hi, I tested this with 0.5.2 now, and the HoloMap is displayed, but still not fully functioning: the slider does not appear.

image

Compare to the example in the documentation:

image

Or in Jupyter:

image

Having these sliders is the main reason for using Holoviews / HoloMap for me, and this is keeping me from using marimo as my main notebook.

For reference, here is the code for the MWE

import numpy as np
import holoviews as hv
hv.extension("bokeh")

_t = np.linspace(0, 10, 101)
hv.HoloMap(
    {f: hv.Curve((_t, np.sin(f * _t))) for f in [0.5, 0.75, 1.0]},
    kdims="frequency",
)

Also here's the output of marimo env, let me know if you need some more information.

{
  "marimo": "0.5.2",
  "OS": "Linux",
  "OS Version": "5.15.0-105-generic",
  "Processor": "x86_64",
  "Python Version": "3.8.10",
  "Binaries": {
    "Browser": "124.0.6367.207",
    "Node": "--"
  },
  "Requirements": {
    "click": "8.1.7",
    "importlib-resources": "6.4.0",
    "jedi": "0.19.1",
    "markdown": "3.6",
    "pymdown-extensions": "10.8.1",
    "pygments": "2.18.0",
    "tomlkit": "0.12.5",
    "uvicorn": "0.29.0",
    "starlette": "0.37.2",
    "websocket": "missing",
    "typing-extensions": "4.11.0",
    "black": "24.4.2"
  }
}
mscolnick commented 1 month ago

Right now, we render HoloMap by converting it to its backend (bokeh/plotly/matplotlib) and then rendering using those specific formatters (e.g. bokeh) to convert to HTML. I think the fix would be to render the HoloMap using panel which seems to be the one adding the slider. I am not familiar enough with that library to support rendering going from HoloMap -> HTML using panel, but if anyone is, we would welcome a contribution.