This page was generated from doc/examples/wfs-animation.ipynb. Interactive online version: Binder badge

[1]:
import matplotlib.pyplot as plt
import numpy as np
import sfs
from matplotlib import animation
from IPython.display import HTML
from functools import partial
from scipy.signal import unit_impulse


# Point source
xs = 0, 2, 0
rs = np.linalg.norm(xs)  # distance from origin
ts = rs / sfs.default.c  # time-of-arrival at origin

# Impulsive excitation
fs = 8000  # Adjust this to change the shape (width) of the impulse
signal = unit_impulse(512), fs  # Band-limited pulse (e.g. sinc) can be used instead

# Circular loudspeaker array
N = 32  # number of loudspeakers
R = 1.5  # radius
array = sfs.array.circular(N, R)

grid = sfs.util.xyz_grid([-2, 2], [-2, 2], 0, spacing=0.02)

delays, weights, selection, secondary_source = \
    sfs.td.wfs.point_25d(array.x, array.n, xs)
d = sfs.td.wfs.driving_signals(delays, weights, signal)
[2]:
# Animation
def plot(d, selection, secondary_source, t=0, ax=None, **kw):
    p = sfs.td.synthesize(d, selection, array, secondary_source, grid=grid,
                          observation_time=t)
    im = sfs.plot2d.amplitude(p, grid, ax=ax, **kw)
    sfs.plot2d.loudspeakers(array.x, array.n, selection * array.a, size=0.15)
    return im

def update_frame_pressure(i, time_stamps):
    t_i = time_stamps[i]
    p = sfs.td.synthesize(d, selection, array, secondary_source, grid=grid,
                          observation_time=t_i)
    im.set_array(p)
    return [im]


time_stamps = np.linspace(0.5/343, 5/343, 100)  # Time sampling is different from fs defined above
frames = 100
interval = 150


fig, ax = plt.subplots(figsize=(5, 5))
p = sfs.td.synthesize(d, selection, array, secondary_source, grid=grid,
                      observation_time=0)
im = plot(d, selection, secondary_source, t=ts, ax=ax, vmin=-0.01, vmax=0.01)

ani = animation.FuncAnimation(
    fig, partial(update_frame_pressure, time_stamps=time_stamps),
    frames=frames, interval=interval, blit=True)
plt.close()
HTML(ani.to_jshtml())
[2]:
[3]:
# Save as gif file - This might take a few minutes.
ani.save("wfs-25d-td.gif", writer='imagemagick',fps=10, dpi=200)