Skip to content

Commit 4a513f5

Browse files
committed
Animation of time-domain WFS
1 parent a684134 commit 4a513f5

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

doc/examples/wfs-animation.ipynb

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"id": "77fc3672",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"import matplotlib.pyplot as plt\n",
11+
"import numpy as np\n",
12+
"import sfs\n",
13+
"from matplotlib import animation\n",
14+
"from IPython.display import HTML\n",
15+
"from functools import partial\n",
16+
"from scipy.signal import unit_impulse\n",
17+
"\n",
18+
"\n",
19+
"# Point source\n",
20+
"xs = 0, 2, 0\n",
21+
"rs = np.linalg.norm(xs) # distance from origin\n",
22+
"ts = rs / sfs.default.c # time-of-arrival at origin\n",
23+
"\n",
24+
"# Impulsive excitation\n",
25+
"fs = 8000 # Adjust this to change the shape (width) of the impulse\n",
26+
"signal = unit_impulse(512), fs # Band-limited pulse (e.g. sinc) can be used instead\n",
27+
"\n",
28+
"# Circular loudspeaker array\n",
29+
"N = 32 # number of loudspeakers\n",
30+
"R = 1.5 # radius\n",
31+
"array = sfs.array.circular(N, R)\n",
32+
"\n",
33+
"grid = sfs.util.xyz_grid([-2, 2], [-2, 2], 0, spacing=0.02)\n",
34+
"\n",
35+
"delays, weights, selection, secondary_source = \\\n",
36+
" sfs.td.wfs.point_25d(array.x, array.n, xs)\n",
37+
"d = sfs.td.wfs.driving_signals(delays, weights, signal)"
38+
]
39+
},
40+
{
41+
"cell_type": "code",
42+
"execution_count": null,
43+
"id": "e3560c30",
44+
"metadata": {
45+
"scrolled": false
46+
},
47+
"outputs": [],
48+
"source": [
49+
"# Animation\n",
50+
"def plot(d, selection, secondary_source, t=0, ax=None, **kw):\n",
51+
" p = sfs.td.synthesize(d, selection, array, secondary_source, grid=grid,\n",
52+
" observation_time=t)\n",
53+
" im = sfs.plot2d.amplitude(p, grid, ax=ax, **kw)\n",
54+
" sfs.plot2d.loudspeakers(array.x, array.n, selection * array.a, size=0.15)\n",
55+
" return im\n",
56+
"\n",
57+
"def update_frame_pressure(i, time_stamps):\n",
58+
" t_i = time_stamps[i]\n",
59+
" p = sfs.td.synthesize(d, selection, array, secondary_source, grid=grid,\n",
60+
" observation_time=t_i)\n",
61+
" im.set_array(p)\n",
62+
" return [im]\n",
63+
"\n",
64+
"\n",
65+
"time_stamps = np.linspace(0.5/343, 5/343, 100) # Time sampling is different from fs defined above\n",
66+
"frames = 100\n",
67+
"interval = 150\n",
68+
"\n",
69+
"\n",
70+
"fig, ax = plt.subplots(figsize=(5, 5))\n",
71+
"p = sfs.td.synthesize(d, selection, array, secondary_source, grid=grid,\n",
72+
" observation_time=0)\n",
73+
"im = plot(d, selection, secondary_source, t=ts, ax=ax, vmin=-0.01, vmax=0.01)\n",
74+
"\n",
75+
"ani = animation.FuncAnimation(\n",
76+
" fig, partial(update_frame_pressure, time_stamps=time_stamps),\n",
77+
" frames=frames, interval=interval, blit=True)\n",
78+
"plt.close()\n",
79+
"HTML(ani.to_jshtml())"
80+
]
81+
},
82+
{
83+
"cell_type": "code",
84+
"execution_count": null,
85+
"id": "9f77a060",
86+
"metadata": {},
87+
"outputs": [],
88+
"source": [
89+
"# Save as gif file - This might take a few minutes.\n",
90+
"ani.save(\"wfs-25d-td.gif\", writer='imagemagick',fps=10, dpi=200)"
91+
]
92+
}
93+
],
94+
"metadata": {
95+
"kernelspec": {
96+
"display_name": "Python 3 (ipykernel)",
97+
"language": "python",
98+
"name": "python3"
99+
},
100+
"language_info": {
101+
"codemirror_mode": {
102+
"name": "ipython",
103+
"version": 3
104+
},
105+
"file_extension": ".py",
106+
"mimetype": "text/x-python",
107+
"name": "python",
108+
"nbconvert_exporter": "python",
109+
"pygments_lexer": "ipython3",
110+
"version": "3.9.5"
111+
}
112+
},
113+
"nbformat": 4,
114+
"nbformat_minor": 5
115+
}

0 commit comments

Comments
 (0)