Source code for doatools.estimation.preprocessing
import numpy as np
[docs]def spatial_smooth(R, l, fb=False):
"""Applies spatial smoothing to the given covariance matrix.
Spatial smoothing can decorrelate coherent sources.
Args:
R: Input covariance matrix. Both real and complex covariance matrices
are supported.
l (int): Number of subarrays. Must be an integer that is greater than 0
and less than or equal to the size of ``R``.
fb (bool): Set to ``True`` to enable forward-backward spatial smoothing.
Default value is False and only forward mode spatial smoothing is
computed.
Returns:
An (m - l + 1) x (m - l + 1) spatially-smoothed covariance matrix, where
m is the size of the input covariance matrix.
References:
[1] S. U. Pillai and B. H. Kwon, "Forward/backward spatial smoothing
techniques for coherent signal identification," IEEE Transactions on
Acoustics, Speech, and Signal Processing, vol. 37, no. 1, pp. 8-15,
Jan. 1989.
"""
m = R.shape[0]
if l < 1 or l > m:
raise ValueError('The number of subarrays must be within [1, {0}].'.format(m))
# Forward pass
Rf = R[:m-l+1, :m-l+1].copy()
for i in range(1, l):
Rf += R[i:i+m-l+1, i:i+m-l+1]
Rf /= l
if not fb:
return Rf
# Adds backward pass
if np.iscomplexobj(Rf):
return 0.5 * (Rf + np.flip(Rf).conj())
else:
return 0.5 * (Rf + np.flip(Rf))
[docs]def l1_svd(y, k):
r"""Performs :math:`l_1`-SVD to help reduce the dimensionality.
Consider the following measurement model
.. math::
\mathbf{Y} = \mathbf{A}\mathbf{X} + \mathbf{N}, (1)
where :math:`\mathbf{Y} \in \mathbb{C}^{M \times N}` is the matrix of
snapshots, :math:`\mathbf{A} \in \mathbb{C}^{M \times K}` is the steering
matrix, :math:`\mathbf{X} \in \mathbb{C}^{K \times N}` consists of source
signals, and :math:`\mathbf{N} \in \mathbb{C}^{M \times N}` consists of
additive noise.
When the number of snapshots, :math:`N`, is large, the resulting problem may
be computationally expensive to solve. Note that
:math:`\mathrm{rank}(\mathbf{A}\mathbf{X}) = K <= M`. We can
decompose :math:`\mathbf{Y}` into two parts: the part corresponding to the
signal subspace, and the part corresponding to the noise subspace. We can
keep just the part corresponding to the signal subspace to reduce the
dimensionality without losing too much information.
To do so, we compute the SVD of :math:`\mathbf{Y}` as
:math:`\mathbf{U}\mathbf{S}\mathbf{V}^H`. Let
:math:`\mathbf{T}_K = [\mathbf{I}_K \mathbf{0}]`. Multiplying both sides of
(1) by :math:`\mathbf{V} \mathbf{T}_K`, we obtain
.. math::
\mathbf{Y}_\mathrm{sv}
= \mathbf{A}\mathbf{X}_\mathrm{sv} + \mathbf{N}_\mathrm{sv}, (2)
where :math:`\mathbf{Y}_\mathrm{sv} = \mathbf{Y}\mathbf{V}\mathbf{T}_K`,
:math:`\mathbf{X}_\mathrm{sv} = \mathbf{X}\mathbf{V}\mathbf{T}_K`,
and :math:`\mathbf{N}_\mathrm{sv} = \mathbf{N}\mathbf{V}\mathbf{T}_K`.
We can then use (2) instead of (1) as our new measurement model to perform
DOA estimation.
Args:
y: The snapshot matrix, each column of which represents a single
snapshot.
k: Dimension of the signal subspace, cannot be greater than either the
number of snapshots or the number of sensors.
Returns:
The reduced measurement matrix.
References:
[1] D. Malioutov, M. Cetin, and A. S. Willsky, "A sparse signal
reconstruction perspective for source localization with sensor arrays,"
IEEE Transactions on Signal Processing, vol. 53, no. 8, pp. 3010-3022,
Aug. 2005.
"""
U, s, Vh = np.linalg.svd(y, full_matrices=False)
return U[:,:k] * s[:k]