Python Bokeh:CustomJS 不会更新 NetworkRenderer 中节点的颜色

问题描述 投票:0回答:1

我希望能够使用 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)
python bokeh
1个回答
0
投票

它是监视更改事件以触发重绘的数据源

graph_renderer.node_renderer.data_source.change.emit()

可以通过在

args
中配置数据源本身而不是图形渲染器来简化回调。

© www.soinside.com 2019 - 2024. All rights reserved.