Confused how to make animate_update with DateSlider

I am trying to understand/adapt the code at: Deploying Bokeh Apps — HoloViews 1.14.5 documentation. I’m using to animate a heatmap. I have the data in the proper format ie. the plots are in a dict where the keys are the date (‘heatmap_keys’) and the values are the heatmaps. My problem is using the DateSlider where I am trying to make it show the dates ie. the ‘heatmap_keys’ instead of just the index of the keys.

In the code below I have the slider values as a list of datetime objects, ‘slider_vals’. I do this so that the slider value displayed is the date of the heatmap being shown.

def modify_doc(doc):
    # Create HoloViews plot and attach the document
    hvplot = renderer.get_plot(dmap, doc)

    # Create a slider and play buttons
    def animate_update():
        year = slider.value + 1
        if year > end:
            year = start
        slider.value = year

    def slider_update(attrname, old, new):
        # Notify the HoloViews stream of the slider update 
        stream.event(phase=new)
    
    slider_vals = [datetime.datetime.strptime(i,'%Y-%m-%d') for i in heatmap_keys]
    start, end = slider_vals[0], slider_vals[-1]
    slider = DateSlider(start=start, end=end, value=start, step=1, title="Phase"
                    ,show_value=True, height=30, width=180, format='%Y-%m-%d')
    slider.on_change('value', slider_update)
    
    callback_id = None

    def animate():
        global callback_id
        if button.label == '► Play':
            button.label = '❚❚ Pause'
            callback_id = doc.add_periodic_callback(animate_update, 80)
        else:
            button.label = '► Play'
            doc.remove_periodic_callback(callback_id)
    button = Button(label='► Play', width=60, height=30)
    button.on_click(animate)
    
    # Combine the holoviews plot and widgets in a layout
    plot = layout([
    [hvplot.state],
    [slider, button]], sizing_mode='fixed')
    
    doc.add_root(plot)
    return doc

My problem is that when the ‘animate_update’ function is called I get an error:

TypeError: '>' not supported between instances of 'float' and 'datetime.datetime'

That’s because in the if statement ‘slider.value + 1’ becomes a float and is compared to ‘end’ which is a datetime object. What I think should happen is that ‘year’ should be the next key in the ‘slider_vals’ list but I don’t know how to make that happen. It looks like start,step, and end are meant to be integers and the it’s assumed the keys to the dict of plots can just be integers. Any guidance would be appreciated.

@Michael_Bourassa The value property is usually demoninated in milliseconds-since-epoch. You can use the helper property value_as_datetime to retrieve the value, always as a datetime object. (Note that, I think that then you would need to add a real datetime interval to it, not just “1”)

Ah. The docs seemed to suggest the interval was related to the index of the stream eg. 0, 1, 2 … Since the data is a sequence separated by non-constant time intervals it looks like this is a non-starter. It would be good if the value displayed could be just the key of the value displayed.

@Michael_Bourassa FYI a categorical slider is still an open feature request: categorical slider · Issue #9843 · bokeh/bokeh · GitHub However unless I am misunderstanding, it seems like you could use an integer slider with a step size of one, and a format set to render whatever you want instead of integers?

@Bryan I Encountered a similar problem that the DateSlider doesn’t response with step interval when I try to move it but appear in either start or end of slider. I try to use Slider but it’s failed with formate="%F %T" or formate="%Y-%m-%d %H:%M:%S". How to format here?

@swpper1 It’s not possible to speculate without concrete information, and picking up the context from years-old threads is also always a challenge. Please open a new topic with a complete Minimal Reproducible Example

OK. I will open a new topic.

1 Like