Module optgraphstate.visualization
Expand source code
import igraph as ig
import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch
def _plot_base(g: ig.Graph,
ax=None,
layout='auto',
figsize=(10, 10),
**visual_style):
if not isinstance(g, ig.Graph):
raise TypeError("Parameter 'g' should be an igraph.Graph instance.")
if ax is None:
_, ax = plt.subplots(figsize=figsize)
ig.plot(g, target=ax, layout=layout, **visual_style)
return ax
def plot_graph(graph,
ax=None,
layout='auto',
figsize=(5, 5),
save=None,
show_vertex_names=True,
vertex_color_normal='white',
vertex_color_clifford='orange',
vertices_to_highlight=None,
vertex_color_highlight='purple',
edge_color_normal='black',
edge_color_fusion='red',
edge_style_fusion='--',
**kwargs):
"""
Plot a graph or an unraveled graph.
See the description of `optgraphstate.GraphState.plot_graph()` for details.
Parameters
----------
graph : igraph.Graph
Graph or unraveled graph to plot.
Returns
-------
fig, ax : matplotlib Figure and Axes object.
"""
if ax is None:
fig, ax = plt.subplots(figsize=figsize)
if not isinstance(graph, ig.Graph):
raise TypeError("Parameter 'graph' is not ig.Graph.")
unraveled = 'ext_fusion' in graph.vs.attributes()
clifford_exists = 'clifford' in graph.vs.attributes()
if vertices_to_highlight is None:
vertices_to_highlight = []
vertices_to_highlight = [str(vname) for vname in vertices_to_highlight]
vertex_colors = []
for v in graph.vs:
if v['name'] in vertices_to_highlight:
color = vertex_color_highlight
elif clifford_exists and v['clifford'] is not None:
color = vertex_color_clifford
else:
color = vertex_color_normal
vertex_colors.append(color)
if unraveled:
graph = graph.copy()
org_ecount = graph.ecount()
done = set()
vs_with_ext_fusion = graph.vs.select(ext_fusion_ne=None)
for v in vs_with_ext_fusion:
if v['name'] not in done:
vname_fusion = v['ext_fusion']
graph.add_edge(v, vname_fusion)
done.add(vname_fusion)
visual_style = {
'vertex_color': vertex_colors,
'edge_color': [edge_color_normal] * org_ecount + [
edge_color_fusion] * round(len(vs_with_ext_fusion) / 2), }
if show_vertex_names:
visual_style['vertex_label'] = graph.vs['name']
visual_style.update(kwargs)
_plot_base(graph, ax=ax, layout=layout, **visual_style)
children = ax.get_children()
ecount = graph.ecount()
lines = [child for child in children if isinstance(child, PathPatch)]
assert len(lines) == ecount
for eid in range(org_ecount, ecount):
lines[eid].set(linestyle=edge_style_fusion)
else:
graph = graph
visual_style = {
'vertex_color': vertex_colors,
'edge_color': edge_color_normal
}
if show_vertex_names:
visual_style['vertex_label'] = graph.vs['name']
visual_style.update(kwargs)
_plot_base(graph, ax=ax, layout=layout, **visual_style)
plt.tight_layout()
if save is not None:
plt.savefig(save, transparent=True)
return fig, ax
def plot_fusion_network(network,
ax=None,
layout='auto',
figsize=(5, 5),
save=None,
show_only_structure=False,
show_node_names=True,
node_color='white',
show_link_names=False,
show_fusion_orders=True,
show_link_cliffords=True,
link_color_ll='black',
link_color_rl='blue',
link_color_rr='red',
arrow_size=0.02,
**kwargs):
"""
Plot a fusion network.
See the description of `optgraphstate.GraphState.plot_fusion_network()`
for details.
Parameters
----------
network : igraph.Graph
Fusion network to plot.
Returns
-------
fig, ax : matplotlib Figure and Axes object.
"""
if ax is None:
fig, ax = plt.subplots(figsize=figsize)
if isinstance(network, dict):
network = network['fusion_network']
if not isinstance(network, ig.Graph):
raise TypeError("Parameter 'network' is not ig.Graph.")
if show_only_structure:
show_node_names = False
show_link_names = False
show_fusion_orders = False
show_link_cliffords = False
# show_vertex_overhead = show_vertex_overhead and 'overhead' in
# network.vs.attributes()
# show_edge_overhead = show_edge_overhead and 'overhead' in
# network.es.attributes()
show_fusion_orders = show_fusion_orders and 'order' in network.es.attributes()
rl_exists = 'RL' in network.es['kind']
if rl_exists:
network_directed = network.copy()
network_directed.to_directed()
es_to_delete = []
for edge in network.es:
v1, v2 = edge.source_vertex, edge.target_vertex
vname1, vname2 = v1['name'], v2['name']
if edge['kind'] == 'RL':
root_node = edge['root_node']
e_to_delete = (vname2, vname1) if root_node == vname2 \
else (vname1, vname2)
else:
e_to_delete = (vname2, vname1)
es_to_delete.append(e_to_delete)
network_directed.delete_edges(es_to_delete)
network = network_directed
link_color_dict = {
'RR': link_color_rr,
'RL': link_color_rl,
'LL': link_color_ll
}
# cliffords = [
# v['clifford_root'] is not None or v['clifford_leaves'] is not None for
# v in network.vs]
# if show_vertex_overhead:
# vertex_label = []
# for v in network.vs:
# name = v['name']
# overhead = v['overhead']
# if abs(overhead % 1) < 1e-6:
# overhead = round(overhead)
# vertex_label.append(f'{name}:{overhead}')
# else:
visual_style = {
# 'vertex_color': [node_color_clifford if clifford else node_color
# for clifford in cliffords],
'vertex_color': node_color,
# 'vertex_shape': ['square' if clifford else 'circle' for clifford in
# cliffords],
'edge_align_label': False,
'edge_color': [link_color_dict[kind] for kind in network.es['kind']],
}
if show_node_names:
visual_style['vertex_label'] \
= network.vs['name'] if network.vcount() else []
if rl_exists:
visual_style['vertex_size'] = 0.4
visual_style['edge_arrow_size'] = [
arrow_size if e['kind'] == 'RL' else 0 for
e in network.es]
# visual_style['edge_color'] = [edge_color_dict[e['kind']] for e in
# network.es]
if network.ecount() and (show_fusion_orders or show_link_names):
visual_style['edge_background'] = 'white'
if sum([show_fusion_orders, show_link_names]) == 1:
if show_fusion_orders:
key = 'order'
# elif show_edge_overhead:
# key = 'overhead'
else:
key = 'name'
edge_label = network.es[key]
else:
edge_label = []
for e in network.es:
# label = []
# if show_edge_labels:
# label.append(f"{e['name']}")
# if show_fusion_order:
# label.append(f"{e['order']}")
# if show_edge_overhead:
# overhead = e['overhead']
# if abs(overhead % 1) < 1e-6:
# overhead = round(overhead)
# label.append(f"W{overhead}")
# label = '_'.join(label)
label = f"{e['name']}-{e['order']}"
edge_label.append(label)
if show_link_cliffords:
for link in network.es.select(cliffords_ne={}):
eid = link.index
edge_label[eid] = str(edge_label[eid]) + 'C'
visual_style['edge_label'] = edge_label
visual_style.update(kwargs)
_plot_base(network, ax=ax, layout=layout, **visual_style)
if network.ecount():
children = ax.get_children()
lines = [child for child in children if isinstance(child, PathPatch)]
edge_style = {
'RR': '--',
'RL': '-',
'LL': '-'
}
for eid, line in enumerate(lines):
link = network.es[eid]
line.set(linestyle=edge_style[link['kind']])
plt.tight_layout()
if save is not None:
plt.savefig(save, transparent=True)
return fig, ax
Functions
def plot_fusion_network(network, ax=None, layout='auto', figsize=(5, 5), save=None, show_only_structure=False, show_node_names=True, node_color='white', show_link_names=False, show_fusion_orders=True, show_link_cliffords=True, link_color_ll='black', link_color_rl='blue', link_color_rr='red', arrow_size=0.02, **kwargs)
-
Plot a fusion network.
See the description of
GraphState.plot_fusion_network()
for details.Parameters
network
:igraph.Graph
- Fusion network to plot.
Returns
fig, ax : matplotlib Figure and Axes object.
Expand source code
def plot_fusion_network(network, ax=None, layout='auto', figsize=(5, 5), save=None, show_only_structure=False, show_node_names=True, node_color='white', show_link_names=False, show_fusion_orders=True, show_link_cliffords=True, link_color_ll='black', link_color_rl='blue', link_color_rr='red', arrow_size=0.02, **kwargs): """ Plot a fusion network. See the description of `optgraphstate.GraphState.plot_fusion_network()` for details. Parameters ---------- network : igraph.Graph Fusion network to plot. Returns ------- fig, ax : matplotlib Figure and Axes object. """ if ax is None: fig, ax = plt.subplots(figsize=figsize) if isinstance(network, dict): network = network['fusion_network'] if not isinstance(network, ig.Graph): raise TypeError("Parameter 'network' is not ig.Graph.") if show_only_structure: show_node_names = False show_link_names = False show_fusion_orders = False show_link_cliffords = False # show_vertex_overhead = show_vertex_overhead and 'overhead' in # network.vs.attributes() # show_edge_overhead = show_edge_overhead and 'overhead' in # network.es.attributes() show_fusion_orders = show_fusion_orders and 'order' in network.es.attributes() rl_exists = 'RL' in network.es['kind'] if rl_exists: network_directed = network.copy() network_directed.to_directed() es_to_delete = [] for edge in network.es: v1, v2 = edge.source_vertex, edge.target_vertex vname1, vname2 = v1['name'], v2['name'] if edge['kind'] == 'RL': root_node = edge['root_node'] e_to_delete = (vname2, vname1) if root_node == vname2 \ else (vname1, vname2) else: e_to_delete = (vname2, vname1) es_to_delete.append(e_to_delete) network_directed.delete_edges(es_to_delete) network = network_directed link_color_dict = { 'RR': link_color_rr, 'RL': link_color_rl, 'LL': link_color_ll } # cliffords = [ # v['clifford_root'] is not None or v['clifford_leaves'] is not None for # v in network.vs] # if show_vertex_overhead: # vertex_label = [] # for v in network.vs: # name = v['name'] # overhead = v['overhead'] # if abs(overhead % 1) < 1e-6: # overhead = round(overhead) # vertex_label.append(f'{name}:{overhead}') # else: visual_style = { # 'vertex_color': [node_color_clifford if clifford else node_color # for clifford in cliffords], 'vertex_color': node_color, # 'vertex_shape': ['square' if clifford else 'circle' for clifford in # cliffords], 'edge_align_label': False, 'edge_color': [link_color_dict[kind] for kind in network.es['kind']], } if show_node_names: visual_style['vertex_label'] \ = network.vs['name'] if network.vcount() else [] if rl_exists: visual_style['vertex_size'] = 0.4 visual_style['edge_arrow_size'] = [ arrow_size if e['kind'] == 'RL' else 0 for e in network.es] # visual_style['edge_color'] = [edge_color_dict[e['kind']] for e in # network.es] if network.ecount() and (show_fusion_orders or show_link_names): visual_style['edge_background'] = 'white' if sum([show_fusion_orders, show_link_names]) == 1: if show_fusion_orders: key = 'order' # elif show_edge_overhead: # key = 'overhead' else: key = 'name' edge_label = network.es[key] else: edge_label = [] for e in network.es: # label = [] # if show_edge_labels: # label.append(f"{e['name']}") # if show_fusion_order: # label.append(f"{e['order']}") # if show_edge_overhead: # overhead = e['overhead'] # if abs(overhead % 1) < 1e-6: # overhead = round(overhead) # label.append(f"W{overhead}") # label = '_'.join(label) label = f"{e['name']}-{e['order']}" edge_label.append(label) if show_link_cliffords: for link in network.es.select(cliffords_ne={}): eid = link.index edge_label[eid] = str(edge_label[eid]) + 'C' visual_style['edge_label'] = edge_label visual_style.update(kwargs) _plot_base(network, ax=ax, layout=layout, **visual_style) if network.ecount(): children = ax.get_children() lines = [child for child in children if isinstance(child, PathPatch)] edge_style = { 'RR': '--', 'RL': '-', 'LL': '-' } for eid, line in enumerate(lines): link = network.es[eid] line.set(linestyle=edge_style[link['kind']]) plt.tight_layout() if save is not None: plt.savefig(save, transparent=True) return fig, ax
def plot_graph(graph, ax=None, layout='auto', figsize=(5, 5), save=None, show_vertex_names=True, vertex_color_normal='white', vertex_color_clifford='orange', vertices_to_highlight=None, vertex_color_highlight='purple', edge_color_normal='black', edge_color_fusion='red', edge_style_fusion='--', **kwargs)
-
Plot a graph or an unraveled graph.
See the description of
GraphState.plot_graph()
for details.Parameters
graph
:igraph.Graph
- Graph or unraveled graph to plot.
Returns
fig, ax : matplotlib Figure and Axes object.
Expand source code
def plot_graph(graph, ax=None, layout='auto', figsize=(5, 5), save=None, show_vertex_names=True, vertex_color_normal='white', vertex_color_clifford='orange', vertices_to_highlight=None, vertex_color_highlight='purple', edge_color_normal='black', edge_color_fusion='red', edge_style_fusion='--', **kwargs): """ Plot a graph or an unraveled graph. See the description of `optgraphstate.GraphState.plot_graph()` for details. Parameters ---------- graph : igraph.Graph Graph or unraveled graph to plot. Returns ------- fig, ax : matplotlib Figure and Axes object. """ if ax is None: fig, ax = plt.subplots(figsize=figsize) if not isinstance(graph, ig.Graph): raise TypeError("Parameter 'graph' is not ig.Graph.") unraveled = 'ext_fusion' in graph.vs.attributes() clifford_exists = 'clifford' in graph.vs.attributes() if vertices_to_highlight is None: vertices_to_highlight = [] vertices_to_highlight = [str(vname) for vname in vertices_to_highlight] vertex_colors = [] for v in graph.vs: if v['name'] in vertices_to_highlight: color = vertex_color_highlight elif clifford_exists and v['clifford'] is not None: color = vertex_color_clifford else: color = vertex_color_normal vertex_colors.append(color) if unraveled: graph = graph.copy() org_ecount = graph.ecount() done = set() vs_with_ext_fusion = graph.vs.select(ext_fusion_ne=None) for v in vs_with_ext_fusion: if v['name'] not in done: vname_fusion = v['ext_fusion'] graph.add_edge(v, vname_fusion) done.add(vname_fusion) visual_style = { 'vertex_color': vertex_colors, 'edge_color': [edge_color_normal] * org_ecount + [ edge_color_fusion] * round(len(vs_with_ext_fusion) / 2), } if show_vertex_names: visual_style['vertex_label'] = graph.vs['name'] visual_style.update(kwargs) _plot_base(graph, ax=ax, layout=layout, **visual_style) children = ax.get_children() ecount = graph.ecount() lines = [child for child in children if isinstance(child, PathPatch)] assert len(lines) == ecount for eid in range(org_ecount, ecount): lines[eid].set(linestyle=edge_style_fusion) else: graph = graph visual_style = { 'vertex_color': vertex_colors, 'edge_color': edge_color_normal } if show_vertex_names: visual_style['vertex_label'] = graph.vs['name'] visual_style.update(kwargs) _plot_base(graph, ax=ax, layout=layout, **visual_style) plt.tight_layout() if save is not None: plt.savefig(save, transparent=True) return fig, ax