or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

algorithms.mdconversion.mddrawing.mdgenerators.mdgraph-classes.mdgraph-io.mdindex.mdlinear-algebra.md

drawing.mddocs/

0

# Graph Drawing and Visualization

1

2

Graph layout algorithms and drawing functions with matplotlib integration for visualizing networks. NetworkX provides comprehensive visualization capabilities for exploring graph structure and properties.

3

4

## Capabilities

5

6

### Core Drawing Functions

7

8

Basic drawing functions using matplotlib for graph visualization.

9

10

```python { .api }

11

def draw(G, pos=None, ax=None, **kwds):

12

"""

13

Draw graph with matplotlib.

14

15

Parameters:

16

- G: NetworkX graph

17

- pos: Dictionary of node positions (computed if None)

18

- ax: Matplotlib axis object

19

- **kwds: Keyword arguments for customization (node_color, edge_color, etc.)

20

21

Returns:

22

None (draws to current matplotlib axis)

23

"""

24

25

def draw_networkx(G, pos=None, arrows=None, with_labels=True, **kwds):

26

"""Draw graph with node and edge labels."""

27

28

def draw_networkx_nodes(G, pos, nodelist=None, node_size=300, node_color='#1f78b4', node_shape='o', alpha=None, cmap=None, vmin=None, vmax=None, ax=None, linewidths=None, edgecolors=None, label=None, margins=None):

29

"""Draw graph nodes."""

30

31

def draw_networkx_edges(G, pos, edgelist=None, width=1.0, edge_color='k', style='solid', alpha=None, arrowstyle=None, arrowsize=10, edge_cmap=None, edge_vmin=None, edge_vmax=None, ax=None, arrows=None, label=None, node_size=300, nodelist=None, node_shape='o', connectionstyle='arc3', min_source_margin=0, min_target_margin=0):

32

"""Draw graph edges."""

33

34

def draw_networkx_labels(G, pos, labels=None, font_size=12, font_color='k', font_family='sans-serif', font_weight='normal', alpha=None, bbox=None, horizontalalignment='center', verticalalignment='center', ax=None, clip_on=True):

35

"""Draw node labels."""

36

37

def draw_networkx_edge_labels(G, pos, edge_labels=None, label_pos=0.5, font_size=10, font_color='k', font_family='sans-serif', font_weight='normal', alpha=None, bbox=None, horizontalalignment='center', verticalalignment='center', ax=None, rotate=True, clip_on=True):

38

"""Draw edge labels."""

39

```

40

41

### Layout Algorithms

42

43

Algorithms for computing node positions for graph visualization.

44

45

```python { .api }

46

def spring_layout(G, k=None, pos=None, fixed=None, iterations=50, threshold=1e-4, weight='weight', scale=1, center=None, dim=2, seed=None):

47

"""

48

Position nodes using Fruchterman-Reingold force-directed algorithm.

49

50

Parameters:

51

- G: NetworkX graph

52

- k: Optimal distance parameter

53

- pos: Initial positions dictionary

54

- fixed: Nodes to keep fixed at initial positions

55

- iterations: Maximum number of iterations

56

- threshold: Convergence threshold

57

- weight: Edge data key for forces

58

- scale: Scale factor for positions

59

- center: Coordinate pair for center of layout

60

- dim: Dimension of layout (2 or 3)

61

- seed: Random seed

62

63

Returns:

64

Dictionary of node positions

65

"""

66

67

def kamada_kawai_layout(G, dist=None, pos=None, weight='weight', scale=1, center=None, dim=2):

68

"""Position nodes using Kamada-Kawai path-length cost-function."""

69

70

def circular_layout(G, scale=1, center=None, dim=2):

71

"""Position nodes on a circle."""

72

73

def random_layout(G, center=None, dim=2, seed=None):

74

"""Position nodes uniformly at random."""

75

76

def shell_layout(G, nlist=None, rotate=None, scale=1, center=None, dim=2):

77

"""Position nodes in concentric circles."""

78

79

def spectral_layout(G, weight='weight', scale=1, center=None, dim=2):

80

"""Position nodes using eigenvectors of graph Laplacian."""

81

82

def planar_layout(G, scale=1, center=None, dim=2):

83

"""Position nodes for planar graphs using Schnyder's algorithm."""

84

85

def spiral_layout(G, scale=1, center=None, dim=2, resolution=0.35, equidistant=False):

86

"""Position nodes in a spiral layout."""

87

88

def multipartite_layout(G, subset_key='subset', align='vertical', scale=1, center=None):

89

"""Position nodes in layers for multipartite graphs."""

90

91

def bipartite_layout(G, nodes, align='horizontal', scale=1, center=None, aspect_ratio=4/3):

92

"""Position nodes for bipartite graphs in two layers."""

93

```

94

95

### Specialized Drawing Functions

96

97

Drawing functions for specific layout algorithms.

98

99

```python { .api }

100

def draw_circular(G, **kwds):

101

"""Draw graph with circular layout."""

102

103

def draw_kamada_kawai(G, **kwds):

104

"""Draw graph with Kamada-Kawai layout."""

105

106

def draw_random(G, **kwds):

107

"""Draw graph with random layout."""

108

109

def draw_spectral(G, **kwds):

110

"""Draw graph with spectral layout."""

111

112

def draw_spring(G, **kwds):

113

"""Draw graph with spring layout."""

114

115

def draw_planar(G, **kwds):

116

"""Draw graph with planar layout."""

117

118

def draw_shell(G, **kwds):

119

"""Draw graph with shell layout."""

120

```

121

122

### Layout Utilities

123

124

Helper functions for working with graph layouts.

125

126

```python { .api }

127

def rescale_layout(pos, scale=1):

128

"""

129

Rescale layout coordinates.

130

131

Parameters:

132

- pos: Dictionary of node positions

133

- scale: Scale factor

134

135

Returns:

136

Dictionary of rescaled positions

137

"""

138

139

def rescale_layout_dict(pos, scale=1):

140

"""Rescale layout with proper handling of dict format."""

141

```

142

143

### PyGraphviz Integration

144

145

Interface with Graphviz layout engines (requires pygraphviz).

146

147

```python { .api }

148

def graphviz_layout(G, prog='neato', root=None, args=''):

149

"""

150

Create layout using Graphviz layout programs.

151

152

Parameters:

153

- G: NetworkX graph

154

- prog: Graphviz layout program ('dot', 'neato', 'fdp', 'sfdp', 'twopi', 'circo')

155

- root: Root node for directed layouts

156

- args: Additional arguments to layout program

157

158

Returns:

159

Dictionary of node positions

160

"""

161

162

def pygraphviz_layout(G, prog='neato', root=None, args=''):

163

"""Alias for graphviz_layout."""

164

165

def to_agraph(N):

166

"""Convert NetworkX graph to PyGraphviz AGraph."""

167

168

def from_agraph(A, create_using=None):

169

"""Convert PyGraphviz AGraph to NetworkX graph."""

170

171

def write_dot(G, path):

172

"""Write graph in DOT format using PyGraphviz."""

173

174

def read_dot(path):

175

"""Read graph from DOT file using PyGraphviz."""

176

177

def view_pygraphviz(G, edgelabel=None, prog='dot', args='', suffix='', path=None):

178

"""View graph using PyGraphviz and system viewer."""

179

```

180

181

### Pydot Integration

182

183

Alternative interface with Graphviz using pydot library.

184

185

```python { .api }

186

def pydot_layout(G, prog='neato', root=None, **kwds):

187

"""Create layout using pydot and Graphviz."""

188

189

def to_pydot(N):

190

"""Convert NetworkX graph to pydot graph."""

191

192

def from_pydot(P):

193

"""Convert pydot graph to NetworkX graph."""

194

```

195

196

## Usage Examples

197

198

### Basic Graph Drawing

199

200

```python

201

import networkx as nx

202

import matplotlib.pyplot as plt

203

204

# Create sample graphs

205

G1 = nx.complete_graph(6)

206

G2 = nx.cycle_graph(8)

207

G3 = nx.star_graph(7)

208

G4 = nx.wheel_graph(8)

209

210

# Create subplot for multiple graphs

211

fig, axes = plt.subplots(2, 2, figsize=(12, 10))

212

213

# Draw graphs with different layouts

214

nx.draw(G1, ax=axes[0,0], with_labels=True, node_color='lightblue',

215

node_size=500, font_size=12, font_weight='bold')

216

axes[0,0].set_title("Complete Graph K6")

217

218

nx.draw_circular(G2, ax=axes[0,1], with_labels=True, node_color='lightgreen',

219

node_size=500, font_size=12, font_weight='bold')

220

axes[0,1].set_title("Cycle Graph C8")

221

222

nx.draw(G3, ax=axes[1,0], with_labels=True, node_color='lightcoral',

223

node_size=500, font_size=12, font_weight='bold')

224

axes[1,0].set_title("Star Graph S7")

225

226

nx.draw_circular(G4, ax=axes[1,1], with_labels=True, node_color='lightyellow',

227

node_size=500, font_size=12, font_weight='bold')

228

axes[1,1].set_title("Wheel Graph W8")

229

230

plt.tight_layout()

231

plt.show()

232

```

233

234

### Customized Graph Visualization

235

236

```python

237

import networkx as nx

238

import matplotlib.pyplot as plt

239

import numpy as np

240

241

# Create graph with attributes

242

G = nx.karate_club_graph()

243

244

# Add attributes for visualization

245

for node in G.nodes():

246

G.nodes[node]['group'] = 'A' if G.degree(node) > 5 else 'B'

247

248

# Compute different layouts

249

layouts = {

250

'Spring': nx.spring_layout(G, seed=42),

251

'Kamada-Kawai': nx.kamada_kawai_layout(G),

252

'Circular': nx.circular_layout(G),

253

'Spectral': nx.spectral_layout(G)

254

}

255

256

# Create visualization

257

fig, axes = plt.subplots(2, 2, figsize=(15, 12))

258

axes = axes.flatten()

259

260

for i, (name, pos) in enumerate(layouts.items()):

261

# Node colors based on group

262

node_colors = ['red' if G.nodes[node]['group'] == 'A' else 'blue'

263

for node in G.nodes()]

264

265

# Node sizes based on degree

266

node_sizes = [G.degree(node) * 50 for node in G.nodes()]

267

268

# Draw graph

269

nx.draw(G, pos=pos, ax=axes[i],

270

node_color=node_colors,

271

node_size=node_sizes,

272

with_labels=True,

273

font_size=8,

274

font_weight='bold',

275

edge_color='gray',

276

alpha=0.7)

277

278

axes[i].set_title(f"{name} Layout")

279

280

plt.tight_layout()

281

plt.show()

282

```

283

284

### Edge and Node Customization

285

286

```python

287

import networkx as nx

288

import matplotlib.pyplot as plt

289

import numpy as np

290

291

# Create weighted graph

292

G = nx.Graph()

293

edges = [(1, 2, 0.8), (2, 3, 0.6), (3, 4, 0.9), (4, 1, 0.7),

294

(1, 3, 0.3), (2, 4, 0.4)]

295

G.add_weighted_edges_from(edges)

296

297

# Position nodes

298

pos = nx.spring_layout(G, seed=42)

299

300

# Get edge weights for visualization

301

edge_weights = [G[u][v]['weight'] for u, v in G.edges()]

302

303

# Create figure

304

plt.figure(figsize=(12, 5))

305

306

# Basic visualization

307

plt.subplot(131)

308

nx.draw(G, pos, with_labels=True, node_color='lightblue',

309

node_size=500, font_size=12, font_weight='bold')

310

plt.title("Basic Graph")

311

312

# Edge width based on weight

313

plt.subplot(132)

314

nx.draw(G, pos, with_labels=True,

315

node_color='lightgreen',

316

node_size=500,

317

edge_color=edge_weights,

318

width=[w*5 for w in edge_weights],

319

edge_cmap=plt.cm.Blues,

320

font_size=12, font_weight='bold')

321

plt.title("Edge Width by Weight")

322

323

# With edge labels

324

plt.subplot(133)

325

nx.draw(G, pos, with_labels=True,

326

node_color='lightcoral',

327

node_size=500,

328

font_size=12, font_weight='bold')

329

330

# Add edge labels

331

edge_labels = {(u, v): f"{d['weight']:.1f}" for u, v, d in G.edges(data=True)}

332

nx.draw_networkx_edge_labels(G, pos, edge_labels, font_size=10)

333

plt.title("With Edge Labels")

334

335

plt.tight_layout()

336

plt.show()

337

```

338

339

### Hierarchical and Bipartite Layouts

340

341

```python

342

import networkx as nx

343

import matplotlib.pyplot as plt

344

345

# Create bipartite graph

346

B = nx.Graph()

347

# Add nodes with bipartite attribute

348

B.add_nodes_from([1, 2, 3, 4], bipartite=0) # Top nodes

349

B.add_nodes_from(['a', 'b', 'c'], bipartite=1) # Bottom nodes

350

# Add edges

351

B.add_edges_from([(1, 'a'), (2, 'a'), (2, 'b'), (3, 'b'), (3, 'c'), (4, 'c')])

352

353

# Create tree

354

T = nx.balanced_tree(2, 3)

355

356

# Create multipartite graph

357

M = nx.Graph()

358

M.add_nodes_from([1, 2, 3], subset=0)

359

M.add_nodes_from([4, 5, 6, 7], subset=1)

360

M.add_nodes_from([8, 9], subset=2)

361

M.add_edges_from([(1, 4), (2, 5), (3, 6), (4, 8), (5, 8), (6, 9), (7, 9)])

362

363

# Create layouts

364

fig, axes = plt.subplots(1, 3, figsize=(15, 5))

365

366

# Bipartite layout

367

top_nodes = {n for n, d in B.nodes(data=True) if d['bipartite'] == 0}

368

pos_bipartite = nx.bipartite_layout(B, top_nodes)

369

nx.draw(B, pos=pos_bipartite, ax=axes[0], with_labels=True,

370

node_color=['lightblue' if n in top_nodes else 'lightcoral' for n in B.nodes()],

371

node_size=500, font_size=12, font_weight='bold')

372

axes[0].set_title("Bipartite Layout")

373

374

# Tree layout (hierarchical)

375

pos_tree = nx.nx_agraph.graphviz_layout(T, prog='dot') if hasattr(nx, 'nx_agraph') else nx.spring_layout(T)

376

nx.draw(T, pos=pos_tree, ax=axes[1], with_labels=True,

377

node_color='lightgreen', node_size=500, font_size=12, font_weight='bold')

378

axes[1].set_title("Hierarchical Tree")

379

380

# Multipartite layout

381

pos_multi = nx.multipartite_layout(M, subset_key='subset')

382

colors = ['red' if d['subset'] == 0 else 'blue' if d['subset'] == 1 else 'green'

383

for n, d in M.nodes(data=True)]

384

nx.draw(M, pos=pos_multi, ax=axes[2], with_labels=True,

385

node_color=colors, node_size=500, font_size=12, font_weight='bold')

386

axes[2].set_title("Multipartite Layout")

387

388

plt.tight_layout()

389

plt.show()

390

```

391

392

### Interactive and Advanced Visualizations

393

394

```python

395

import networkx as nx

396

import matplotlib.pyplot as plt

397

from matplotlib.widgets import Slider

398

import numpy as np

399

400

# Create graph that changes over time

401

def create_temporal_graph(t):

402

"""Create graph that evolves with parameter t."""

403

G = nx.Graph()

404

n = 10

405

406

# Add nodes

407

G.add_nodes_from(range(n))

408

409

# Add edges based on time parameter

410

for i in range(n):

411

for j in range(i+1, n):

412

# Probability of edge depends on time and distance

413

prob = 0.3 * (1 + np.sin(t + i*0.5 + j*0.3))

414

if np.random.random() < prob:

415

G.add_edge(i, j)

416

417

return G

418

419

# Set up the figure and axis

420

fig, ax = plt.subplots(figsize=(10, 8))

421

plt.subplots_adjust(bottom=0.15)

422

423

# Initial graph

424

t_init = 0

425

G = create_temporal_graph(t_init)

426

pos = nx.circular_layout(G) # Keep positions fixed

427

428

# Initial drawing

429

nx.draw(G, pos=pos, ax=ax, with_labels=True,

430

node_color='lightblue', node_size=500,

431

font_size=12, font_weight='bold')

432

ax.set_title(f"Temporal Graph (t = {t_init:.2f})")

433

434

# Add slider

435

ax_slider = plt.axes([0.2, 0.05, 0.6, 0.03])

436

slider = Slider(ax_slider, 'Time', 0, 2*np.pi, valinit=t_init)

437

438

def update_graph(val):

439

"""Update graph based on slider value."""

440

ax.clear()

441

t = slider.val

442

443

# Create new graph

444

np.random.seed(42) # For reproducibility

445

G = create_temporal_graph(t)

446

447

# Draw updated graph

448

nx.draw(G, pos=pos, ax=ax, with_labels=True,

449

node_color='lightblue', node_size=500,

450

font_size=12, font_weight='bold')

451

ax.set_title(f"Temporal Graph (t = {t:.2f})")

452

fig.canvas.draw()

453

454

slider.on_changed(update_graph)

455

plt.show()

456

```

457

458

### Graph Comparison Visualization

459

460

```python

461

import networkx as nx

462

import matplotlib.pyplot as plt

463

464

def compare_graphs(graphs, titles, layout_func=nx.spring_layout):

465

"""Compare multiple graphs side by side."""

466

n_graphs = len(graphs)

467

fig, axes = plt.subplots(1, n_graphs, figsize=(5*n_graphs, 5))

468

469

if n_graphs == 1:

470

axes = [axes]

471

472

for i, (G, title) in enumerate(zip(graphs, titles)):

473

pos = layout_func(G, seed=42)

474

475

# Compute node colors based on centrality

476

centrality = nx.degree_centrality(G)

477

node_colors = [centrality[node] for node in G.nodes()]

478

479

nx.draw(G, pos=pos, ax=axes[i],

480

node_color=node_colors,

481

cmap=plt.cm.viridis,

482

node_size=500,

483

with_labels=True,

484

font_size=10,

485

font_weight='bold',

486

edge_color='gray',

487

alpha=0.8)

488

489

axes[i].set_title(f"{title}\n{G.number_of_nodes()} nodes, {G.number_of_edges()} edges")

490

491

plt.tight_layout()

492

return fig

493

494

# Create different graph types for comparison

495

graphs = [

496

nx.erdos_renyi_graph(20, 0.15, seed=42),

497

nx.barabasi_albert_graph(20, 2, seed=42),

498

nx.watts_strogatz_graph(20, 4, 0.3, seed=42),

499

nx.complete_graph(8)

500

]

501

502

titles = ['Erdős-Rényi', 'Barabási-Albert', 'Watts-Strogatz', 'Complete']

503

504

fig = compare_graphs(graphs, titles)

505

plt.show()

506

```