Laure D
Laure D

Reputation: 887

DatetimeRangeSlide updating network graph with bokeh

I would like to update a network graph using a datetime range slider with Bokeh. So appearing/disappearing nodes depending on the datetime range, and also width of edges is proportional to the number of connections between sources and target within datetime range.

So far here is my code:

nb_conn = df.groupby(['src','dst'])['src'].count()
nb_conn = nb_conn.rename("nb_conn")
nb_conn_tot = nb_conn.sum()
ratio_nb_conn = (nb_conn/nb_conn_tot)*100

netflow_feat = (
    df.merge(ratio_nb_conn, on=["src", 'dst'])
)

G = nx.from_pandas_edgelist(netflow_feat, source='src', target='dst' ,edge_attr='nb_conn')

degrees = dict(nx.degree(G))
nx.set_node_attributes(G, name='degree', values=degrees)

number_to_adjust_by = 5
adjusted_node_size = dict([(node, degree+number_to_adjust_by) for node, degree in nx.degree(G)])
nx.set_node_attributes(G, name='adjusted_node_size', values=adjusted_node_size)

number_to_adjust_by = 5
adjusted_node_size = dict([(node, degree+number_to_adjust_by) for node, degree in nx.degree(G)])
nx.set_node_attributes(G, name='adjusted_node_size', values=adjusted_node_size)

#Choose attributes from G network to size and color by — setting manual size (e.g. 10) or color (e.g. 'skyblue') also allowed
size_by_this_attribute = 'adjusted_node_size'
color_by_this_attribute = 'adjusted_node_size'

#Pick a color palette — Blues8, Reds8, Purples8, Oranges8, Viridis8
color_palette = Blues8

#Choose a title!
title = 'Cibles Network'

#Establish which categories will appear when hovering over each node
HOVER_TOOLTIPS = [
       ("IP", "@index"),
]

#Create a plot — set dimensions, toolbar, and title
plot = figure(tooltips = HOVER_TOOLTIPS,
              tools="pan,wheel_zoom,save,reset", active_scroll='wheel_zoom',
            x_range=Range1d(-20.1, 20.1), y_range=Range1d(-20.1, 20.1), title=title)

#Create a network graph object
# https://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.drawing.layout.spring_layout.html\
network_graph = from_networkx(G, nx.spring_layout, scale=20, center=(0, 0))

#Set node sizes and colors according to node degree (color as spectrum of color palette)
minimum_value_color = min(network_graph.node_renderer.data_source.data[color_by_this_attribute])
maximum_value_color = max(network_graph.node_renderer.data_source.data[color_by_this_attribute])
network_graph.node_renderer.glyph = Circle(fill_color=linear_cmap(color_by_this_attribute, color_palette, minimum_value_color, maximum_value_color))

#Set edge opacity and width
network_graph.edge_renderer.data_source.data["line_width"] = [G.get_edge_data(a,b)['nb_conn'] for a, b in G.edges()]
network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5)
network_graph.edge_renderer.glyph.line_width = {'field': 'line_width'}

plot.renderers.append(network_graph)

backup_edge_data = copy.deepcopy(network_graph.edge_renderer.data_source.data)

code = """ 

    # print out array of date from, date to
    console.log(cb_obj.value); 
    
    # dates returned from slider are not at round intervals and include time;
    const date_from = Date.parse(new Date(cb_obj.value[0]).toDateString());
    const date_to = Date.parse(new Date(cb_obj.value[1]).toDateString());

    const old_Weight = df["nb_conn"];
    const old_start = df.loc[start];
    const old_end = df.loc[end];

    const df_filtered = df[(df['timestamp'] >= date_from) & (df['timestamp'] <= date_to)]

    What should I do here??? 

    graph_setup.edge_renderer.data_source.data = new_data_edge; 
    graph_setup.edge_renderer.data_source.change.emit();
    
"""
callback = CustomJS(args = dict(graph_setup = network_graph,
                                df=netflow_feat,
                                start = netflow_feat['timestamp'].min,
                                end = netflow_feat['timestamp'].max), code = code)

datetime_range_slider = DatetimeRangeSlider(value=(datetime(2023, 1, 5, 12), datetime(2022, 1, 6, 18)),
                                            start=datetime(2023, 1, 5), end=datetime(2023, 1, 7))


datetime_range_slider.js_on_change("value", callback) 

layout = Column(plot, datetime_range_slider)
show(layout)

In the callback function, is it supposed to be only javascript? I guess my callback function is not correct but I don't know how to do what I'd like to do, or is it even possible?

Upvotes: 0

Views: 58

Answers (0)

Related Questions