Bug when saving dynamic map

Hello everyone,

I’ve reported this bug last year in the ‘Holoviews’ category. There it was pointed out there that the bug may be related to Panel. Since I’ve been running in to the same problem over and over, I thought I would re-ask this question in this category in the hopes that someone might have a fix or a workaround I could use.

The issue is that saving any dynamic map or holomap of a network graph with any two or more interactive parameters leads to a file in which changing the interactive parameter affects the graph only in some cases. The more interactive paramers you use, the more annoyingly unresponsive the saved application becomes.

The code below illustrates the issue. It’s just a simple two node graph with one connecting edge and two arbitrary interactive parameters (modification of edge-and node color, but any interactive changes to the graph will lead to the same problem).

I’ve been having this issue for quite some time, so any ideas would really be appreciated.

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

# function that creates a graph with two nodes and one connecting edge and sets its edge and node color to the given 
# function parameters
def hv_graph(edge_color, node_color):
    node_indices = np.arange(2, dtype=np.int32)
    source = np.zeros(2, dtype=np.int32)
    target = node_indices
    graph = hv.Graph(((source, target),)).opts(edge_color=edge_color, node_color=node_color)
    return graph

def main():
    # create the dynamic map
    dmap = hv.DynamicMap(hv_graph, kdims=["edge_color", "node_color"])
    dmap = dmap.redim.values(edge_color=["green", "black"], node_color=["green", "black"])
    # save the dynamic map
    hv.save(dmap, 'dmap.html', backend='bokeh')
    return

if __name__ == '__main__':
    main()

The original discussion of this topic can be found under https://discourse.holoviz.org/t/dynamic-map-unable-to-switch-between-some-cases/2953

Hello @optmat, here is a workaround by using panel.

The code you show is perfectly legit and something I would have also done before panel. But I think the patterns that panel offer will make your life much easier (in addition to solve this specific issue).

This is how it looks (this is code for a notebook).

import panel as pn
import numpy as np
import holoviews as hv
pn.extension()

def hv_graph(edge_color, node_color):
    node_indices = np.arange(2, dtype=np.int32)
    source = np.zeros(2, dtype=np.int32)
    target = node_indices
    graph = hv.Graph(((source, target),)).opts(edge_color=edge_color, node_color=node_color)
    return graph

h = pn.interact(hv_graph,edge_color=['green','black'],node_color=['green','black'])
h.save('dmap.html',embed=True)
h

Note that to specify embed=True is very important since it will precalculate all the states of your app so that the html has all what it needs to be dynamic (without a Python server) ; see embedding and save documentation.

To expect that hv.save or the save method from panel gives you the same interactivity with or without a running Python server is very natural from the user perspective but in reality is asking a lot (given that you could put any kind of calculations inside the hv_graph function). For this to work, it’s better to have a limited number of states (the default is limited to 1000 states).
In your case though, if all you do is to expose Bokeh options, there would certainly be a more efficient way than precalculating every state, but I guess this would require to integrate and interact with bokehjs directly and write some html and js code.

2 Likes

@marcbernot
Thanks a million, that‘s exactly what I was looking for, I really appreciate the help :slight_smile: