Search code examples
python-3.xbokehholoviews

Change pan of DynamicMap with callback


I have timeseries data which I want to display day by day using holoviews in a bokeh server. My code boils down to:

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

hv.extension("bokeh", "matplotlib")
renderer = hv.renderer('bokeh')

df = pd.DataFrame(pd.date_range("2019-11-01", "2019-11-07", freq="H"), columns=["timestamp"])
df["level"] = 17
df = df.set_index("timestamp")
ds = hv.Dataset(df, kdims="timestamp", vdims="level")

days = list(sorted({t.date() for t in df.index}))
pattern_dim = hv.Dimension('Day', values=days)

dmap = hv.DynamicMap(lambda d: ds[d:d + np.timedelta64(1, 'D')].to(hv.Curve), kdims=[pattern_dim])
doc = renderer.server_doc(dmap)

However when I change the day using the slider in bokeh serve ... I have to manually adjust the pan to view the new data. Can this be done using the callback?

Something similar has been asked for bokeh without holoviews: Manually change x range for Bokeh plot


Solution

  • The solution is using DataRange1d

    import pandas as pd
    import numpy as np
    import holoviews as hv
    from bokeh.models import DataRange1d
    from bokeh.plotting import Figure
    
    hv.extension("bokeh", "matplotlib")
    renderer = hv.renderer('bokeh')
    
    df = pd.DataFrame(pd.date_range("2019-11-01", "2019-11-07", freq="H"), columns=["timestamp"])
    df["level"] = 17
    df = df.set_index("timestamp")
    ds = hv.Dataset(df, kdims="timestamp", vdims="level")
    
    days = list(sorted({t.date() for t in df.index}))
    pattern_dim = hv.Dimension('Day', values=days)
    dmap = hv.DynamicMap(lambda d: ds[d:d + np.timedelta64(1, 'D')].to(hv.Curve), kdims=[pattern_dim])
    doc = renderer.server_doc(dmap)
    for x in doc.select({'type': Figure}):
        x.x_range = DataRange1d()
    

    Found in this github issue: https://github.com/pyviz/holoviews/issues/2441