Как преобразовать граф Holoviews в «модель» Bokeh, чтобы использовать больше функций Bokeh, таких как bokeh.models.GraphRenderer и node_renderer? - PullRequest
0 голосов
/ 28 июня 2019

Я пытаюсь создать ориентированный граф, используя networkx и bokeh, однако я также хочу показать стрелки для каждого аута. Я обнаружил, что библиотека Holoviews имеет возможность добавить параметр 'Direct = True' в свой конструктор графа. Однако я также хочу использовать конструктивные особенности Bokeh, такие как настройка цвета / размера узла на основе ранее установленных атрибутов узла. Последний работает только в том случае, если я использую Bokeh from_networkx () для получения объекта bokeh.models.renderers.GraphRender, а затем использую его атрибуты node_renderer и edge_renderer.

Проблема заключается в том, что при использовании средства визуализации Holoviews для указания Bokeh в качестве бэкэнда он возвращает bokeh.plotting.figure.Figure вместо GraphRenderer. В конечном счете, я хочу знать, как уметь контролировать размер / цвет узла на основе некоторых атрибутов, возможных через Bokeh, и одновременно использовать Holoviews для отображения стрелок на каждом краю.

import networkx as nx
import holoviews as hv
from holoviews import opts
hv.extension('bokeh')
from bokeh.io import show, output_file

# ... some code for I/O ...
G = nx.DiGraph(edgeList)   # Directed networkx graph

# Set Node/Edge attributes to display upon hover
numConnections = {k:v for k,v in G.out_degree()}
nx.set_node_attributes(G, numConnections, name='numConnections')

# Returns Holoviews graph
hvGraph = hv.Graph.from_networkx(G, nx.spring_layout).opts(tools=['hover'], directed=True, arrowhead_length=0.01)
# Renders Holoviews graph into bokeh.plotting.figure.Figure
hvRendered = hv.render(hvGraph, 'bokeh')

output_file("out.html")
show(hvRendered)


# # The below code runs as expected using Bokeh only, and not Holoviews 
# # to produce the directed graph (without arrowed edges):

# from bokeh.models import Plot, Range1d, MultiLine, Circle
# from bokeh.models import LinearColorMapper, ColorBar, BasicTicker
# import bokeh.models as bm
# from bokeh.models.graphs import from_networkx
# from bokeh.models.graphs import NodesAndLinkedEdges, EdgesAndLinkedNodes


# # Returns GraphRenderer from bokeh.models.renderers.DateRenderer 
# graphRenderer = from_networkx(G, nx.spring_layout)

# mapper = LinearColorMapper(palette="Viridis256", low=76, high=0)

# # Node size/color when unselected / selected / hover
# graphRenderer.node_renderer.glyph = Circle(
#     size='node_size',
#     fill_color= {'field': "numConnections", "transform": mapper},
#     fill_alpha=.8
# )
# graphRenderer.node_renderer.selection_glyph = Circle(
#     size=25,
#     fill_color=Inferno6[4]
# )
# graphRenderer.node_renderer.hover_glyph = Circle(
#     size=20,
#     fill_color=Inferno6[3]
# )

# # Edge size/color when unselected / selected / hover
# graphRenderer.edge_renderer.glyph = MultiLine(
#     line_color="#CCCCCC",
#     line_alpha=0.8,
#     line_width=3
# )
# graphRenderer.edge_renderer.selection_glyph = MultiLine(
#     line_color=Inferno6[4],
#     line_width=4
# )
# graphRenderer.edge_renderer.hover_glyph = MultiLine(
#     line_color=Inferno6[3],
#     line_width=4
# )

# graphRenderer.node_renderer.data_source.data['numConnections'] = [v for k,v in 
    nx.get_node_attributes(G,'numConnections').items()]

# graphRenderer.selection_policy = NodesAndLinkedEdges()
# graphRenderer.inspection_policy = NodesAndLinkedEdges()

# bar = ColorBar(color_mapper=mapper, location=(0,0),     title='#connections')

# # Create Bokeh Plot
# plot = Plot(
#     plot_width=20,
#     plot_height=20,
#     x_range=Range1d(-1.1,1.1),
#     y_range=Range1d(-1.1,1.1)
# )

# plot.add_tools(
#     bm.HoverTool(tooltips=[("#connections", "@numConnections")]),
#     bm.TapTool(),
#     bm.BoxSelectTool()
# )
# plot.renderers.append(graphRenderer)

# output_file("bokeh.html")
# show(plot)

После рендеринга графа Холовьева в фигуру Боке (а не models.GraphRenderer), если я пытаюсь вызвать атрибут node_renderer с использованием визуализированного объекта фигуры Боке, он, очевидно, выдает исключение.

Traceback (последний вызов был последним): файл "holoview.py", строка 106, в hvRenderedGraph.node_renderer.selection_glyph = Circle () AttributeError: объект 'BokehRenderer' не имеет атрибута 'node_renderer'

1 Ответ

1 голос
/ 03 июля 2019

Вы можете получить объект GraphRender с помощью следующего кода:

from bokeh.models import GraphRenderer
gr = hvRendered.select_one(GraphRenderer)

, затем используйте gr.node_renderer и gr.edge_renderer для настройки стиля.

...