acoular 25.7__py3-none-any.whl → 25.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acoular/aiaa/aiaa.py +7 -9
- acoular/base.py +6 -9
- acoular/calib.py +19 -18
- acoular/configuration.py +2 -2
- acoular/environments.py +102 -113
- acoular/fbeamform.py +296 -301
- acoular/fprocess.py +7 -4
- acoular/grids.py +98 -111
- acoular/h5cache.py +5 -1
- acoular/h5files.py +96 -9
- acoular/microphones.py +22 -27
- acoular/process.py +7 -11
- acoular/sdinput.py +0 -5
- acoular/signals.py +29 -27
- acoular/sources.py +189 -322
- acoular/spectra.py +33 -44
- acoular/tbeamform.py +217 -199
- acoular/tools/helpers.py +25 -33
- acoular/tools/metrics.py +5 -10
- acoular/tprocess.py +173 -209
- acoular/trajectory.py +5 -5
- acoular/version.py +2 -2
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/METADATA +6 -2
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/RECORD +27 -27
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/WHEEL +0 -0
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/licenses/AUTHORS.rst +0 -0
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/licenses/LICENSE +0 -0
acoular/spectra.py
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
# ------------------------------------------------------------------------------
|
|
4
4
|
"""Estimation of power spectra and related tools.
|
|
5
5
|
|
|
6
|
+
.. inheritance-diagram::
|
|
7
|
+
acoular.spectra
|
|
8
|
+
:top-classes:
|
|
9
|
+
acoular.spectra.BaseSpectra
|
|
10
|
+
:parts: 1
|
|
11
|
+
|
|
6
12
|
.. autosummary::
|
|
7
13
|
:toctree: generated/
|
|
8
14
|
|
|
@@ -13,26 +19,7 @@
|
|
|
13
19
|
|
|
14
20
|
from abc import abstractmethod
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
arange,
|
|
18
|
-
array,
|
|
19
|
-
bartlett,
|
|
20
|
-
blackman,
|
|
21
|
-
dot,
|
|
22
|
-
empty,
|
|
23
|
-
fill_diagonal,
|
|
24
|
-
hamming,
|
|
25
|
-
hanning,
|
|
26
|
-
imag,
|
|
27
|
-
linalg,
|
|
28
|
-
ndarray,
|
|
29
|
-
newaxis,
|
|
30
|
-
ones,
|
|
31
|
-
real,
|
|
32
|
-
searchsorted,
|
|
33
|
-
sum, # noqa A004
|
|
34
|
-
zeros,
|
|
35
|
-
)
|
|
22
|
+
import numpy as np
|
|
36
23
|
from scipy import fft
|
|
37
24
|
from traits.api import (
|
|
38
25
|
ABCHasStrictTraits,
|
|
@@ -53,7 +40,6 @@ from traits.api import (
|
|
|
53
40
|
# acoular imports
|
|
54
41
|
from .base import SamplesGenerator
|
|
55
42
|
from .configuration import config
|
|
56
|
-
from .deprecation import deprecated_alias
|
|
57
43
|
from .fastFuncs import calcCSM
|
|
58
44
|
from .h5cache import H5cache
|
|
59
45
|
from .h5files import H5CacheFileBase
|
|
@@ -61,9 +47,6 @@ from .internal import digest
|
|
|
61
47
|
from .tools.utils import find_basename
|
|
62
48
|
|
|
63
49
|
|
|
64
|
-
@deprecated_alias(
|
|
65
|
-
{'numchannels': 'num_channels', 'time_data': 'source'}, read_only=['numchannels'], removal_version='25.10'
|
|
66
|
-
)
|
|
67
50
|
class BaseSpectra(ABCHasStrictTraits):
|
|
68
51
|
"""
|
|
69
52
|
Base class for handling spectral data in Acoular.
|
|
@@ -94,7 +77,13 @@ class BaseSpectra(ABCHasStrictTraits):
|
|
|
94
77
|
#:
|
|
95
78
|
#: - ``'Blackman'``
|
|
96
79
|
window = Map(
|
|
97
|
-
{
|
|
80
|
+
{
|
|
81
|
+
'Rectangular': np.ones,
|
|
82
|
+
'Hanning': np.hanning,
|
|
83
|
+
'Hamming': np.hamming,
|
|
84
|
+
'Bartlett': np.bartlett,
|
|
85
|
+
'Blackman': np.blackman,
|
|
86
|
+
},
|
|
98
87
|
default_value='Rectangular',
|
|
99
88
|
desc='type of window for FFT',
|
|
100
89
|
)
|
|
@@ -181,7 +170,7 @@ class BaseSpectra(ABCHasStrictTraits):
|
|
|
181
170
|
# generator that yields the time data blocks for every channel (with optional overlap)
|
|
182
171
|
def _get_source_data(self):
|
|
183
172
|
bs = self.block_size
|
|
184
|
-
temp = empty((2 * bs, self.num_channels))
|
|
173
|
+
temp = np.empty((2 * bs, self.num_channels))
|
|
185
174
|
pos = bs
|
|
186
175
|
posinc = bs / self.overlap_
|
|
187
176
|
for data_block in self.source.result(bs):
|
|
@@ -293,7 +282,7 @@ class PowerSpectra(BaseSpectra):
|
|
|
293
282
|
fftfreq = self.fftfreq()
|
|
294
283
|
if fftfreq is not None:
|
|
295
284
|
if self._ind_high is None:
|
|
296
|
-
return array([fftfreq[self.ind_low], None])
|
|
285
|
+
return np.array([fftfreq[self.ind_low], None])
|
|
297
286
|
return fftfreq[[self.ind_low, self.ind_high]]
|
|
298
287
|
return None
|
|
299
288
|
|
|
@@ -309,7 +298,7 @@ class PowerSpectra(BaseSpectra):
|
|
|
309
298
|
if fftfreq is not None:
|
|
310
299
|
if self._index_set_last:
|
|
311
300
|
return min(self._ind_low, fftfreq.shape[0] - 1)
|
|
312
|
-
return searchsorted(fftfreq[:-1], self._freqlc)
|
|
301
|
+
return np.searchsorted(fftfreq[:-1], self._freqlc)
|
|
313
302
|
return 0
|
|
314
303
|
|
|
315
304
|
@property_depends_on(['source.sample_freq', 'block_size', '_ind_high', '_freqhc'])
|
|
@@ -322,7 +311,7 @@ class PowerSpectra(BaseSpectra):
|
|
|
322
311
|
return min(self._ind_high, fftfreq.shape[0] - 1)
|
|
323
312
|
if self._freqhc is None:
|
|
324
313
|
return None
|
|
325
|
-
return searchsorted(fftfreq[:-1], self._freqhc)
|
|
314
|
+
return np.searchsorted(fftfreq[:-1], self._freqhc)
|
|
326
315
|
return None
|
|
327
316
|
|
|
328
317
|
def _set_ind_high(self, ind_high): # by setting this the user sets the lower index
|
|
@@ -338,7 +327,7 @@ class PowerSpectra(BaseSpectra):
|
|
|
338
327
|
fftfreq = self.fftfreq()
|
|
339
328
|
if fftfreq is not None:
|
|
340
329
|
try:
|
|
341
|
-
indices = arange(fftfreq.shape[0], dtype=int)
|
|
330
|
+
indices = np.arange(fftfreq.shape[0], dtype=int)
|
|
342
331
|
if self.ind_high is None:
|
|
343
332
|
return indices[self.ind_low :]
|
|
344
333
|
return indices[self.ind_low : self.ind_high]
|
|
@@ -385,18 +374,18 @@ class PowerSpectra(BaseSpectra):
|
|
|
385
374
|
"""
|
|
386
375
|
t = self.source
|
|
387
376
|
wind = self.window_(self.block_size)
|
|
388
|
-
weight = dot(wind, wind)
|
|
389
|
-
wind = wind[newaxis, :].swapaxes(0, 1)
|
|
377
|
+
weight = np.dot(wind, wind)
|
|
378
|
+
wind = wind[np.newaxis, :].swapaxes(0, 1)
|
|
390
379
|
numfreq = int(self.block_size / 2 + 1)
|
|
391
380
|
csm_shape = (numfreq, t.num_channels, t.num_channels)
|
|
392
|
-
csm_upper = zeros(csm_shape, dtype=self.precision)
|
|
381
|
+
csm_upper = np.zeros(csm_shape, dtype=self.precision)
|
|
393
382
|
# get time data blockwise
|
|
394
383
|
for data in self._get_source_data():
|
|
395
384
|
ft = fft.rfft(data * wind, None, 0).astype(self.precision)
|
|
396
385
|
calcCSM(csm_upper, ft) # only upper triangular part of matrix is calculated (for speed reasons)
|
|
397
386
|
# create the full csm matrix via transposing and complex conj.
|
|
398
387
|
csm_lower = csm_upper.conj().transpose(0, 2, 1)
|
|
399
|
-
[fill_diagonal(csm_lower[cntFreq, :, :], 0) for cntFreq in range(csm_lower.shape[0])]
|
|
388
|
+
[np.fill_diagonal(csm_lower[cntFreq, :, :], 0) for cntFreq in range(csm_lower.shape[0])]
|
|
400
389
|
csm = csm_lower + csm_upper
|
|
401
390
|
# onesided spectrum: multiplication by 2.0=sqrt(2)^2
|
|
402
391
|
return csm * (2.0 / self.block_size / weight / self.num_blocks)
|
|
@@ -445,10 +434,10 @@ class PowerSpectra(BaseSpectra):
|
|
|
445
434
|
eva_dtype = 'float32'
|
|
446
435
|
# csm = self.csm #trigger calculation
|
|
447
436
|
csm_shape = self.csm.shape
|
|
448
|
-
eva = empty(csm_shape[0:2], dtype=eva_dtype)
|
|
449
|
-
eve = empty(csm_shape, dtype=self.precision)
|
|
437
|
+
eva = np.empty(csm_shape[0:2], dtype=eva_dtype)
|
|
438
|
+
eve = np.empty(csm_shape, dtype=self.precision)
|
|
450
439
|
for i in range(csm_shape[0]):
|
|
451
|
-
(eva[i], eve[i]) = linalg.eigh(self.csm[i])
|
|
440
|
+
(eva[i], eve[i]) = np.linalg.eigh(self.csm[i])
|
|
452
441
|
return (eva, eve)
|
|
453
442
|
|
|
454
443
|
def calc_eva(self):
|
|
@@ -605,12 +594,12 @@ class PowerSpectra(BaseSpectra):
|
|
|
605
594
|
f = self.fftfreq()
|
|
606
595
|
if num == 0:
|
|
607
596
|
# single frequency line
|
|
608
|
-
return self.eva[searchsorted(f, freq)]
|
|
609
|
-
f1 = searchsorted(f, freq * 2.0 ** (-0.5 / num))
|
|
610
|
-
f2 = searchsorted(f, freq * 2.0 ** (0.5 / num))
|
|
597
|
+
return self.eva[np.searchsorted(f, freq)]
|
|
598
|
+
f1 = np.searchsorted(f, freq * 2.0 ** (-0.5 / num))
|
|
599
|
+
f2 = np.searchsorted(f, freq * 2.0 ** (0.5 / num))
|
|
611
600
|
if f1 == f2:
|
|
612
601
|
return self.eva[f1]
|
|
613
|
-
return sum(self.eva[f1:f2], 0)
|
|
602
|
+
return np.sum(self.eva[f1:f2], 0)
|
|
614
603
|
|
|
615
604
|
|
|
616
605
|
class PowerSpectraImport(PowerSpectra):
|
|
@@ -696,7 +685,7 @@ class PowerSpectraImport(PowerSpectra):
|
|
|
696
685
|
(number of frequencies, num_channels, num_channels)!'
|
|
697
686
|
raise ValueError(msg)
|
|
698
687
|
self._csm = csm
|
|
699
|
-
self._csmsum = real(self._csm).sum() + (imag(self._csm) ** 2).sum() # to trigger new digest creation
|
|
688
|
+
self._csmsum = np.real(self._csm).sum() + (np.imag(self._csm) ** 2).sum() # to trigger new digest creation
|
|
700
689
|
|
|
701
690
|
@property_depends_on(['digest'])
|
|
702
691
|
def _get_eva(self):
|
|
@@ -719,7 +708,7 @@ class PowerSpectraImport(PowerSpectra):
|
|
|
719
708
|
Array containing the frequencies.
|
|
720
709
|
"""
|
|
721
710
|
if isinstance(self.frequencies, float):
|
|
722
|
-
return array([self.frequencies])
|
|
723
|
-
if isinstance(self.frequencies, ndarray):
|
|
711
|
+
return np.array([self.frequencies])
|
|
712
|
+
if isinstance(self.frequencies, np.ndarray):
|
|
724
713
|
return self.frequencies
|
|
725
714
|
return self.frequencies
|