0
# Visualization
1
2
Multi-backend visualization system supporting Cairo, matplotlib, and plotly for creating publication-quality graph visualizations. igraph provides extensive customization options for colors, shapes, sizes, and styling.
3
4
## Capabilities
5
6
### Basic Plotting
7
8
Core plotting functionality with the main plot function that automatically selects appropriate backends.
9
10
```python { .api }
11
def plot(obj, target=None, bbox=(0,0,600,600), **kwds):
12
"""
13
Main plotting function for graphs and other objects.
14
15
Parameters:
16
- obj: Graph, Layout, Clustering, etc. - object to plot
17
- target: str/file, output target (filename, file object, or None for display)
18
- bbox: tuple, bounding box (left, top, right, bottom) or BoundingBox
19
- **kwds: keyword arguments for styling and layout
20
21
Common styling parameters:
22
- layout: Layout object or string (algorithm name)
23
- vertex_size: int/list, vertex sizes
24
- vertex_color: color/list, vertex colors
25
- vertex_label: str/list, vertex labels
26
- edge_width: float/list, edge widths
27
- edge_color: color/list, edge colors
28
- margin: int/tuple, plot margins
29
30
Returns:
31
Plot object (backend-dependent)
32
"""
33
```
34
35
**Usage Examples:**
36
37
```python
38
import igraph as ig
39
40
# Create sample graph
41
g = ig.Graph.Famous("Zachary") # Karate club network
42
layout = g.layout_fruchterman_reingold()
43
44
# Basic plot
45
ig.plot(g, layout=layout)
46
47
# Save to file
48
ig.plot(g, "karate_club.png", layout=layout, bbox=(800, 600))
49
50
# With styling
51
ig.plot(g,
52
layout=layout,
53
vertex_size=20,
54
vertex_color="lightblue",
55
vertex_label=g.vs.indices,
56
edge_width=2,
57
margin=50)
58
59
# Color by community
60
communities = g.community_leiden()
61
colors = ["red", "blue", "green", "yellow", "purple"]
62
vertex_colors = [colors[i % len(colors)] for i in communities.membership]
63
64
ig.plot(g,
65
layout=layout,
66
vertex_color=vertex_colors,
67
vertex_size=25,
68
vertex_frame_width=0,
69
edge_width=0.5,
70
bbox=(800, 600),
71
margin=30)
72
```
73
74
### Plot Objects and Backends
75
76
Work directly with plot objects for fine-grained control and multi-step plotting.
77
78
```python { .api }
79
class Plot:
80
def __init__(self, bbox=(0,0,600,600), palette=None):
81
"""
82
Create plot object.
83
84
Parameters:
85
- bbox: BoundingBox or tuple, plotting area
86
- palette: Palette, color palette for automatic coloring
87
"""
88
89
def add(self, obj, **kwds):
90
"""
91
Add object to plot.
92
93
Parameters:
94
- obj: object to add (Graph, Layout, etc.)
95
- **kwds: styling parameters
96
97
Returns:
98
None
99
"""
100
101
def save(self, fname=None):
102
"""
103
Save plot to file.
104
105
Parameters:
106
- fname: str, filename (extension determines format)
107
108
Returns:
109
None
110
"""
111
112
def show(self):
113
"""
114
Display plot in interactive window or notebook.
115
116
Returns:
117
None
118
"""
119
120
# Backend-specific classes
121
class CairoGraphDrawer:
122
"""Cairo-based graph drawing backend."""
123
124
class MatplotlibGraphDrawer:
125
"""Matplotlib-based graph drawing backend."""
126
127
class PlotlyGraphDrawer:
128
"""Plotly-based graph drawing backend."""
129
```
130
131
**Usage Examples:**
132
133
```python
134
from igraph.drawing import Plot, BoundingBox
135
from igraph.drawing.colors import RainbowPalette
136
137
# Create plot object
138
plot = Plot(bbox=BoundingBox(800, 600), palette=RainbowPalette())
139
140
# Add graph with custom styling
141
plot.add(g,
142
layout=layout,
143
vertex_size=g.degree(), # Size by degree
144
vertex_color=communities.membership,
145
vertex_label=[f"v{i}" for i in range(g.vcount())],
146
edge_width=[1 + w*2 for w in g.es["weight"]] if "weight" in g.es.attributes() else 1)
147
148
# Save in different formats
149
plot.save("network.png")
150
plot.save("network.pdf")
151
plot.save("network.svg")
152
153
# Display interactively
154
plot.show()
155
```
156
157
### Color Systems and Palettes
158
159
Comprehensive color management with multiple palette types and color space conversions.
160
161
```python { .api }
162
class Palette:
163
def get(self, index):
164
"""
165
Get color at index.
166
167
Parameters:
168
- index: int, color index
169
170
Returns:
171
Color, RGBA color tuple
172
"""
173
174
class GradientPalette(Palette):
175
def __init__(self, start_color, end_color, n=256):
176
"""
177
Gradient between two colors.
178
179
Parameters:
180
- start_color: color specification
181
- end_color: color specification
182
- n: int, number of gradient steps
183
"""
184
185
class RainbowPalette(Palette):
186
def __init__(self, n=256, start=0, end=None):
187
"""
188
HSV rainbow palette.
189
190
Parameters:
191
- n: int, number of colors
192
- start: float, starting hue (0-1)
193
- end: float, ending hue
194
"""
195
196
class ClusterColoringPalette(Palette):
197
def __init__(self, n):
198
"""
199
Palette optimized for distinguishable cluster colors.
200
201
Parameters:
202
- n: int, number of clusters
203
"""
204
205
# Color conversion functions
206
def color_name_to_rgb(color): ...
207
def hsv_to_rgb(h, s, v): ...
208
def hsl_to_rgb(h, s, l): ...
209
def rgb_to_hsv(r, g, b): ...
210
```
211
212
**Usage Examples:**
213
214
```python
215
from igraph.drawing.colors import (
216
GradientPalette, RainbowPalette, ClusterColoringPalette,
217
color_name_to_rgb, hsv_to_rgb
218
)
219
220
# Gradient palette for vertex values
221
values = g.betweenness()
222
max_val = max(values)
223
gradient = GradientPalette("white", "red", n=100)
224
vertex_colors = [gradient.get(int(v/max_val * 99)) for v in values]
225
226
# Rainbow palette for communities
227
n_communities = len(set(communities.membership))
228
rainbow = RainbowPalette(n_communities)
229
community_colors = [rainbow.get(i) for i in communities.membership]
230
231
# Cluster-optimized palette
232
cluster_palette = ClusterColoringPalette(n_communities)
233
optimal_colors = [cluster_palette.get(i) for i in communities.membership]
234
235
# Color conversions
236
red_rgb = color_name_to_rgb("red")
237
custom_hsv = hsv_to_rgb(0.3, 0.8, 1.0) # Green-ish
238
239
# Plot with different color schemes
240
ig.plot(g, layout=layout, vertex_color=vertex_colors,
241
vertex_size=20, bbox=(800, 600))
242
```
243
244
### Advanced Styling Options
245
246
Comprehensive styling system for vertices, edges, and overall plot appearance.
247
248
```python { .api }
249
# Vertex styling parameters
250
vertex_styling = {
251
"vertex_size": "int/list - vertex sizes",
252
"vertex_color": "color/list - fill colors",
253
"vertex_frame_color": "color/list - border colors",
254
"vertex_frame_width": "float/list - border widths",
255
"vertex_shape": "str/list - shapes ('circle', 'square', 'triangle-up', etc.)",
256
"vertex_label": "str/list - text labels",
257
"vertex_label_size": "int/list - label font sizes",
258
"vertex_label_color": "color/list - label colors",
259
"vertex_label_family": "str - font family",
260
"vertex_label_angle": "float/list - label rotation angles",
261
"vertex_label_dist": "float/list - distance from vertex center",
262
"vertex_order": "list - drawing order",
263
}
264
265
# Edge styling parameters
266
edge_styling = {
267
"edge_width": "float/list - edge widths",
268
"edge_color": "color/list - edge colors",
269
"edge_curved": "bool/float/list - curvature (0=straight, 1=curved)",
270
"edge_arrow_size": "float/list - arrow head sizes",
271
"edge_arrow_width": "float/list - arrow head widths",
272
"edge_label": "str/list - edge labels",
273
"edge_label_size": "int/list - label font sizes",
274
"edge_label_color": "color/list - label colors",
275
"edge_loop_size": "float/list - self-loop sizes",
276
}
277
278
# Plot-level styling
279
plot_styling = {
280
"layout": "Layout/str - vertex positions or algorithm name",
281
"margin": "int/tuple - plot margins",
282
"bbox": "BoundingBox/tuple - plotting area",
283
"background": "color - background color",
284
"palette": "Palette - automatic color palette",
285
}
286
```
287
288
**Usage Examples:**
289
290
```python
291
# Advanced vertex styling
292
vertex_degrees = g.degree()
293
max_degree = max(vertex_degrees)
294
295
ig.plot(g,
296
layout=layout,
297
# Vertex appearance
298
vertex_size=[10 + d*2 for d in vertex_degrees], # Size by degree
299
vertex_color=communities.membership,
300
vertex_frame_color="black",
301
vertex_frame_width=1.5,
302
vertex_shape="circle",
303
# Vertex labels
304
vertex_label=g.vs.indices,
305
vertex_label_size=10,
306
vertex_label_color="white",
307
vertex_label_dist=0,
308
# Edge appearance
309
edge_width=0.8,
310
edge_color="gray",
311
edge_curved=0.1,
312
edge_arrow_size=1.0,
313
# Plot settings
314
margin=40,
315
background="white",
316
bbox=(1000, 800))
317
318
# Conditional styling based on properties
319
def style_by_centrality(graph, centrality_values):
320
"""Style vertices based on centrality scores."""
321
max_cent = max(centrality_values)
322
323
return {
324
'vertex_size': [5 + c/max_cent * 25 for c in centrality_values],
325
'vertex_color': ["red" if c > max_cent*0.7 else "lightblue" for c in centrality_values],
326
'vertex_frame_width': [3 if c > max_cent*0.7 else 1 for c in centrality_values]
327
}
328
329
betweenness = g.betweenness()
330
styling = style_by_centrality(g, betweenness)
331
ig.plot(g, layout=layout, **styling)
332
```
333
334
### Interactive and Web-based Visualization
335
336
Plotly backend for interactive visualizations suitable for web applications and notebooks.
337
338
```python { .api }
339
# Plotly-specific plotting
340
def plot_plotly(graph, layout=None, **kwargs):
341
"""
342
Create interactive plotly visualization.
343
344
Parameters:
345
- graph: Graph object
346
- layout: Layout object or algorithm name
347
- **kwargs: plotly-specific styling options
348
349
Returns:
350
Plotly Figure object
351
"""
352
```
353
354
**Usage Examples:**
355
356
```python
357
# Interactive plotting with plotly (if available)
358
try:
359
import plotly.graph_objects as go
360
from igraph.drawing.plotly import plot as plot_plotly
361
362
# Create interactive plot
363
fig = plot_plotly(g,
364
layout=layout,
365
vertex_size=vertex_degrees,
366
vertex_color=communities.membership,
367
vertex_text=[f"Vertex {i}" for i in range(g.vcount())],
368
edge_width=1)
369
370
# Customize interactivity
371
fig.update_layout(
372
title="Interactive Network Visualization",
373
showlegend=False,
374
hovermode='closest',
375
width=800,
376
height=600
377
)
378
379
# Display in notebook or save as HTML
380
fig.show()
381
fig.write_html("interactive_network.html")
382
383
except ImportError:
384
print("Plotly not available, using Cairo backend")
385
ig.plot(g, layout=layout, bbox=(800, 600))
386
```
387
388
### Matplotlib Integration
389
390
Use matplotlib backend for integration with scientific plotting workflows.
391
392
```python { .api }
393
# Matplotlib-specific functionality
394
class MatplotlibGraphDrawer:
395
def __init__(self, context):
396
"""Initialize matplotlib drawer with axis context."""
397
398
def draw(self, graph, **kwargs):
399
"""Draw graph on matplotlib axis."""
400
```
401
402
**Usage Examples:**
403
404
```python
405
# Matplotlib integration
406
try:
407
import matplotlib.pyplot as plt
408
from igraph.drawing.matplotlib import MatplotlibGraphDrawer
409
410
# Create subplot layout
411
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
412
413
# Plot original graph
414
ax1.set_title("Original Network")
415
drawer1 = MatplotlibGraphDrawer(ax1)
416
drawer1.draw(g,
417
layout=layout,
418
vertex_size=vertex_degrees,
419
vertex_color=communities.membership)
420
421
# Plot simplified version
422
g_simple = g.simplify()
423
ax2.set_title("Simplified Network")
424
drawer2 = MatplotlibGraphDrawer(ax2)
425
drawer2.draw(g_simple,
426
layout=g_simple.layout_fruchterman_reingold(),
427
vertex_size=20,
428
vertex_color="lightblue")
429
430
plt.tight_layout()
431
plt.savefig("network_comparison.png", dpi=300, bbox_inches='tight')
432
plt.show()
433
434
except ImportError:
435
print("Matplotlib not available")
436
```
437
438
### Specialized Visualizations
439
440
Custom visualization types for specific analysis needs.
441
442
**Usage Examples:**
443
444
```python
445
# Adjacency matrix visualization
446
adj_matrix = g.get_adjacency_sparse()
447
ig.plot(adj_matrix, "adjacency_matrix.png")
448
449
# Community structure visualization
450
def plot_community_structure(graph, communities):
451
"""Enhanced community visualization."""
452
# Create color map for communities
453
n_communities = len(communities)
454
colors = ig.RainbowPalette(n_communities)
455
456
# Size vertices by within-community degree
457
within_degrees = []
458
for v in graph.vs:
459
v_community = communities.membership[v.index]
460
community_vertices = [i for i, c in enumerate(communities.membership) if c == v_community]
461
subgraph = graph.subgraph(community_vertices)
462
within_degrees.append(subgraph.degree()[community_vertices.index(v.index)])
463
464
return ig.plot(graph,
465
layout=graph.layout_fruchterman_reingold(),
466
vertex_color=[colors.get(c) for c in communities.membership],
467
vertex_size=[5 + d*3 for d in within_degrees],
468
vertex_frame_color="black",
469
vertex_frame_width=1,
470
edge_width=0.5,
471
edge_color="gray",
472
bbox=(1000, 800),
473
margin=50)
474
475
# Edge bundling visualization
476
def plot_with_edge_bundling(graph, layout, bundle_strength=0.8):
477
"""Simulate edge bundling effect."""
478
# Calculate edge curvature based on community crossing
479
communities = graph.community_leiden()
480
edge_curved = []
481
482
for edge in graph.es:
483
source_comm = communities.membership[edge.source]
484
target_comm = communities.membership[edge.target]
485
# More curvature for inter-community edges
486
curvature = bundle_strength if source_comm != target_comm else 0.1
487
edge_curved.append(curvature)
488
489
return ig.plot(graph,
490
layout=layout,
491
vertex_color=communities.membership,
492
edge_curved=edge_curved,
493
edge_color=["red" if c > 0.5 else "lightgray" for c in edge_curved],
494
bbox=(800, 600))
495
496
# Multi-layer network visualization
497
def plot_multilayer(graphs, layouts=None, titles=None):
498
"""Plot multiple related graphs."""
499
n_graphs = len(graphs)
500
501
if layouts is None:
502
layouts = [g.layout_fruchterman_reingold() for g in graphs]
503
if titles is None:
504
titles = [f"Layer {i+1}" for i in range(n_graphs)]
505
506
# Create grid layout for multiple plots
507
import math
508
cols = math.ceil(math.sqrt(n_graphs))
509
rows = math.ceil(n_graphs / cols)
510
511
for i, (graph, layout, title) in enumerate(zip(graphs, layouts, titles)):
512
ig.plot(graph,
513
f"layer_{i+1}.png",
514
layout=layout,
515
vertex_size=15,
516
vertex_color="lightblue",
517
bbox=(400, 400),
518
margin=30)
519
520
# Usage
521
plot_community_structure(g, communities)
522
plot_with_edge_bundling(g, layout)
523
```