我希望能够使用 JS 回调选择不同的底层数据来更改 NetworkRenderer 对象中节点的颜色,但除非我使用一些技巧,否则绘图实际上不会更新。
我尝试使用 CustomJS 更改
'fill_value'
的 node_renderer
属性,以在 node_renderer.data_source
中使用不同的列,但这不会更新绘图(尽管我可以看到 'fill_value
' 是如果我在浏览器控制台中进行一些日志记录,则正确更改)。
我设法真正改变颜色的唯一方法如下。本质上,我需要在
node_renderer.data_source
中复制不同的数据,这没问题,但这还不够:只有当我运行另一个通过 js_link
更改节点的某些属性的回调时,我才能真正更改颜色
方法(在本示例中,我使用微调器更改节点大小) - 一旦更改大小,颜色就会更新,并且需要重复该过程才能使它们再次更改。
我相信这不是正常行为,但这是我的代码的错误或问题吗?
import numpy as np
import networkx as nx
from bokeh.models import Circle, MultiLine, Select, Spinner, CustomJS
from bokeh.plotting import figure, from_networkx, show
from bokeh.palettes import Viridis256
from bokeh.layouts import column
#starting from this example: https://docs.bokeh.org/en/latest/docs/examples/topics/graph/node_and_edge_attributes.html
G = nx.karate_club_graph()
SAME_CLUB_COLOR, DIFFERENT_CLUB_COLOR = "darkgrey", "red"
edge_attrs = {}
for start_node, end_node, _ in G.edges(data=True):
edge_color = SAME_CLUB_COLOR if G.nodes[start_node]["club"] == G.nodes[end_node]["club"] else DIFFERENT_CLUB_COLOR
edge_attrs[(start_node, end_node)] = edge_color
nx.set_edge_attributes(G, edge_attrs, "edge_color")
plot = figure(width=400, height=400, x_range=(-1.2, 1.2), y_range=(-1.2, 1.2),
x_axis_location=None, y_axis_location=None, toolbar_location=None,
title="Graph Interaction Demo", background_fill_color="#efefef",
tooltips="index: @index, club: @club")
plot.grid.grid_line_color = None
graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))
#Some random data for the node colors
cds = ColumnDataSource({'Colors1': [Viridis256[int(val*255)] for val in np.random.rand(len(G.nodes))],
'Colors2': [Viridis256[int(val*255)] for val in np.random.rand(len(G.nodes))]})
#Copy it in the node_renderer
graph_renderer.node_renderer.data_source.data['color'] = cds.data['Colors1']
graph_renderer.node_renderer.glyph = Circle(size=15, fill_color="color")
graph_renderer.edge_renderer.glyph = MultiLine(line_color="edge_color",
line_alpha=1, line_width=2)
#Define the widgets for the interactions
sel = Select(value='Colors1', options=['Colors1', 'Colors2'])
spin = Spinner(title="Glyph size", low=1, high=40, step=0.5, value=10, width=80)
callback = CustomJS(args=dict(graph_renderer=graph_renderer, cds=cds),
code="""
var selection = cb_obj.value
graph_renderer.node_renderer.data_source.data['color'] = cds.data[selection]
graph_renderer.node_renderer.change.emit()
""")
sel.js_on_change('value', callback)
spin.js_link('value', graph_renderer.node_renderer.glyph, 'size')
#Make the plot
plot.renderers.append(graph_renderer)
my_lay = column(sel, spin, plot)
show(my_lay)
它是监视更改事件以触发重绘的数据源
graph_renderer.node_renderer.data_source.change.emit()
可以通过在
args
中配置数据源本身而不是图形渲染器来简化回调。