or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

3d-plotting.mdanimation.mdbackends.mdcolors-styling.mdindex.mdobject-oriented.mdpyplot.mdshapes.md

animation.mddocs/

0

# Animation and Interactivity

1

2

Creating animated plots and interactive visualizations. Matplotlib provides comprehensive animation capabilities through function-based and artist-based approaches, with support for various export formats and interactive backends.

3

4

## Capabilities

5

6

### Animation Base Classes

7

8

Core animation framework for creating animated visualizations.

9

10

```python { .api }

11

import matplotlib.animation as manimation

12

13

class Animation:

14

def __init__(self, fig, event_source=None, blit=False):

15

"""Base class for all animations."""

16

17

def save(self, filename, writer=None, fps=None, dpi=None, codec=None,

18

bitrate=None, extra_args=None, metadata=None, extra_anim=None,

19

savefig_kwargs=None, *, progress_callback=None) -> None:

20

"""Save the animation to a file."""

21

22

def to_html5_video(self, embed_limit=None) -> str:

23

"""Convert animation to HTML5 video."""

24

25

def to_jshtml(self, fps=None, embed_frames=True, default_mode=None) -> str:

26

"""Generate HTML representation with JavaScript controls."""

27

28

def pause(self) -> None:

29

"""Pause the animation."""

30

31

def resume(self) -> None:

32

"""Resume the animation."""

33

34

class TimedAnimation(Animation):

35

def __init__(self, fig, interval=200, repeat_delay=0, repeat=True,

36

event_source=None, *args, **kwargs):

37

"""Base class for timed animations."""

38

39

def _draw_frame(self, framedata) -> None:

40

"""Draw a single frame of the animation."""

41

```

42

43

### Function-Based Animation

44

45

Animation using a function that is called repeatedly to update the plot.

46

47

```python { .api }

48

class FuncAnimation(TimedAnimation):

49

def __init__(self, fig, func, frames=None, init_func=None, fargs=None,

50

save_count=None, *, cache_frame_data=True, **kwargs):

51

"""Animation by repeatedly calling a function."""

52

53

def new_frame_seq(self):

54

"""Return a new sequence of frame information."""

55

56

def new_saved_frame_seq(self):

57

"""Return a new sequence of saved frame information."""

58

59

# Convenience function

60

def FuncAnimation(fig, func, frames=None, init_func=None, fargs=None,

61

interval=200, repeat_delay=0, repeat=True, blit=False,

62

save_count=None, cache_frame_data=True) -> FuncAnimation:

63

"""Animate by repeatedly calling function func."""

64

```

65

66

### Artist-Based Animation

67

68

Animation using a list of artists that are shown sequentially.

69

70

```python { .api }

71

class ArtistAnimation(TimedAnimation):

72

def __init__(self, fig, artists, interval=200, repeat_delay=0, repeat=True,

73

blit=False):

74

"""Animation using a list of artists."""

75

76

def new_frame_seq(self):

77

"""Return a new sequence of artists."""

78

79

def new_saved_frame_seq(self):

80

"""Return a new sequence of saved artists."""

81

82

# Convenience function

83

def ArtistAnimation(fig, artists, interval=200, repeat_delay=0, repeat=True,

84

blit=False) -> ArtistAnimation:

85

"""Animate by sequentially displaying a list of artists."""

86

```

87

88

### Writer Classes

89

90

Classes for saving animations to various file formats.

91

92

```python { .api }

93

class Writer:

94

def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,

95

metadata=None):

96

"""Base class for animation writers."""

97

98

def setup(self, fig, outfile, dpi=None) -> None:

99

"""Setup for writing the animation."""

100

101

def grab_frame(self, **kwargs) -> None:

102

"""Grab the current frame."""

103

104

def finish(self) -> None:

105

"""Finish writing the animation."""

106

107

class MovieWriter(Writer):

108

def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,

109

metadata=None):

110

"""Base class for movie writers using external tools."""

111

112

class FFMpegWriter(MovieWriter):

113

def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,

114

metadata=None):

115

"""Writer using FFmpeg for video encoding."""

116

117

class ImageMagickWriter(MovieWriter):

118

def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,

119

metadata=None):

120

"""Writer using ImageMagick for GIF creation."""

121

122

class PillowWriter(Writer):

123

def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,

124

metadata=None):

125

"""Writer using Pillow for GIF creation."""

126

127

class HTMLWriter(Writer):

128

def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,

129

metadata=None, embed_frames=False):

130

"""Writer for HTML with JavaScript controls."""

131

```

132

133

### Interactive Widgets

134

135

Interactive controls and widgets for plot manipulation.

136

137

```python { .api }

138

from matplotlib.widgets import *

139

140

class Button:

141

def __init__(self, ax, label, image=None, color='0.85', hovercolor='0.95'):

142

"""Clickable button widget."""

143

144

def on_clicked(self, func) -> None:

145

"""Connect function to button click event."""

146

147

class Slider:

148

def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,

149

closedmin=True, closedmax=True, slidermin=None, slidermax=None,

150

dragging=True, valstep=None, orientation='horizontal',

151

initcolor='r', track_color='lightgrey', handle_style='round'):

152

"""Slider widget for continuous value selection."""

153

154

def on_changed(self, func) -> None:

155

"""Connect function to slider value change event."""

156

157

def set_val(self, val) -> None:

158

"""Set slider value."""

159

160

class CheckButtons:

161

def __init__(self, ax, labels, actives=None):

162

"""Check button widget for multiple boolean selections."""

163

164

def on_clicked(self, func) -> None:

165

"""Connect function to check button click event."""

166

167

class RadioButtons:

168

def __init__(self, ax, labels, active=0, activecolor='blue'):

169

"""Radio button widget for single selection from multiple options."""

170

171

def on_clicked(self, func) -> None:

172

"""Connect function to radio button selection event."""

173

174

class TextBox:

175

def __init__(self, ax, label, initial='', color='.95', hovercolor='1',

176

label_pad=.01, textalignment='left'):

177

"""Text input widget."""

178

179

def on_text_change(self, func) -> None:

180

"""Connect function to text change event."""

181

182

def on_submit(self, func) -> None:

183

"""Connect function to text submission event."""

184

```

185

186

## Usage Examples

187

188

### Basic Function Animation

189

190

```python

191

import matplotlib.pyplot as plt

192

import matplotlib.animation as animation

193

import numpy as np

194

195

# Set up the figure and axis

196

fig, ax = plt.subplots()

197

x = np.linspace(0, 2*np.pi, 100)

198

line, = ax.plot(x, np.sin(x))

199

200

ax.set_ylim(-2, 2)

201

ax.set_xlabel('X')

202

ax.set_ylabel('Y')

203

ax.set_title('Animated Sine Wave')

204

205

def animate(frame):

206

"""Animation function called sequentially."""

207

# Update the y data with a phase shift

208

y = np.sin(x + frame * 0.1)

209

line.set_ydata(y)

210

return line,

211

212

def init():

213

"""Initialize animation - return the artists to be animated."""

214

line.set_ydata(np.sin(x))

215

return line,

216

217

# Create animation

218

anim = animation.FuncAnimation(fig, animate, init_func=init,

219

frames=200, interval=50, blit=True, repeat=True)

220

221

# Display the animation

222

plt.show()

223

224

# Save as GIF (optional)

225

# anim.save('sine_wave.gif', writer='pillow', fps=20)

226

```

227

228

### Multiple Plot Animation

229

230

```python

231

import matplotlib.pyplot as plt

232

import matplotlib.animation as animation

233

import numpy as np

234

235

# Create subplots

236

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

237

238

# Data setup

239

x = np.linspace(0, 2*np.pi, 100)

240

line1, = ax1.plot(x, np.sin(x), 'b-', label='sin(x)')

241

line2, = ax1.plot(x, np.cos(x), 'r-', label='cos(x)')

242

ax1.set_ylim(-2, 2)

243

ax1.set_title('Trigonometric Functions')

244

ax1.legend()

245

ax1.grid(True)

246

247

# Scatter plot setup

248

scat = ax2.scatter([], [], s=100, alpha=0.7)

249

ax2.set_xlim(-2, 2)

250

ax2.set_ylim(-2, 2)

251

ax2.set_title('Moving Points')

252

ax2.grid(True)

253

254

def animate(frame):

255

"""Animate both subplots."""

256

# Update trigonometric plots

257

phase = frame * 0.1

258

line1.set_ydata(np.sin(x + phase))

259

line2.set_ydata(np.cos(x + phase))

260

261

# Update scatter plot

262

n_points = 20

263

theta = np.linspace(0, 2*np.pi, n_points) + phase

264

x_scat = 1.5 * np.cos(theta)

265

y_scat = 1.5 * np.sin(theta)

266

267

# Update scatter plot data

268

scat.set_offsets(np.column_stack((x_scat, y_scat)))

269

270

return line1, line2, scat

271

272

# Create and run animation

273

anim = animation.FuncAnimation(fig, animate, frames=200, interval=100, blit=True)

274

plt.tight_layout()

275

plt.show()

276

```

277

278

### Artist Animation Example

279

280

```python

281

import matplotlib.pyplot as plt

282

import matplotlib.animation as animation

283

import numpy as np

284

285

# Generate data for multiple frames

286

fig, ax = plt.subplots()

287

288

# Create list of artists for each frame

289

artists = []

290

for i in range(50):

291

# Generate data for this frame

292

x = np.linspace(0, 10, 100)

293

y = np.sin(x + i * 0.2) * np.exp(-x/10)

294

295

# Create line artist

296

line, = ax.plot(x, y, 'b-')

297

title = ax.text(0.5, 0.9, f'Frame {i+1}', transform=ax.transAxes,

298

ha='center', fontsize=14)

299

300

# Add both line and title to this frame's artists

301

artists.append([line, title])

302

303

ax.set_xlim(0, 10)

304

ax.set_ylim(-1.5, 1.5)

305

ax.set_xlabel('X')

306

ax.set_ylabel('Y')

307

ax.grid(True)

308

309

# Create artist animation

310

anim = animation.ArtistAnimation(fig, artists, interval=100, blit=True, repeat=True)

311

plt.show()

312

```

313

314

### Interactive Animation with Widgets

315

316

```python

317

import matplotlib.pyplot as plt

318

import matplotlib.animation as animation

319

from matplotlib.widgets import Slider, Button

320

import numpy as np

321

322

# Create figure and subplots

323

fig = plt.figure(figsize=(12, 8))

324

ax_plot = plt.subplot2grid((4, 4), (0, 0), colspan=4, rowspan=3)

325

ax_slider1 = plt.subplot2grid((4, 4), (3, 0), colspan=2)

326

ax_slider2 = plt.subplot2grid((4, 4), (3, 2), colspan=2)

327

328

# Initial parameters

329

x = np.linspace(0, 4*np.pi, 200)

330

freq_init = 1.0

331

amp_init = 1.0

332

333

# Create initial plot

334

line, = ax_plot.plot(x, amp_init * np.sin(freq_init * x), 'b-', linewidth=2)

335

ax_plot.set_xlim(0, 4*np.pi)

336

ax_plot.set_ylim(-3, 3)

337

ax_plot.set_xlabel('X')

338

ax_plot.set_ylabel('Amplitude')

339

ax_plot.set_title('Interactive Animated Sine Wave')

340

ax_plot.grid(True)

341

342

# Animation variables

343

anim_running = True

344

phase = 0

345

346

# Create sliders

347

slider_freq = Slider(ax_slider1, 'Frequency', 0.1, 5.0, valinit=freq_init)

348

slider_amp = Slider(ax_slider2, 'Amplitude', 0.1, 3.0, valinit=amp_init)

349

350

def animate(frame):

351

"""Animation function."""

352

global phase

353

if anim_running:

354

phase += 0.1

355

freq = slider_freq.val

356

amp = slider_amp.val

357

y = amp * np.sin(freq * x + phase)

358

line.set_ydata(y)

359

return line,

360

361

def update_freq(val):

362

"""Update frequency from slider."""

363

pass # Animation function will read slider value

364

365

def update_amp(val):

366

"""Update amplitude from slider."""

367

pass # Animation function will read slider value

368

369

# Connect sliders

370

slider_freq.on_changed(update_freq)

371

slider_amp.on_changed(update_amp)

372

373

# Create animation

374

anim = animation.FuncAnimation(fig, animate, frames=1000, interval=50,

375

blit=True, repeat=True)

376

377

plt.tight_layout()

378

plt.show()

379

```

380

381

### 3D Animation

382

383

```python

384

import matplotlib.pyplot as plt

385

import matplotlib.animation as animation

386

from mpl_toolkits.mplot3d import Axes3D

387

import numpy as np

388

389

# Create 3D plot

390

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

391

ax = fig.add_subplot(111, projection='3d')

392

393

# Generate 3D data

394

def generate_data(frame):

395

"""Generate 3D surface data for given frame."""

396

x = np.linspace(-5, 5, 50)

397

y = np.linspace(-5, 5, 50)

398

X, Y = np.meshgrid(x, y)

399

400

# Create animated wave

401

t = frame * 0.1

402

Z = np.sin(np.sqrt(X**2 + Y**2) - t) * np.exp(-0.1 * np.sqrt(X**2 + Y**2))

403

404

return X, Y, Z

405

406

# Initial plot

407

X, Y, Z = generate_data(0)

408

surface = ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)

409

410

ax.set_xlim(-5, 5)

411

ax.set_ylim(-5, 5)

412

ax.set_zlim(-1, 1)

413

ax.set_xlabel('X')

414

ax.set_ylabel('Y')

415

ax.set_zlabel('Z')

416

ax.set_title('3D Animated Wave')

417

418

def animate(frame):

419

"""Animate 3D surface."""

420

ax.clear()

421

422

X, Y, Z = generate_data(frame)

423

surface = ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)

424

425

ax.set_xlim(-5, 5)

426

ax.set_ylim(-5, 5)

427

ax.set_zlim(-1, 1)

428

ax.set_xlabel('X')

429

ax.set_ylabel('Y')

430

ax.set_zlabel('Z')

431

ax.set_title(f'3D Animated Wave - Frame {frame}')

432

433

return surface,

434

435

# Create animation

436

anim = animation.FuncAnimation(fig, animate, frames=100, interval=100, blit=False)

437

plt.show()

438

```

439

440

### Saving Animations

441

442

```python

443

import matplotlib.pyplot as plt

444

import matplotlib.animation as animation

445

import numpy as np

446

447

# Create simple animation

448

fig, ax = plt.subplots()

449

x = np.linspace(0, 2*np.pi, 100)

450

line, = ax.plot(x, np.sin(x))

451

ax.set_ylim(-2, 2)

452

453

def animate(frame):

454

y = np.sin(x + frame * 0.1)

455

line.set_ydata(y)

456

return line,

457

458

anim = animation.FuncAnimation(fig, animate, frames=100, interval=50, blit=True)

459

460

# Save as MP4 (requires ffmpeg)

461

try:

462

anim.save('animation.mp4', writer='ffmpeg', fps=20, bitrate=1800)

463

print("Saved as MP4")

464

except:

465

print("FFmpeg not available")

466

467

# Save as GIF (requires Pillow or ImageMagick)

468

try:

469

anim.save('animation.gif', writer='pillow', fps=20)

470

print("Saved as GIF")

471

except:

472

print("Pillow not available")

473

474

# Save as HTML with JavaScript controls

475

anim.save('animation.html', writer='html', fps=20, embed_frames=True)

476

print("Saved as HTML")

477

478

plt.show()

479

```