acoular 25.4__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/__init__.py +2 -4
- acoular/aiaa/aiaa.py +10 -10
- acoular/base.py +12 -34
- acoular/calib.py +20 -19
- acoular/configuration.py +3 -3
- acoular/demo/__init__.py +6 -1
- acoular/demo/acoular_demo.py +34 -10
- acoular/deprecation.py +10 -1
- acoular/environments.py +107 -117
- acoular/fastFuncs.py +16 -10
- acoular/fbeamform.py +300 -402
- acoular/fprocess.py +7 -33
- acoular/grids.py +228 -134
- acoular/h5cache.py +10 -4
- acoular/h5files.py +106 -9
- acoular/internal.py +4 -0
- acoular/microphones.py +22 -10
- acoular/process.py +7 -53
- acoular/sdinput.py +8 -5
- acoular/signals.py +29 -27
- acoular/sources.py +205 -335
- acoular/spectra.py +33 -43
- acoular/tbeamform.py +220 -199
- acoular/tools/helpers.py +52 -33
- acoular/tools/metrics.py +5 -10
- acoular/tprocess.py +1392 -647
- acoular/traitsviews.py +1 -3
- acoular/trajectory.py +5 -5
- acoular/version.py +4 -3
- {acoular-25.4.dist-info → acoular-25.10.dist-info}/METADATA +8 -4
- acoular-25.10.dist-info/RECORD +56 -0
- acoular-25.4.dist-info/RECORD +0 -56
- {acoular-25.4.dist-info → acoular-25.10.dist-info}/WHEEL +0 -0
- {acoular-25.4.dist-info → acoular-25.10.dist-info}/licenses/AUTHORS.rst +0 -0
- {acoular-25.4.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,8 +47,6 @@ from .internal import digest
|
|
|
61
47
|
from .tools.utils import find_basename
|
|
62
48
|
|
|
63
49
|
|
|
64
|
-
@deprecated_alias({'numchannels': 'num_channels'}, read_only=True)
|
|
65
|
-
@deprecated_alias({'time_data': 'source'}, read_only=False)
|
|
66
50
|
class BaseSpectra(ABCHasStrictTraits):
|
|
67
51
|
"""
|
|
68
52
|
Base class for handling spectral data in Acoular.
|
|
@@ -93,7 +77,13 @@ class BaseSpectra(ABCHasStrictTraits):
|
|
|
93
77
|
#:
|
|
94
78
|
#: - ``'Blackman'``
|
|
95
79
|
window = Map(
|
|
96
|
-
{
|
|
80
|
+
{
|
|
81
|
+
'Rectangular': np.ones,
|
|
82
|
+
'Hanning': np.hanning,
|
|
83
|
+
'Hamming': np.hamming,
|
|
84
|
+
'Bartlett': np.bartlett,
|
|
85
|
+
'Blackman': np.blackman,
|
|
86
|
+
},
|
|
97
87
|
default_value='Rectangular',
|
|
98
88
|
desc='type of window for FFT',
|
|
99
89
|
)
|
|
@@ -180,7 +170,7 @@ class BaseSpectra(ABCHasStrictTraits):
|
|
|
180
170
|
# generator that yields the time data blocks for every channel (with optional overlap)
|
|
181
171
|
def _get_source_data(self):
|
|
182
172
|
bs = self.block_size
|
|
183
|
-
temp = empty((2 * bs, self.num_channels))
|
|
173
|
+
temp = np.empty((2 * bs, self.num_channels))
|
|
184
174
|
pos = bs
|
|
185
175
|
posinc = bs / self.overlap_
|
|
186
176
|
for data_block in self.source.result(bs):
|
|
@@ -292,7 +282,7 @@ class PowerSpectra(BaseSpectra):
|
|
|
292
282
|
fftfreq = self.fftfreq()
|
|
293
283
|
if fftfreq is not None:
|
|
294
284
|
if self._ind_high is None:
|
|
295
|
-
return array([fftfreq[self.ind_low], None])
|
|
285
|
+
return np.array([fftfreq[self.ind_low], None])
|
|
296
286
|
return fftfreq[[self.ind_low, self.ind_high]]
|
|
297
287
|
return None
|
|
298
288
|
|
|
@@ -308,7 +298,7 @@ class PowerSpectra(BaseSpectra):
|
|
|
308
298
|
if fftfreq is not None:
|
|
309
299
|
if self._index_set_last:
|
|
310
300
|
return min(self._ind_low, fftfreq.shape[0] - 1)
|
|
311
|
-
return searchsorted(fftfreq[:-1], self._freqlc)
|
|
301
|
+
return np.searchsorted(fftfreq[:-1], self._freqlc)
|
|
312
302
|
return 0
|
|
313
303
|
|
|
314
304
|
@property_depends_on(['source.sample_freq', 'block_size', '_ind_high', '_freqhc'])
|
|
@@ -321,7 +311,7 @@ class PowerSpectra(BaseSpectra):
|
|
|
321
311
|
return min(self._ind_high, fftfreq.shape[0] - 1)
|
|
322
312
|
if self._freqhc is None:
|
|
323
313
|
return None
|
|
324
|
-
return searchsorted(fftfreq[:-1], self._freqhc)
|
|
314
|
+
return np.searchsorted(fftfreq[:-1], self._freqhc)
|
|
325
315
|
return None
|
|
326
316
|
|
|
327
317
|
def _set_ind_high(self, ind_high): # by setting this the user sets the lower index
|
|
@@ -337,7 +327,7 @@ class PowerSpectra(BaseSpectra):
|
|
|
337
327
|
fftfreq = self.fftfreq()
|
|
338
328
|
if fftfreq is not None:
|
|
339
329
|
try:
|
|
340
|
-
indices = arange(fftfreq.shape[0], dtype=int)
|
|
330
|
+
indices = np.arange(fftfreq.shape[0], dtype=int)
|
|
341
331
|
if self.ind_high is None:
|
|
342
332
|
return indices[self.ind_low :]
|
|
343
333
|
return indices[self.ind_low : self.ind_high]
|
|
@@ -384,18 +374,18 @@ class PowerSpectra(BaseSpectra):
|
|
|
384
374
|
"""
|
|
385
375
|
t = self.source
|
|
386
376
|
wind = self.window_(self.block_size)
|
|
387
|
-
weight = dot(wind, wind)
|
|
388
|
-
wind = wind[newaxis, :].swapaxes(0, 1)
|
|
377
|
+
weight = np.dot(wind, wind)
|
|
378
|
+
wind = wind[np.newaxis, :].swapaxes(0, 1)
|
|
389
379
|
numfreq = int(self.block_size / 2 + 1)
|
|
390
380
|
csm_shape = (numfreq, t.num_channels, t.num_channels)
|
|
391
|
-
csm_upper = zeros(csm_shape, dtype=self.precision)
|
|
381
|
+
csm_upper = np.zeros(csm_shape, dtype=self.precision)
|
|
392
382
|
# get time data blockwise
|
|
393
383
|
for data in self._get_source_data():
|
|
394
384
|
ft = fft.rfft(data * wind, None, 0).astype(self.precision)
|
|
395
385
|
calcCSM(csm_upper, ft) # only upper triangular part of matrix is calculated (for speed reasons)
|
|
396
386
|
# create the full csm matrix via transposing and complex conj.
|
|
397
387
|
csm_lower = csm_upper.conj().transpose(0, 2, 1)
|
|
398
|
-
[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])]
|
|
399
389
|
csm = csm_lower + csm_upper
|
|
400
390
|
# onesided spectrum: multiplication by 2.0=sqrt(2)^2
|
|
401
391
|
return csm * (2.0 / self.block_size / weight / self.num_blocks)
|
|
@@ -444,10 +434,10 @@ class PowerSpectra(BaseSpectra):
|
|
|
444
434
|
eva_dtype = 'float32'
|
|
445
435
|
# csm = self.csm #trigger calculation
|
|
446
436
|
csm_shape = self.csm.shape
|
|
447
|
-
eva = empty(csm_shape[0:2], dtype=eva_dtype)
|
|
448
|
-
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)
|
|
449
439
|
for i in range(csm_shape[0]):
|
|
450
|
-
(eva[i], eve[i]) = linalg.eigh(self.csm[i])
|
|
440
|
+
(eva[i], eve[i]) = np.linalg.eigh(self.csm[i])
|
|
451
441
|
return (eva, eve)
|
|
452
442
|
|
|
453
443
|
def calc_eva(self):
|
|
@@ -604,12 +594,12 @@ class PowerSpectra(BaseSpectra):
|
|
|
604
594
|
f = self.fftfreq()
|
|
605
595
|
if num == 0:
|
|
606
596
|
# single frequency line
|
|
607
|
-
return self.eva[searchsorted(f, freq)]
|
|
608
|
-
f1 = searchsorted(f, freq * 2.0 ** (-0.5 / num))
|
|
609
|
-
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))
|
|
610
600
|
if f1 == f2:
|
|
611
601
|
return self.eva[f1]
|
|
612
|
-
return sum(self.eva[f1:f2], 0)
|
|
602
|
+
return np.sum(self.eva[f1:f2], 0)
|
|
613
603
|
|
|
614
604
|
|
|
615
605
|
class PowerSpectraImport(PowerSpectra):
|
|
@@ -695,7 +685,7 @@ class PowerSpectraImport(PowerSpectra):
|
|
|
695
685
|
(number of frequencies, num_channels, num_channels)!'
|
|
696
686
|
raise ValueError(msg)
|
|
697
687
|
self._csm = csm
|
|
698
|
-
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
|
|
699
689
|
|
|
700
690
|
@property_depends_on(['digest'])
|
|
701
691
|
def _get_eva(self):
|
|
@@ -718,7 +708,7 @@ class PowerSpectraImport(PowerSpectra):
|
|
|
718
708
|
Array containing the frequencies.
|
|
719
709
|
"""
|
|
720
710
|
if isinstance(self.frequencies, float):
|
|
721
|
-
return array([self.frequencies])
|
|
722
|
-
if isinstance(self.frequencies, ndarray):
|
|
711
|
+
return np.array([self.frequencies])
|
|
712
|
+
if isinstance(self.frequencies, np.ndarray):
|
|
723
713
|
return self.frequencies
|
|
724
714
|
return self.frequencies
|