Source code for doatools.estimation.coarray
import numpy as np
from ..model.arrays import UniformLinearArray, GridBasedArrayDesign
from ..model.coarray import WeightFunction1D
from .core import ensure_covariance_size
from ..utils.math import vec
[docs]class CoarrayACMBuilder1D:
"""Creates a coarray-based augmented covariance matrix builder.
Based on the specified sensor array, creates a callable object that can
transform sample covariance matrices obtained from the physical array model
into augmented covariance matrices under the difference coarray model
Args:
array (~doatools.model.arrays.ArrayDesign): A 1D grid-based sensor
array. Common candidates include
:class:`~doatools.model.arrays.CoPrimeArray`,
:class:`~doatools.model.arrays.NestedArray`,
:class:`~doatools.model.arrays.MinimumRedundancyLinearArray`.
"""
def __init__(self, array):
if not isinstance(array, GridBasedArrayDesign) or array.ndim > 1:
raise ValueError('Expecting a 1D grid-based array.')
self._array = array
self._w = WeightFunction1D(array)
[docs] def __call__(self, R, method='ss'):
"""A shortcut to :meth:`transform`."""
return self.transform(R, method)
@property
def input_size(self):
"""Retrieves the size of the input covariance matrix."""
return self._array.size
@property
def output_size(self):
"""Retrieves the size of the output/transformed covariance matrix."""
return self._w.get_central_ula_size(True)
[docs] def get_virtual_ula(self, name=None):
"""Retrieves the corresponding virtual uniform linear array.
Args:
name (str): Name of the virtual uniform linear array. If not
specified, a default name will be generated.
Returns:
~doatools.model.arrays.UniformLinearArray: A uniform linear array
corresponding to the augmented covariance matrix.
"""
if name is None:
name = 'Virtual ULA of ' + self._array.name
return UniformLinearArray(self.output_size, self._array.d0, name)
[docs] def transform(self, R, method='ss'):
"""Transforms the input sample covariance matrix.
Args:
R (~numpy.ndarray): Sample covariance matrix.
method (str): ``'ss'`` for spatial-smoothing based transformation,
and ``'da'`` for direct-augmentation based transformation.
It should be noted that direct-augmentation does not guarantee
the positive-definiteness of augmented covariance matrix, which
may lead to unexpected results when using beamforming-based
estimators.
Returns:
~numpy.ndarray: The augmented covariance matrix.
References:
[1] M. Wang and A. Nehorai, "Coarrays, MUSIC, and the Cramér-Rao
Bound," *IEEE Transactions on Signal Processing*, vol. 65, no. 4,
pp. 933-946, Feb. 2017.
[2] P. Pal and P. P. Vaidyanathan, "Nested arrays: A novel approach
to array processing with enhanced degrees of freedom,"
*IEEE Transactions on Signal Processing*, vol. 58, no. 8,
pp. 4167-4181, Aug. 2010.
"""
ensure_covariance_size(R, self._array)
if method not in ['ss', 'da']:
raise ValueError('Method can only be one of the following: ss, da.')
mc = self._w.get_central_ula_size()
mv = (mc + 1) // 2
z = np.zeros((mc,), dtype=np.complex_)
r = vec(R)
for i in range(mc):
diff = i - mv + 1
z[i] = np.mean(r[self._w.indices_of(diff)])
Ra = np.zeros((mv, mv), dtype=np.complex_)
if method == 'ss':
# Spatial smoothing
for i in range(mv):
Ra += np.outer(z[i:i+mv], z[i:i+mv].conj())
Ra /= mv
else:
# Direct augmentation
for i in range(mv):
Ra[:,-(i+1)] = z[i:i+mv]
return Ra