aiaa#

Classes for importing AIAA Array Benchmarks.

These classes allow importing data from HDF5 files following the specifications of the AIAA microphone array methods benchmarking effort: https://www-docs.b-tu.de/fg-akustik/public/veroeffentlichungen/ArrayMethodsFileFormatsR2P4Release.pdf .

The classes are derived from according Acoular classes so that they can be used directly within the framework.

Examples#

>>> micgeom = MicAIAABenchmark(file='some_benchmarkdata.h5')
>>> timedata = TimeSamplesAIAABenchmark(file='some_benchmarkdata.h5')

TimeSamplesAIAABenchmark

Container for AIAA benchmark data in *.h5 format.

TriggerAIAABenchmark

Container for tacho data in *.h5 format.

CsmAIAABenchmark

Class to load the CSM that is stored in AIAA Benchmark HDF5 file.

MicAIAABenchmark

Provides the geometric arrangement of microphones in the array.

class acoular.aiaa.aiaa.TimeSamplesAIAABenchmark#

Bases: TimeSamples

Container for AIAA benchmark data in *.h5 format.

This class loads measured data from h5 files in AIAA benchmark format and and provides information about this data. Objects of this class behave similar to TimeSamples objects.

result(num=128)#

Generate blocks of time-domain data iteratively.

The result() method is a Python generator that yields blocks of time-domain data of the specified size. Data is either read from an HDF5 file (if file is set) or from a NumPy array (if data is directly provided).

Parameters:
numint, optional

The size of each block to be yielded, representing the number of time-domain samples per block.

Yields:
numpy.ndarray

A 2D array of shape (num, num_channels) representing a block of time-domain data. The last block may have fewer than num samples if the total number of samples is not a multiple of num.

Raises:
OSError

If no samples are available (i.e., num_samples is 0).

Examples

Create a generator and access blocks of data:

>>> import numpy as np
>>> from acoular.sources import TimeSamples
>>> ts = TimeSamples(data=np.random.rand(1000, 4), sample_freq=51200)
>>> generator = ts.result(num=256)
>>> for block in generator:
...     print(block.shape)
(256, 4)
(256, 4)
(256, 4)
(232, 4)

Note that the last block may have fewer that num samples.

file#

Full path to the .h5 file containing time-domain data.

basename#

Basename of the .h5 file, set automatically from the file attribute.

num_channels#

Number of input channels in the time data, set automatically based on the loaded data or specified array.

num_samples#

Total number of time-domain samples, set automatically based on the loaded data or specified array.

data#

A 2D NumPy array containing the time-domain data, shape (num_samples, num_channels).

metadata#

Metadata loaded from the HDF5 file, if available.

digest#

A unique identifier for the samples, based on its properties. (read-only)

sample_freq#

Sampling frequency of the signal, defaults to 1.0

class acoular.aiaa.aiaa.TriggerAIAABenchmark#

Bases: TimeSamplesAIAABenchmark

Container for tacho data in *.h5 format.

This class loads tacho data from h5 files as specified in “Microphone Array Benchmark b11: Rotating Point Sources” (https://doi.org/10.14279/depositonce-8460) and and provides information about this data.

result(num=128)#

Generate blocks of time-domain data iteratively.

The result() method is a Python generator that yields blocks of time-domain data of the specified size. Data is either read from an HDF5 file (if file is set) or from a NumPy array (if data is directly provided).

Parameters:
numint, optional

The size of each block to be yielded, representing the number of time-domain samples per block.

Yields:
numpy.ndarray

A 2D array of shape (num, num_channels) representing a block of time-domain data. The last block may have fewer than num samples if the total number of samples is not a multiple of num.

Raises:
OSError

If no samples are available (i.e., num_samples is 0).

Examples

Create a generator and access blocks of data:

>>> import numpy as np
>>> from acoular.sources import TimeSamples
>>> ts = TimeSamples(data=np.random.rand(1000, 4), sample_freq=51200)
>>> generator = ts.result(num=256)
>>> for block in generator:
...     print(block.shape)
(256, 4)
(256, 4)
(256, 4)
(232, 4)

Note that the last block may have fewer that num samples.

file#

Full path to the .h5 file containing time-domain data.

basename#

Basename of the .h5 file, set automatically from the file attribute.

num_channels#

Number of input channels in the time data, set automatically based on the loaded data or specified array.

num_samples#

Total number of time-domain samples, set automatically based on the loaded data or specified array.

data#

A 2D NumPy array containing the time-domain data, shape (num_samples, num_channels).

metadata#

Metadata loaded from the HDF5 file, if available.

digest#

A unique identifier for the samples, based on its properties. (read-only)

sample_freq#

Sampling frequency of the signal, defaults to 1.0

class acoular.aiaa.aiaa.CsmAIAABenchmark#

Bases: PowerSpectraImport

Class to load the CSM that is stored in AIAA Benchmark HDF5 file.

file#

Full name of the .h5 file with data

basename#

Basename of the .h5 file with data, is set automatically.

num_channels#

number of channels

digest#

A unique identifier for the CSM importer, based on its properties. (read-only)

fftfreq()#

Return the Discrete Fourier Transform sample frequencies.

Returns:
ndarray

Array of length block_size/2+1 containing the sample frequencies.

calc_csm()#

Calculate the CSM for the given source data.

This method computes the CSM by performing a block-wise Fast Fourier Transform (FFT) on the source data, applying a window function, and averaging the results. Only the upper triangular part of the matrix is computed for efficiency, and the lower triangular part is constructed via transposition and complex conjugation.

Returns:
numpy.ndarray

The computed cross spectral matrix as an array of shape (n, m, m) of complex values for n frequencies and m channels as in num_channels.

Examples

>>> import numpy as np
>>> from acoular import TimeSamples
>>> from acoular.spectra import PowerSpectra
>>>
>>> data = np.random.rand(1000, 4)
>>> ts = TimeSamples(data=data, sample_freq=51200)
>>> print(ts.num_channels, ts.num_samples, ts.sample_freq)
4 1000 51200.0
>>> ps = PowerSpectra(source=ts, block_size=128, window='Blackman')
>>> ps.csm.shape
(65, 4, 4)
calc_ev()#

Calculate eigenvalues and eigenvectors of the CSM for each frequency.

The eigenvalues represent the spectral power, and the eigenvectors correspond to the principal components of the matrix. This calculation is performed for all frequency slices of the CSM.

Returns:
tuple of numpy.ndarray
A tuple containing:
  • eva (numpy.ndarray): Eigenvalues as a 2D array of shape (n, m), where n is the number of frequencies and m is the number of channels. The datatype depends on the precision.

  • eve (numpy.ndarray): Eigenvectors as a 3D array of shape (n, m, m). The datatype is consistent with the precision of the input data.

Notes

  • The precision of the eigenvalues is determined by precision ('float64' for complex128 precision and 'float32' for complex64 precision).

  • This method assumes the CSM is already computed and accessible via csm.

Examples

>>> import numpy as np
>>> from acoular import TimeSamples
>>> from acoular.spectra import PowerSpectra
>>>
>>> data = np.random.rand(1000, 4)
>>> ts = TimeSamples(data=data, sample_freq=51200)
>>> ps = PowerSpectra(source=ts, block_size=128, window='Hanning')
>>> eva, eve = ps.calc_ev()
>>> print(eva.shape, eve.shape)
(65, 4) (65, 4, 4)
calc_eva()#

Calculate eigenvalues of the CSM.

This method computes and returns the eigenvalues of the CSM for all frequency slices.

Returns:
numpy.ndarray

A 2D array of shape (n, m) containing the eigenvalues for n frequencies and m channels. The datatype depends on precision ('float64' for complex128 precision and 'float32' for complex64 precision).

Notes

This method internally calls calc_ev() and extracts only the eigenvalues.

calc_eve()#

Calculate eigenvectors of the Cross Spectral Matrix (CSM).

This method computes and returns the eigenvectors of the CSM for all frequency slices.

Returns:
numpy.ndarray

A 3D array of shape (n, m, m) containing the eigenvectors for n frequencies and m channels. Each slice eve[f] represents an (m, m) matrix of eigenvectors for frequency f. The datatype matches the precision of the CSM (complex128 or complex64).

Notes

This method internally calls calc_ev() and extracts only the eigenvectors.

synthetic_ev(freq, num=0)#

Retrieve synthetic eigenvalues for a specified frequency or frequency range.

This method calculates the eigenvalues of the CSM for a single frequency or a synthetic frequency range. If num is set to 0, it retrieves the eigenvalues at the exact frequency. Otherwise, it averages eigenvalues across a range determined by freq and num.

Parameters:
freqfloat

The target frequency for which the eigenvalues are calculated. This is the center frequency for synthetic averaging.

numint, optional

The number of subdivisions in the logarithmic frequency space around the center frequency freq.

  • 0 (default): Only the eigenvalues for the exact frequency line are returned.

  • Non-zero:

num

frequency band width

0

single frequency line

1

octave band

3

third-octave band

n

1/n-octave band

Returns:
numpy.ndarray

An array of eigenvalues. If num == 0, the eigenvalues for the single frequency are returned. For num > 0, a summed array of eigenvalues across the synthetic frequency range is returned.

Examples

>>> import numpy as np
>>> from acoular import TimeSamples
>>> from acoular.spectra import PowerSpectra
>>> np.random.seed(0)
>>>
>>> data = np.random.rand(1000, 4)
>>> ts = TimeSamples(data=data, sample_freq=51200)
>>> ps = PowerSpectra(source=ts, block_size=128, window='Hamming')
>>> ps.synthetic_ev(freq=5000, num=5)
array([0.00048803, 0.0010141 , 0.00234248, 0.00457097])
>>> ps.synthetic_ev(freq=5000)
array([0.00022468, 0.0004589 , 0.00088059, 0.00245989])
csm#

The cross-spectral matrix stored in an array of shape (n, m, m) of complex for n frequencies and m channels.

frequencies#

The frequencies included in the CSM in ascending order. Accepts list, array, or a single float value.

source#

PowerSpectraImport does not consume time data; source is always None.

sample_freq#

Sampling frequency of the signal. Default is None

block_size#

Block size for FFT, non-functional in this class.

window#

Windowing method, non-functional in this class.

overlap#

Overlap between blocks, non-functional in this class.

cached#

Caching capability, always disabled.

num_blocks#

Number of FFT blocks, always None.

ind_low#

Index of lowest frequency line to compute. Default is 1. Only used by objects that fetch the CSM. PowerSpectra computes every frequency line.

ind_high#

Index of highest frequency line to compute. Default is -1 (last possible line for default block_size).

freq_range#

2-element array with the lowest and highest frequency. If the higher frequency is larger than the max frequency, the max frequency will be the upper bound.

indices#

The sequence of frequency indices between ind_low and ind_high. (read-only)

eva#

The eigenvalues of the CSM, stored as an array of shape (n,) of floats for n frequencies. (read-only)

eve#

The eigenvectors of the cross spectral matrix, stored as an array of shape (n, m, m) of floats for n frequencies and m channels as in num_channels. (read-only)

precision#

Precision of the FFT, corresponding to NumPy dtypes. Default is 'complex128'.

class acoular.aiaa.aiaa.MicAIAABenchmark#

Bases: MicGeom

Provides the geometric arrangement of microphones in the array.

In contrast to standard Acoular microphone geometries, the AIAA benchmark format includes the array geometry as metadata in the file containing the measurement data.

file#

Name of the .h5-file from which to read the data.

export_mpos(filename)#

Export the microphone positions to an XML file.

This method generates an XML file containing the positions of all valid microphones in the array. Each microphone is represented by a <pos> element with Name, x, y, and z attributes. The generated XML is formatted to match the structure required for importing into the MicGeom class.

Parameters:
filenamestr

The path to the file to which the microphone positions will be written. The file extension must be .xml.

Raises:
OSError

If the file cannot be written due to permissions issues or invalid file paths.

Notes

  • The file will be saved in UTF-8 encoding.

  • The Name attribute for each microphone is set as "Point {i+1}", where i is the index of the microphone.

  • This method only exports the positions of the valid microphones (those not listed in invalid_channels).

  • All coordinates (x, y, z) are exported in meters by default (see here).

pos_total#

Array containing the x, y, z positions of all microphones, including invalid ones, shape (3, num_mics ). This is set automatically when file changes or explicitly by assigning an array of floats. All coordinates are in meters by default (see here).

pos#

Array containing the x, y, z positions of valid microphones (i.e., excluding those in invalid_channels), shape (3, num_mics ). (read-only) All coordinates are in meters by default (see here).

invalid_channels#

List of indices indicating microphones to be excluded from calculations and results. Default is [].

num_mics#

Number of valid microphones in the array. (read-only)

center#

The geometric center of the array, calculated as the arithmetic mean of the positions of all valid microphones. (read-only)

aperture#

The maximum distance between any two valid microphones in the array. (read-only)

digest#

A unique identifier for the geometry, based on its properties. (read-only)