or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

alignment.mdclustering.mdcore-dtw.mddistance-matrices.mdindex.mdndim-dtw.mdvisualization.mdwarping-paths.mdweighted-dtw.md

visualization.mddocs/

0

# Visualization Tools

1

2

Comprehensive visualization capabilities for DTW analysis, including warping path plots, distance matrix heatmaps, and time series alignment visualizations. These tools provide essential insights into DTW behavior, sequence relationships, and clustering results for both 1D and multi-dimensional data.

3

4

## Capabilities

5

6

### Warping Path Visualization

7

8

Visualize the optimal warping path between two time series, showing how elements from one sequence align with elements from another.

9

10

```python { .api }

11

def plot_warping(s1, s2, path, filename=None):

12

"""

13

Plot optimal warping between two sequences.

14

15

Creates a visualization showing both time series with connecting lines

16

that illustrate the optimal warping path alignment between sequences.

17

18

Parameters:

19

- s1, s2: array-like, input time series sequences

20

- path: list, warping path as sequence of (i, j) coordinate pairs

21

- filename: str, optional file path to save the plot

22

23

Returns:

24

tuple: (figure, axes) matplotlib objects

25

"""

26

27

def plot_warpingpaths(s1, s2, paths, path=None, filename=None,

28

shownumbers=False):

29

"""

30

Plot warping paths matrix with sequences.

31

32

Displays the full accumulated cost matrix (warping paths) as a heatmap

33

alongside the input sequences, with optional overlay of the optimal path.

34

35

Parameters:

36

- s1, s2: array-like, input sequences

37

- paths: 2D array, warping paths matrix from dtw.warping_paths()

38

- path: list, optional optimal path to overlay

39

- filename: str, optional file path to save plot

40

- shownumbers: bool, display numerical values in matrix cells

41

42

Returns:

43

tuple: (figure, axes) matplotlib objects

44

"""

45

```

46

47

### Sequence Warping Visualization

48

49

Visualize the transformation of one sequence to match another through DTW warping.

50

51

```python { .api }

52

def plot_warp(from_s, to_s, new_s, path, filename=None):

53

"""

54

Plot warped sequence relationships.

55

56

Shows the original sequence, target sequence, and the warped result

57

to illustrate how DTW transforms one sequence to better match another.

58

59

Parameters:

60

- from_s: array-like, original source sequence

61

- to_s: array-like, target sequence to warp towards

62

- new_s: array-like, warped version of source sequence

63

- path: list, warping path used for transformation

64

- filename: str, optional file path to save plot

65

66

Returns:

67

tuple: (figure, axes) matplotlib objects

68

"""

69

```

70

71

### Distance Matrix Visualization

72

73

Create heatmap visualizations of distance matrices for analyzing relationships between multiple time series.

74

75

```python { .api }

76

def plot_matrix(distances, filename=None, ax=None, shownumbers=False):

77

"""

78

Plot distance matrix as heatmap.

79

80

Creates a color-coded heatmap representation of the distance matrix

81

showing pairwise similarities between all sequences in a collection.

82

83

Parameters:

84

- distances: 2D array, symmetric distance matrix

85

- filename: str, optional file path to save plot

86

- ax: matplotlib axis, optional axis for plotting

87

- shownumbers: bool, display distance values in matrix cells

88

89

Returns:

90

tuple: (figure, axes) matplotlib objects

91

"""

92

```

93

94

## Usage Examples

95

96

### Basic Warping Path Visualization

97

98

```python

99

from dtaidistance import dtw

100

from dtaidistance.dtw_visualisation import plot_warping, plot_warpingpaths

101

import matplotlib.pyplot as plt

102

103

# Create two sequences with different temporal patterns

104

s1 = [0, 1, 2, 3, 2, 1, 0, 0]

105

s2 = [0, 0, 1, 2, 2, 3, 2, 1, 0]

106

107

# Compute optimal warping path

108

path = dtw.warping_path(s1, s2)

109

print("Warping path:", path)

110

111

# Visualize the warping between sequences

112

fig, ax = plot_warping(s1, s2, path)

113

plt.title('DTW Warping Path Between Sequences')

114

plt.show()

115

116

# Also compute and visualize the full warping paths matrix

117

distance, paths_matrix = dtw.warping_paths(s1, s2)

118

119

fig, ax = plot_warpingpaths(s1, s2, paths_matrix, path)

120

plt.title('DTW Warping Paths Matrix')

121

plt.show()

122

```

123

124

### Advanced Warping Path Analysis

125

126

```python

127

from dtaidistance import dtw

128

from dtaidistance.dtw_visualisation import plot_warping, plot_warpingpaths

129

import numpy as np

130

import matplotlib.pyplot as plt

131

132

# Create sequences with clear temporal distortions

133

t1 = np.linspace(0, 4*np.pi, 50)

134

t2 = np.linspace(0, 4*np.pi, 40)

135

136

s1 = np.sin(t1) + 0.1 * np.random.randn(len(t1))

137

s2 = np.sin(t2 * 1.2) + 0.1 * np.random.randn(len(t2)) # Slightly faster

138

139

# Compute warping with constraints

140

distance, paths = dtw.warping_paths(s1, s2, window=10)

141

path = dtw.best_path(paths)

142

143

# Create comprehensive visualization

144

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 10))

145

146

# Plot original sequences

147

ax1.plot(s1, 'b-', label='Sequence 1', linewidth=2)

148

ax1.plot(s2, 'r-', label='Sequence 2', linewidth=2)

149

ax1.set_title('Original Sequences')

150

ax1.legend()

151

ax1.grid(True)

152

153

# Plot warping paths matrix

154

im = ax2.imshow(paths, cmap='viridis', origin='lower')

155

ax2.set_title('Warping Paths Matrix')

156

ax2.set_xlabel('Sequence 2 Index')

157

ax2.set_ylabel('Sequence 1 Index')

158

plt.colorbar(im, ax=ax2)

159

160

# Plot optimal path on matrix

161

if path:

162

path_i, path_j = zip(*path)

163

ax2.plot(path_j, path_i, 'white', linewidth=2, alpha=0.8)

164

165

# Plot warping connections

166

ax3.plot(s1, 'b-o', label='Sequence 1', markersize=4)

167

ax3.plot(s2, 'r-o', label='Sequence 2', markersize=4)

168

169

# Draw warping connections

170

for i, j in path[::5]: # Show every 5th connection for clarity

171

if i < len(s1) and j < len(s2):

172

ax3.plot([i, j], [s1[i], s2[j]], 'gray', alpha=0.3, linewidth=0.5)

173

174

ax3.set_title('Warping Connections (every 5th)')

175

ax3.legend()

176

ax3.grid(True)

177

178

# Show warping path coordinates

179

ax4.plot([p[0] for p in path], label='Sequence 1 indices', marker='o', markersize=3)

180

ax4.plot([p[1] for p in path], label='Sequence 2 indices', marker='s', markersize=3)

181

ax4.set_title('Warping Path Coordinates')

182

ax4.set_xlabel('Path Step')

183

ax4.set_ylabel('Sequence Index')

184

ax4.legend()

185

ax4.grid(True)

186

187

plt.tight_layout()

188

plt.show()

189

190

print(f"DTW distance: {distance:.3f}")

191

print(f"Path length: {len(path)}")

192

```

193

194

### Sequence Warping Transformation Visualization

195

196

```python

197

from dtaidistance import dtw

198

from dtaidistance.dtw_visualisation import plot_warp

199

import numpy as np

200

import matplotlib.pyplot as plt

201

202

# Create source and target sequences

203

source = np.array([1, 2, 4, 6, 4, 2, 1, 1, 1])

204

target = np.array([1, 3, 5, 3, 1])

205

206

# Perform sequence warping

207

warped_source, path = dtw.warp(source, target)

208

209

# Visualize the warping transformation

210

fig, ax = plot_warp(source, target, warped_source, path)

211

plt.title('Sequence Warping Transformation')

212

plt.show()

213

214

# Additional analysis plot

215

fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(10, 8))

216

217

# Original sequences

218

ax1.plot(source, 'b-o', label='Original Source', linewidth=2, markersize=6)

219

ax1.plot(target, 'r-o', label='Target', linewidth=2, markersize=6)

220

ax1.set_title('Original Sequences')

221

ax1.legend()

222

ax1.grid(True)

223

224

# Warped source vs target

225

ax2.plot(warped_source, 'g-o', label='Warped Source', linewidth=2, markersize=6)

226

ax2.plot(target, 'r--', label='Target (reference)', linewidth=2, alpha=0.7)

227

ax2.set_title('Warped Source vs Target')

228

ax2.legend()

229

ax2.grid(True)

230

231

# Difference after warping

232

difference = np.array(warped_source) - np.array(target)

233

ax3.bar(range(len(difference)), difference, color='purple', alpha=0.7)

234

ax3.set_title('Difference After Warping')

235

ax3.set_xlabel('Time Point')

236

ax3.set_ylabel('Difference')

237

ax3.grid(True)

238

239

plt.tight_layout()

240

plt.show()

241

242

print(f"Original DTW distance: {dtw.distance(source, target):.3f}")

243

print(f"Warped sequence distance: {dtw.distance(warped_source, target):.3f}")

244

```

245

246

### Distance Matrix Heatmap

247

248

```python

249

from dtaidistance import dtw

250

from dtaidistance.dtw_visualisation import plot_matrix

251

import numpy as np

252

import matplotlib.pyplot as plt

253

254

# Create diverse time series collection

255

np.random.seed(42)

256

series = []

257

258

# Group 1: Sine waves with different frequencies

259

for freq in [1, 1.5, 2]:

260

t = np.linspace(0, 4*np.pi, 50)

261

s = np.sin(freq * t) + 0.1 * np.random.randn(50)

262

series.append(s)

263

264

# Group 2: Cosine waves

265

for freq in [1, 1.5]:

266

t = np.linspace(0, 4*np.pi, 50)

267

s = np.cos(freq * t) + 0.1 * np.random.randn(50)

268

series.append(s)

269

270

# Group 3: Linear trends

271

for slope in [0.5, 1.0, 1.5]:

272

t = np.linspace(0, 1, 50)

273

s = slope * t + 0.1 * np.random.randn(50)

274

series.append(s)

275

276

# Compute distance matrix

277

distances = dtw.distance_matrix(series, parallel=True)

278

279

# Visualize distance matrix

280

fig, ax = plot_matrix(distances, shownumbers=False)

281

plt.title('DTW Distance Matrix Heatmap')

282

283

# Add series type labels

284

group_labels = ['Sin 1Hz', 'Sin 1.5Hz', 'Sin 2Hz', 'Cos 1Hz', 'Cos 1.5Hz',

285

'Linear 0.5', 'Linear 1.0', 'Linear 1.5']

286

ax.set_xticks(range(len(group_labels)))

287

ax.set_yticks(range(len(group_labels)))

288

ax.set_xticklabels(group_labels, rotation=45, ha='right')

289

ax.set_yticklabels(group_labels)

290

291

plt.tight_layout()

292

plt.show()

293

294

# Analyze distance patterns

295

print("Distance matrix analysis:")

296

print(f"Matrix shape: {distances.shape}")

297

print(f"Mean distance: {np.mean(distances[np.triu_indices_from(distances, k=1)]):.3f}")

298

print(f"Min distance: {np.min(distances[np.triu_indices_from(distances, k=1)]):.3f}")

299

print(f"Max distance: {np.max(distances):.3f}")

300

```

301

302

### Multi-Panel Comprehensive Analysis

303

304

```python

305

from dtaidistance import dtw

306

from dtaidistance.dtw_visualisation import plot_warping, plot_warpingpaths, plot_matrix

307

import numpy as np

308

import matplotlib.pyplot as plt

309

310

# Generate test data

311

np.random.seed(42)

312

s1 = np.cumsum(np.random.randn(30)) + np.sin(np.linspace(0, 4*np.pi, 30))

313

s2 = np.cumsum(np.random.randn(25)) + np.cos(np.linspace(0, 3*np.pi, 25))

314

s3 = np.linspace(0, 5, 35) + 0.5 * np.random.randn(35)

315

316

series_collection = [s1, s2, s3]

317

318

# Compute various DTW analyses

319

distance_12, paths_12 = dtw.warping_paths(s1, s2, window=5)

320

path_12 = dtw.best_path(paths_12)

321

distances_matrix = dtw.distance_matrix(series_collection)

322

323

# Create comprehensive visualization

324

fig = plt.figure(figsize=(15, 10))

325

326

# Layout: 2 rows, 3 columns

327

ax1 = plt.subplot(2, 3, 1)

328

ax2 = plt.subplot(2, 3, 2)

329

ax3 = plt.subplot(2, 3, 3)

330

ax4 = plt.subplot(2, 3, 4)

331

ax5 = plt.subplot(2, 3, 5)

332

ax6 = plt.subplot(2, 3, 6)

333

334

# Plot 1: Original time series

335

for i, s in enumerate(series_collection):

336

ax1.plot(s, f'C{i}-', label=f'Series {i+1}', linewidth=2)

337

ax1.set_title('Original Time Series')

338

ax1.legend()

339

ax1.grid(True)

340

341

# Plot 2: Warping paths matrix

342

im2 = ax2.imshow(paths_12, cmap='viridis', origin='lower')

343

ax2.set_title('Warping Paths Matrix (S1 vs S2)')

344

ax2.set_xlabel('Series 2 Index')

345

ax2.set_ylabel('Series 1 Index')

346

if path_12:

347

path_i, path_j = zip(*path_12)

348

ax2.plot(path_j, path_i, 'white', linewidth=2)

349

350

# Plot 3: Distance matrix heatmap

351

im3 = ax3.imshow(distances_matrix, cmap='hot', origin='lower')

352

ax3.set_title('Distance Matrix')

353

ax3.set_xlabel('Series Index')

354

ax3.set_ylabel('Series Index')

355

plt.colorbar(im3, ax=ax3)

356

357

# Plot 4: Warping between S1 and S2

358

ax4.plot(s1, 'b-o', label='Series 1', markersize=4)

359

ax4.plot(s2, 'r-o', label='Series 2', markersize=4)

360

361

# Draw some warping connections

362

for i, (idx1, idx2) in enumerate(path_12[::3]): # Every 3rd connection

363

if idx1 < len(s1) and idx2 < len(s2):

364

ax4.plot([idx1, idx2], [s1[idx1], s2[idx2]], 'gray', alpha=0.4, linewidth=0.5)

365

366

ax4.set_title('Warping Connections (S1 vs S2)')

367

ax4.legend()

368

ax4.grid(True)

369

370

# Plot 5: Path analysis

371

if path_12:

372

path_i, path_j = zip(*path_12)

373

ax5.plot(path_i, 'b-', label='Series 1 indices', linewidth=2)

374

ax5.plot(path_j, 'r-', label='Series 2 indices', linewidth=2)

375

ax5.set_title('Optimal Path Indices')

376

ax5.set_xlabel('Path Step')

377

ax5.set_ylabel('Sequence Index')

378

ax5.legend()

379

ax5.grid(True)

380

381

# Plot 6: Distance comparison

382

distances_pairwise = [

383

dtw.distance(series_collection[0], series_collection[1]),

384

dtw.distance(series_collection[0], series_collection[2]),

385

dtw.distance(series_collection[1], series_collection[2])

386

]

387

pair_labels = ['S1-S2', 'S1-S3', 'S2-S3']

388

389

bars = ax6.bar(pair_labels, distances_pairwise, color=['blue', 'green', 'red'], alpha=0.7)

390

ax6.set_title('Pairwise DTW Distances')

391

ax6.set_ylabel('DTW Distance')

392

393

# Add value labels on bars

394

for bar, distance in zip(bars, distances_pairwise):

395

height = bar.get_height()

396

ax6.text(bar.get_x() + bar.get_width()/2., height + 0.1,

397

f'{distance:.2f}', ha='center', va='bottom')

398

399

plt.tight_layout()

400

plt.show()

401

402

print(f"DTW distance S1-S2: {distance_12:.3f}")

403

print(f"Path length: {len(path_12)}")

404

print(f"Series lengths: S1={len(s1)}, S2={len(s2)}, S3={len(s3)}")

405

```

406

407

### Interactive Visualization with Constraints

408

409

```python

410

from dtaidistance import dtw

411

from dtaidistance.dtw_visualisation import plot_warpingpaths

412

import numpy as np

413

import matplotlib.pyplot as plt

414

415

def compare_constraints(s1, s2, constraints_list):

416

"""Compare DTW results with different constraint settings."""

417

418

fig, axes = plt.subplots(2, len(constraints_list), figsize=(15, 8))

419

420

for i, constraints in enumerate(constraints_list):

421

# Compute DTW with constraints

422

distance, paths = dtw.warping_paths(s1, s2, **constraints)

423

path = dtw.best_path(paths)

424

425

# Plot warping paths matrix

426

im = axes[0, i].imshow(paths, cmap='viridis', origin='lower')

427

axes[0, i].set_title(f'Window={constraints.get("window", "None")}\\n'

428

f'Distance={distance:.2f}')

429

430

if path:

431

path_i, path_j = zip(*path)

432

axes[0, i].plot(path_j, path_i, 'white', linewidth=2)

433

434

# Plot sequences with warping connections

435

axes[1, i].plot(s1, 'b-o', label='S1', markersize=3)

436

axes[1, i].plot(s2, 'r-o', label='S2', markersize=3)

437

438

# Draw warping connections (sample every 5th)

439

for j, (idx1, idx2) in enumerate(path[::5]):

440

if idx1 < len(s1) and idx2 < len(s2):

441

axes[1, i].plot([idx1, idx2], [s1[idx1], s2[idx2]],

442

'gray', alpha=0.3, linewidth=0.5)

443

444

axes[1, i].set_title(f'Warping Connections')

445

axes[1, i].grid(True)

446

if i == 0:

447

axes[1, i].legend()

448

449

plt.tight_layout()

450

plt.show()

451

452

# Test different constraint settings

453

s1 = np.sin(np.linspace(0, 4*np.pi, 40)) + 0.1*np.random.randn(40)

454

s2 = np.sin(np.linspace(0, 3*np.pi, 30)) + 0.1*np.random.randn(30)

455

456

constraint_sets = [

457

{}, # No constraints

458

{'window': 5}, # Narrow window

459

{'window': 15}, # Wide window

460

{'window': 10, 'max_dist': 20.0} # Window + early stopping

461

]

462

463

compare_constraints(s1, s2, constraint_sets)

464

```

465

466

This comprehensive visualization module provides essential tools for understanding DTW behavior, analyzing sequence relationships, and validating clustering results through intuitive graphical representations.