Multi-frequency & Multi-angular selection - CLEAN-T

This script is an example of use of MultiFreqCleanT Class in DeconvolutionMethods library using simulated microphone signals

  • Test Case : Moving source with rotation on 3 axes

  • Analysis : Multiple CLEAN-T run on different angular window along the trajectory and for different frequency bands

[ ]:
import numpy as np
import pylab as pl
import scipy.io as io
from cleantipy.DeconvolutionMethods import MultiFreqCleanT, CleantMap
from cleantipy.Propagation import MovingSrcSimu_t
from Sarradj_2016_array import MicArrayGeom
import time

# Set the default figure facecolor to transparent
pl.rcParams['figure.facecolor'] = 'none'
# Set the default axes facecolor to white
pl.rcParams['axes.facecolor'] = 'white'

# Set to "True" if forcing recomputation is needed
compute = False

Parameters

[2]:
pref = 2*10**-5 #Pa
fs = 10000
T = 3
Nt = int(fs*T)
t = np.arange(T*fs)/fs

fs_traj = 4 # 4 GPS points per seceonds
# fs_traj = fs # same as time samplerate
Nt_ = T*fs_traj+1
t_traj = np.arange(Nt_)/fs_traj

# Agngles setup
ang = np.array([(1-np.cos(t_traj/2))/2,0*t_traj,-(1-np.cos(t_traj/2))/3]).T

# Trajectory setup
v = 100   # m/s
Z = 150 # m
Y = 0   # m
X = np.arange(Nt_)*v/fs_traj - T*v/2    # m
traj = np.array([X,Y*np.ones(Nt_),Z*np.ones(Nt_)]).T

# Adding rotations
traj += np.array([0*np.arange(Nt_),-(1-np.cos(t_traj/2))*180/np.pi,0*np.arange(Nt_)]).T

# Micropophone array geometry setup
Nmic = 256
x, y = MicArrayGeom(Nmic,h=2)
z_array = 0

geom = np.array([x,y,z_array*np.ones((Nmic))]).T

# Source definition (position and signal)
sig = np.array([np.random.randn(Nt), # white noise
                np.sin(2*np.pi*440*2*t), # 880 Hz sine
                np.sin(2*np.pi*440*t)]) # 440 Hz sine
pos = np.array([[10,0,0],
                [0,10,0],
                [0,-10,0]]) # relative position to the trajectory

Run or load the microphone signals

[3]:

# Define simulation object simu = MovingSrcSimu_t(geom, pos, traj, t, sig, t_traj=t_traj, angles=ang, SNR=60, timeOrigin='source') simu.plot() ax = pl.gca() ax.set_xlim(-100,100) ax.set_ylim(-100,100) #%% Compute simulated pressures if compute: try: print("** Computing microphone signals **") simu.compute(parrallel=True,interpolation="quadratic") Sig = simu.p_t io.savemat('SimuAngles.mat',{'Sig':Sig}) except : tmp = io.loadmat('SimuAngles.mat',variable_names=['Sig']) Sig = tmp['Sig'] else: try: tmp = io.loadmat('SimuAngles.mat',variable_names=['Sig']) Sig = tmp['Sig'] except : print("** SimuAngles.mat not found: Computing microphone signals **") simu.compute(parrallel=True,interpolation="quadratic") Sig = simu.p_t io.savemat('SimuAngles.mat',{'Sig':Sig}) del simu
../_images/notebook_computeCleanT_multiFreq_multiAngles_5_0.png

Define reconstruction grid and angular window selection for CLEAN-T

[4]:
#%% define image plan relatively to the trajectory
Lx = 40
Ly = 40
resX = 2
resY = 2
x_F = np.arange(0,Lx,resX)-Lx/2
y_F = np.arange(0,Ly,resY)-Ly/2
z_F = 0
X_F, Y_F, Z_F = np.meshgrid(x_F,y_F,z_F)
grid = np.array([X_F.reshape(-1),Y_F.reshape(-1),Z_F.reshape(-1)]).T



#%% define angle selections
AngleWindows = np.array([[-15, -5],
                         [-5, 5]])

Set CLEAN-T object

[5]:
#%% Initialise CLEAN-T
cleant = MultiFreqCleanT(geom,grid,traj,t,Sig,ang,t_traj,debug=False,fc=[400,800],\
                         bandtype='octave',angleSelection=AngleWindows)

Compute CLEAN-T

[6]:
print('\n')
print(69*'*')
print("** Starting CLEAN-T computation on a grid following the trajectory **")
print(69*'*')

dyn = 15 # Dynamic range of results display in dB
normalisedByMax = False # if True, data are normalised by maximum, if False dislay is given in dB ref 20µPa

t1 = time.time()
cleant.ComputeCleanT(dyn = dyn,parrallel=True)
t2 = time.time()
print("CLEAN-T Computation took %.1f s"%(t2-t1))


*********************************************************************
** Starting CLEAN-T computation on a grid following the trajectory **
*********************************************************************


** Starting CLEAN-T computation over the 400 Hz octave band **
****** Angular window: -15.0--5.0° ******
0 - Residual energy: 100.0%
1 - Residual energy: 35.2%
2 - Residual energy: 5.9%
3 - Residual energy: 2.2%
Residual energy inferior to stop criterion : 5%
****** Angular window: -5.0-5.0° ******
0 - Residual energy: 100.0%
1 - Residual energy: 42.3%
2 - Residual energy: 3.5%
Residual energy inferior to stop criterion : 5%
****** Angular window: -15.0--5.0° ******
Tonal     - 89.3 dB - Pos.: x:0.0       y:-10.0 z:0.0 (rel. traj.) - E: 100.0%
Broadband - 78.8 dB - Pos.: x:10.0      y:0.0   z:0.0 (rel. traj.) - E: 35.2%
Tonal     - 71.5 dB - Pos.: x:0.0       y:-10.0 z:0.0 (rel. traj.) - E: 5.9%
****** Angular window: -5.0-5.0° ******
Tonal     - 89.1 dB - Pos.: x:0.0       y:-10.0 z:0.0 (rel. traj.) - E: 100.0%
Broadband - 80.5 dB - Pos.: x:10.0      y:0.0   z:0.0 (rel. traj.) - E: 42.3%


** Starting CLEAN-T computation over the 800 Hz octave band **
****** Angular window: -15.0--5.0° ******
0 - Residual energy: 100.0%
1 - Residual energy: 108.4%
2 - Residual energy: 60.4%
3 - Residual energy: 4.9%
Residual energy inferior to stop criterion : 5%
****** Angular window: -5.0-5.0° ******
0 - Residual energy: 100.0%
1 - Residual energy: 85.5%
2 - Residual energy: 45.0%
3 - Residual energy: 3.2%
Residual energy inferior to stop criterion : 5%
****** Angular window: -15.0--5.0° ******
Tonal     - 89.6 dB - Pos.: x:0.0       y:10.0  z:0.0 (rel. traj.) - E: 100.0%
Tonal     - 76.7 dB - Pos.: x:0.0       y:-10.0 z:0.0 (rel. traj.) - E: 108.4%
Broadband - 82.9 dB - Pos.: x:10.0      y:0.0   z:0.0 (rel. traj.) - E: 60.4%
****** Angular window: -5.0-5.0° ******
Tonal     - 89.5 dB - Pos.: x:0.0       y:10.0  z:0.0 (rel. traj.) - E: 100.0%
Tonal     - 76.6 dB - Pos.: x:0.0       y:-10.0 z:0.0 (rel. traj.) - E: 85.5%
Broadband - 82.6 dB - Pos.: x:10.0      y:0.0   z:0.0 (rel. traj.) - E: 45.0%
CLEAN-T Computation took 81.2 s

Display results

[ ]:
#%% Display results on grid along the trajectory
for ww in range(len(AngleWindows)):

    fig, axs = pl.subplots(2,len(cleant.Results),
                           constrained_layout=True,figsize=(3.5*len(cleant.Results),8.5))
    # fig.patch.set_alpha(0)
    fig.suptitle('CLEAN-T vs BF - [%.1f° , %.1f°]' \
                               %(cleant.angleSelection[ww,0],cleant.angleSelection[ww,1]))
    for ff in range(len(cleant.Results)):
        ax = axs[0,ff]
        BF_dB = cleant.Results[ff]['Sources'][0][ww]['AcousticMap'].reshape((y_F.size,x_F.size))
        mx = np.max(BF_dB)
        ax.imshow(BF_dB, vmax=mx, vmin=mx-dyn, \
                origin='lower',cmap='hot_r',\
                    extent=[x_F[0],x_F[-1],y_F[0],y_F[-1]])
        if ff==0:
            ax.set_ylabel('y (m)')
        # fig.colorbar(ax=ax)
        ax.set_title('f_c = %d Hz' %(cleant.Results[ff]['fc']))
        # pl.tight_layout()

        ax = axs[1,ff]
        CleantMap(cleant.CleanTObjects[ff],gauss=True,dyn=dyn,sameDynRange=False,adym=normalisedByMax,sigThreshold=2e-5)
        ax.set_xlabel('x (m)')
        if ff==0:
            ax.set_ylabel('y (m)')
        img = ax.imshow(cleant.CleanTObjects[ff].q_disp[ww], origin='lower',
                  extent=[x_F[0],x_F[-1],y_F[0],y_F[-1]], cmap='RdBu',
                  vmin=-dyn,vmax=dyn,interpolation_stage='data')
        cbar = fig.colorbar(img, ax=ax,\
                            ticks=[-dyn, 0, dyn],location="bottom")
        if normalisedByMax:
            cbar.ax.set_xticklabels([0, -dyn, 0])
        else:
            cbar.ax.set_xticklabels(['%.1f' %(cleant.CleanTObjects[ff].qmax_bb[ww]),\
                                 '%d' %(-dyn), '%.1f' %(cleant.CleanTObjects[ff].qmax_ton[ww])])
        # cbar.ax.set_title('[dB]')
        cbar.set_label('Broadband               Tonal       ', fontstyle='italic', labelpad=-13)
../_images/notebook_computeCleanT_multiFreq_multiAngles_13_0.png
../_images/notebook_computeCleanT_multiFreq_multiAngles_13_1.png