0
# Visualization
1
2
Visualization functions create movies and interactive plots from field data with automatic scaling, customizable styling, and support for various output formats.
3
4
## Capabilities
5
6
### Movie Generation
7
8
Create animated movies from stored simulation data.
9
10
```python { .api }
11
def movie(storage, filename=None, *, progress=True, **kwargs):
12
"""
13
Create movie from stored field data.
14
15
Parameters:
16
- storage: StorageBase, stored simulation data
17
- filename: str, output filename (auto-generated if None)
18
- progress: bool, show progress bar during generation
19
- kwargs: additional movie parameters (fps, dpi, writer, etc.)
20
21
Returns:
22
str: Path to generated movie file
23
"""
24
25
def movie_multiple(storages, filename=None, *, progress=True, **kwargs):
26
"""
27
Create movie from multiple storage sources.
28
29
Parameters:
30
- storages: list of StorageBase, multiple data sources
31
- filename: str, output filename
32
- progress: bool, show progress bar
33
- kwargs: movie parameters and layout options
34
35
Returns:
36
str: Path to generated movie file
37
"""
38
39
def movie_scalar(storage, filename=None, *, progress=True, **kwargs):
40
"""
41
Create movie optimized for scalar field data.
42
43
Parameters:
44
- storage: StorageBase, scalar field data
45
- filename: str, output filename
46
- progress: bool, show progress bar
47
- kwargs: scalar-specific visualization parameters
48
49
Returns:
50
str: Path to generated movie file
51
"""
52
```
53
54
### Interactive Plotting
55
56
Create interactive plots for real-time field visualization and analysis.
57
58
```python { .api }
59
def plot_interactive(field, title=None, *, fig_num=1, **kwargs):
60
"""
61
Create interactive plot of field data.
62
63
Parameters:
64
- field: FieldBase, field to visualize
65
- title: str, plot title
66
- fig_num: int, matplotlib figure number
67
- kwargs: additional plotting parameters
68
69
Returns:
70
matplotlib figure: Interactive plot figure
71
"""
72
```
73
74
### Kymograph Visualization
75
76
Create kymograph plots showing field evolution over time and space.
77
78
```python { .api }
79
def plot_kymograph(storage, *, field_index=0, transpose=False, **kwargs):
80
"""
81
Plot kymograph (space-time diagram) from stored data.
82
83
Parameters:
84
- storage: StorageBase, time series field data
85
- field_index: int, field index for FieldCollection data
86
- transpose: bool, transpose space and time axes
87
- kwargs: plotting parameters (colormap, scaling, etc.)
88
89
Returns:
90
matplotlib.axes.Axes: Kymograph plot axes
91
"""
92
93
def plot_kymographs(storage, *, filename=None, **kwargs):
94
"""
95
Plot multiple kymographs for vector/tensor fields.
96
97
Parameters:
98
- storage: StorageBase, time series data
99
- filename: str, save filename (shows if None)
100
- kwargs: plotting and layout parameters
101
102
Returns:
103
matplotlib.figure.Figure: Figure with multiple kymographs
104
"""
105
```
106
107
### Field Magnitude Visualization
108
109
Visualize magnitude and components of vector/tensor fields.
110
111
```python { .api }
112
def plot_magnitudes(storage, *, title=None, filename=None, **kwargs):
113
"""
114
Plot magnitude evolution from stored data.
115
116
Parameters:
117
- storage: StorageBase, time series data
118
- title: str, plot title
119
- filename: str, save filename (shows if None)
120
- kwargs: plotting parameters
121
122
Returns:
123
PlotReference: Reference to the created plot
124
"""
125
```
126
127
### Interactive Visualization
128
129
Create interactive visualizations using external tools.
130
131
```python { .api }
132
def plot_interactive(storage, viewer_args=None, **kwargs):
133
"""
134
Create interactive plot using napari or similar viewer.
135
136
Parameters:
137
- storage: StorageBase, field data for visualization
138
- viewer_args: dict, arguments for the viewer
139
- kwargs: additional visualization parameters
140
"""
141
```
142
143
### Movie and Visualization Classes
144
145
Advanced movie creation with custom rendering and effects.
146
147
```python { .api }
148
class Movie:
149
def __init__(self, filename, *, writer="auto", fps=10, dpi=100):
150
"""
151
Initialize movie writer.
152
153
Parameters:
154
- filename: str, output movie filename
155
- writer: str, movie writer backend
156
- fps: int, frames per second
157
- dpi: int, resolution
158
"""
159
160
def add_frame(self, frame_data, **kwargs):
161
"""
162
Add frame to movie.
163
164
Parameters:
165
- frame_data: FieldBase, field data for frame
166
- kwargs: frame-specific parameters
167
"""
168
169
def save(self):
170
"""Finalize and save movie file"""
171
172
def __enter__(self):
173
"""Context manager entry"""
174
return self
175
176
def __exit__(self, exc_type, exc_val, exc_tb):
177
"""Context manager exit"""
178
self.save()
179
```
180
181
## Usage Examples
182
183
### Basic Movie Creation
184
185
```python
186
import pde
187
188
# Run simulation with data collection
189
grid = pde.CartesianGrid([[0, 10], [0, 10]], [64, 64])
190
eq = pde.AllenCahnPDE()
191
state = eq.get_initial_condition(grid)
192
193
# Collect data for movie
194
storage = pde.MemoryStorage()
195
tracker = pde.DataTracker(storage=storage, interrupts=0.1)
196
result = eq.solve(state, t_range=5.0, tracker=tracker)
197
198
# Create movie
199
movie_file = pde.movie(storage, "phase_separation.mp4", fps=15)
200
print(f"Movie saved as: {movie_file}")
201
```
202
203
### Custom Movie with Styling
204
205
```python
206
import pde
207
import matplotlib.pyplot as plt
208
209
# Simulation setup
210
grid = pde.UnitGrid([128], periodic=True)
211
eq = pde.KuramotoSivashinskyPDE()
212
state = eq.get_initial_condition(grid)
213
214
storage = pde.MemoryStorage()
215
tracker = pde.DataTracker(storage=storage, interrupts=0.05)
216
result = eq.solve(state, t_range=20.0, tracker=tracker)
217
218
# Create styled movie
219
movie_params = {
220
"fps": 20,
221
"dpi": 150,
222
"colormap": "plasma",
223
"title": "Kuramoto-Sivashinsky Dynamics",
224
"xlabel": "Position",
225
"ylabel": "Height"
226
}
227
228
pde.movie_scalar(storage, "ks_evolution.mp4", **movie_params)
229
```
230
231
### Interactive Visualization
232
233
```python
234
import pde
235
import matplotlib.pyplot as plt
236
237
# 2D field for interactive exploration
238
grid = pde.CartesianGrid([[-5, 5], [-5, 5]], [64, 64])
239
field = pde.ScalarField.from_expression(grid, "exp(-(x**2 + y**2)/2)")
240
241
# Create interactive plot
242
fig = pde.plot_interactive(
243
field,
244
title="Interactive Field Visualization",
245
colorbar=True,
246
aspect="equal"
247
)
248
249
plt.show()
250
```
251
252
### Kymograph Analysis
253
254
```python
255
import pde
256
257
# 1D simulation for kymograph
258
grid = pde.UnitGrid([128], periodic=True)
259
eq = pde.DiffusionPDE(diffusivity=0.01)
260
261
# Create traveling wave initial condition
262
def traveling_wave(x):
263
return np.sin(2*np.pi*x) + 0.5*np.sin(4*np.pi*x)
264
265
state = pde.ScalarField.from_expression(grid, traveling_wave)
266
267
# Long time simulation
268
storage = pde.MemoryStorage()
269
tracker = pde.DataTracker(storage=storage, interrupts=0.1)
270
result = eq.solve(state, t_range=50.0, tracker=tracker)
271
272
# Create kymograph
273
ax = pde.plot_kymograph(
274
storage,
275
transpose=False,
276
colormap="RdBu_r",
277
title="Diffusion Evolution"
278
)
279
plt.xlabel("Position")
280
plt.ylabel("Time")
281
plt.show()
282
```
283
284
### Vector Field Visualization
285
286
```python
287
import pde
288
289
# Create vector field
290
grid = pde.CartesianGrid([[-2, 2], [-2, 2]], [32, 32])
291
def vortex(x, y):
292
return [-y, x]
293
294
vector_field = pde.VectorField.from_expression(grid, vortex)
295
296
# Visualize components and magnitude
297
fig = pde.plot_magnitudes(
298
vector_field,
299
layout="grid",
300
colormap="viridis",
301
title="Vortex Field Analysis"
302
)
303
plt.show()
304
```
305
306
### Custom Movie with Multiple Fields
307
308
```python
309
import pde
310
311
# Simulate coupled system
312
grid = pde.CartesianGrid([[0, 20], [0, 20]], [64, 64])
313
eq = pde.CahnHilliardPDE()
314
state = eq.get_initial_condition(grid)
315
316
# Create auxiliary fields for analysis
317
storage = pde.MemoryStorage()
318
aux_storage = pde.MemoryStorage()
319
320
def analysis_callback(field, t):
321
# Store gradient magnitude
322
grad = field.gradient("auto_periodic_neumann")
323
grad_mag = grad.magnitude()
324
aux_storage.append(grad_mag, {"t": t})
325
326
trackers = [
327
pde.DataTracker(storage=storage, interrupts=0.2),
328
pde.CallbackTracker(analysis_callback, interrupts=0.2)
329
]
330
331
result = eq.solve(state, t_range=10.0, tracker=trackers)
332
333
# Create multi-panel movie
334
storages = [storage, aux_storage]
335
labels = ["Concentration", "Gradient Magnitude"]
336
337
pde.movie_multiple(
338
storages,
339
"cahn_hilliard_analysis.mp4",
340
layout="horizontal",
341
titles=labels,
342
fps=10
343
)
344
```
345
346
### High-Quality Movie Production
347
348
```python
349
import pde
350
351
# High-resolution simulation
352
grid = pde.CartesianGrid([[0, 10], [0, 10]], [256, 256])
353
eq = pde.SwiftHohenbergPDE(a=0.2, b=1.0)
354
state = eq.get_initial_condition(grid)
355
356
# Dense data collection for smooth animation
357
storage = pde.MemoryStorage()
358
tracker = pde.DataTracker(storage=storage, interrupts=0.02)
359
360
result = eq.solve(state, t_range=30.0, tracker=tracker)
361
362
# High-quality movie parameters
363
movie_config = {
364
"fps": 30,
365
"dpi": 300,
366
"writer": "ffmpeg",
367
"bitrate": 5000,
368
"codec": "h264",
369
"colormap": "magma",
370
"interpolation": "bilinear"
371
}
372
373
pde.movie(storage, "high_quality_patterns.mp4", **movie_config)
374
print("High-quality movie generated")
375
```
376
377
### Real-time Visualization
378
379
```python
380
import pde
381
import matplotlib.pyplot as plt
382
383
# Set up real-time plotting
384
grid = pde.UnitGrid([64, 64], periodic=True)
385
eq = pde.AllenCahnPDE()
386
state = eq.get_initial_condition(grid)
387
388
# Custom real-time plotting tracker
389
class RealTimePlotter(pde.TrackerBase):
390
def __init__(self, interrupts=1):
391
super().__init__(interrupts=interrupts)
392
self.fig, self.ax = plt.subplots(figsize=(8, 6))
393
self.im = None
394
395
def handle(self, field, t):
396
if self.im is None:
397
self.im = self.ax.imshow(field.data, animated=True)
398
self.ax.set_title("Real-time Evolution")
399
plt.colorbar(self.im, ax=self.ax)
400
else:
401
self.im.set_array(field.data)
402
self.im.set_clim(field.data.min(), field.data.max())
403
404
self.ax.set_title(f"t = {t:.2f}")
405
plt.pause(0.01)
406
407
# Run with real-time visualization
408
plotter = RealTimePlotter(interrupts=0.1)
409
result = eq.solve(state, t_range=10.0, tracker=plotter)
410
plt.show()
411
```