Acoular 24.10 documentation

Airfoil in open jet – Time domain beamforming methods.

«  Sector Integration Example   ::   Wind tunnel examples   ::   Moving sources examples  »

Airfoil in open jet – Time domain beamforming methods.

Demonstrates different microphone array methods operating in the time domain. Uses measured data in file example_data.h5, calibration in file example_calib.xml, microphone geometry in array_56.xml (part of Acoular).

import urllib
from pathlib import Path

import acoular as ac
import numpy as np

The 4 kHz third-octave band is used for the example.

cfreq = 4000
num = 3
calib_file = Path('../data/example_calib.xml')
if not calib_file.exists():
    calib_file = Path().cwd() / 'example_calib.xml'
    if not calib_file.exists():
        print('Cannot find calibration file. Downloading...')
        url = 'https://github.com/acoular/acoular/tree/master/examples/data/example_calib.xml'
        urllib.request.urlretrieve(url, calib_file)
    print(f'Calibration file location: {calib_file}')

time_data_file = Path('../data/example_data.h5')
if not time_data_file.exists():
    time_data_file = Path().cwd() / 'example_data.h5'
    if not time_data_file.exists():
        print('Cannot find example_data.h5 file. Downloading...')
        url = 'https://github.com/acoular/acoular/tree/master/examples/data/example_data.h5'
        time_data_file, _ = urllib.request.urlretrieve(url, time_data_file)
    print(f'Time data file location: {time_data_file}')

Setting up the processing chain for the time domain methods.

Hint

An in-depth explanation for setting up the time data, microphone geometry, environment and steering vector is given in the example Airfoil in open jet – steering vectors..

ts = ac.MaskedTimeSamples(
    name=time_data_file,
    invalid_channels=[1, 7],
    start=0,
    stop=16000,
    calib=ac.Calib(from_file=calib_file),
)
mics = ac.MicGeom(from_file=Path(ac.__file__).parent / 'xml' / 'array_56.xml', invalid_channels=[1, 7])
grid = ac.RectGrid(x_min=-0.6, x_max=-0.0, y_min=-0.3, y_max=0.3, z=0.68, increment=0.05)
env = ac.Environment(c=346.04)
st = ac.SteeringVector(grid=grid, mics=mics, env=env)

First, classic delay-and-sum beamforming in time domain is set up using the acoular.tbeamform.BeamformerTime class. To produce an image of the sound sources, the beamformer time signal output for each grid-point is zero-phase filtered, squared and block-wise averaged over time. The result is cached to disk to prevent recalculation.

bt = ac.BeamformerTime(source=ts, steer=st)
ft = ac.FiltFiltOctave(source=bt, band=cfreq)
pt = ac.TimePower(source=ft)
avgt = ac.Average(source=pt, naverage=1024)
cacht = ac.Cache(source=avgt)  # cache to prevent recalculation

Second, by using the acoular.tbeamform.BeamformerTimeSq class, the squared output of the beamformer is calculated directly. It also allows for the removal of the autocorrelation, which is similar to the removal of the cross spectral matrix diagonal.

fi = ac.FiltFiltOctave(source=ts, band=cfreq)
bts = ac.BeamformerTimeSq(source=fi, steer=st, r_diag=True)
avgts = ac.Average(source=bts, naverage=1024)
cachts = ac.Cache(source=avgts)  # cache to prevent recalculation

Third, CLEAN deconvolution in the time domain (CLEAN-T) is applied, using the acoular.tbeamform.BeamformerCleant class.

fct = ac.FiltFiltOctave(source=ts, band=cfreq)
bct = ac.BeamformerCleant(source=fct, steer=st, n_iter=20, damp=0.7)
ptct = ac.TimePower(source=bct)
avgct = ac.Average(source=ptct, naverage=1024)
cachct = ac.Cache(source=avgct)  # cache to prevent recalculation

Finally, squared signals with autocorrelation removal can be obtained by using the acoular.tbeamform.BeamformerCleantSq class.

fcts = ac.FiltFiltOctave(source=ts, band=cfreq)
bcts = ac.BeamformerCleantSq(source=fcts, steer=st, n_iter=20, damp=0.7, r_diag=True)
avgcts = ac.Average(source=bcts, naverage=1024)
cachcts = ac.Cache(source=avgcts)  # cache to prevent recalculation

Plot result maps for different beamformers in time domain

from pylab import colorbar, figure, imshow, show, subplot, tight_layout, title

ftitles = ['BeamformerTime', 'BeamformerTimeSq', 'BeamformerCleant', 'BeamformerCleantSq']
i2 = 1  # no of figure
i1 = 1  # no of subplot
for b in (cacht, cachts, cachct, cachcts):
    # first, plot time-dependent result (block-wise)
    fig = figure(i2, (7, 7))
    fig.suptitle(f'{ftitles[i2 - 1]}: block-wise source maps (f={cfreq} Hz)')
    i2 += 1
    res = np.zeros(grid.size)  # init accumulator for average
    i3 = 1  # no of subplot
    for r in b.result(1):  # one single block
        subplot(4, 4, i3)
        i3 += 1
        res += r[0]  # average accum.
        map = r[0].reshape(grid.shape)
        mx = ac.L_p(map.max())
        imshow(ac.L_p(map.T), vmax=mx, vmin=mx - 15, origin='lower', interpolation='nearest', extent=grid.extend())
        title('%i' % ((i3 - 1) * 1024))
    res /= i3 - 1  # average
    tight_layout()

    # second, plot overall result (average over all blocks)
    fig = figure(10, (8, 2))
    fig.suptitle(f'Averaged source maps (f={cfreq} Hz)')
    subplot(1, 4, i1)
    i1 += 1
    map = res.reshape(grid.shape)
    mx = ac.L_p(map.max())
    imshow(ac.L_p(map.T), vmax=mx, vmin=mx - 15, origin='lower', interpolation='nearest', extent=grid.extend())
    colorbar(shrink=0.5)
    title(('BeamformerTime', 'BeamformerTimeSq', 'BeamformerCleant', 'BeamformerCleantSq')[i2 - 2])
tight_layout()
show()
[('example_data_cache.h5', 20)]
[('example_data_cache.h5', 21)]
[('example_data_cache.h5', 22)]
[('example_data_cache.h5', 23)]

Total running time of the script: (0 minutes 12.032 seconds)

Gallery generated by Sphinx-Gallery

«  Sector Integration Example   ::   Wind tunnel examples   ::   Moving sources examples  »