acoular 25.7__py3-none-any.whl → 26.1__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/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
- from numpy import (
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,9 +77,14 @@ class BaseSpectra(ABCHasStrictTraits):
94
77
  #:
95
78
  #: - ``'Blackman'``
96
79
  window = Map(
97
- {'Rectangular': ones, 'Hanning': hanning, 'Hamming': hamming, 'Bartlett': bartlett, 'Blackman': blackman},
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
- desc='type of window for FFT',
100
88
  )
101
89
 
102
90
  #: Overlap factor for FFT block averaging. One of:
@@ -108,7 +96,7 @@ class BaseSpectra(ABCHasStrictTraits):
108
96
  #: - ``'75%'``
109
97
  #:
110
98
  #: - ``'87.5%'``
111
- overlap = Map({'None': 1, '50%': 2, '75%': 4, '87.5%': 8}, default_value='None', desc='overlap of FFT blocks')
99
+ overlap = Map({'None': 1, '50%': 2, '75%': 4, '87.5%': 8}, default_value='None')
112
100
 
113
101
  #: FFT block size. Must be one of: ``128``, ``256``, ``512``, ``1024``, ... ``65536``.
114
102
  #: Default is ``1024``.
@@ -123,11 +111,10 @@ class BaseSpectra(ABCHasStrictTraits):
123
111
  16384,
124
112
  32768,
125
113
  65536,
126
- desc='number of samples per FFT block',
127
114
  )
128
115
 
129
116
  #: Precision of the FFT, corresponding to NumPy dtypes. Default is ``'complex128'``.
130
- precision = Enum('complex128', 'complex64', desc='precision of the fft')
117
+ precision = Enum('complex128', 'complex64')
131
118
 
132
119
  #: A unique identifier for the spectra, based on its properties. (read-only)
133
120
  digest = Property(depends_on=['precision', 'block_size', 'window', 'overlap'])
@@ -181,7 +168,7 @@ class BaseSpectra(ABCHasStrictTraits):
181
168
  # generator that yields the time data blocks for every channel (with optional overlap)
182
169
  def _get_source_data(self):
183
170
  bs = self.block_size
184
- temp = empty((2 * bs, self.num_channels))
171
+ temp = np.empty((2 * bs, self.num_channels))
185
172
  pos = bs
186
173
  posinc = bs / self.overlap_
187
174
  for data_block in self.source.result(bs):
@@ -218,19 +205,16 @@ class PowerSpectra(BaseSpectra):
218
205
  #: :class:`SamplesGenerator<acoular.base.SamplesGenerator>` or a derived class.
219
206
  source = Instance(SamplesGenerator)
220
207
 
221
- # Shadow trait, should not be set directly, for internal use.
222
- _ind_low = Int(1, desc='index of lowest frequency line')
223
-
224
- # Shadow trait, should not be set directly, for internal use.
225
- _ind_high = Union(Int(-1), None, desc='index of highest frequency line')
208
+ _ind_low = Int(1)
209
+ _ind_high = Union(Int(-1), None)
226
210
 
227
211
  #: Index of lowest frequency line to compute. Default is ``1``. Only used by objects that fetch
228
212
  #: the CSM. PowerSpectra computes every frequency line.
229
- ind_low = Property(_ind_low, desc='index of lowest frequency line')
213
+ ind_low = Property(_ind_low)
230
214
 
231
215
  #: Index of highest frequency line to compute. Default is ``-1``
232
216
  #: (last possible line for default :attr:`~BaseSpectra.block_size`).
233
- ind_high = Property(_ind_high, desc='index of lowest frequency line')
217
+ ind_high = Property(_ind_high)
234
218
 
235
219
  # Stores the set lower frequency, for internal use, should not be set directly.
236
220
  _freqlc = Float(0)
@@ -244,37 +228,37 @@ class PowerSpectra(BaseSpectra):
244
228
  _index_set_last = Bool(True)
245
229
 
246
230
  #: A flag indicating whether the result should be cached in HDF5 files. Default is ``True``.
247
- cached = Bool(True, desc='cached flag')
231
+ cached = Bool(True)
248
232
 
249
233
  #: The number of FFT blocks used for averaging. This is derived from the
250
234
  #: :attr:`~BaseSpectra.block_size` and :attr:`~BaseSpectra.overlap` parameters. (read-only)
251
- num_blocks = Property(desc='overall number of FFT blocks')
235
+ num_blocks = Property()
252
236
 
253
237
  #: 2-element array with the lowest and highest frequency. If the higher frequency is larger than
254
238
  #: the max frequency, the max frequency will be the upper bound.
255
- freq_range = Property(desc='frequency range')
239
+ freq_range = Property()
256
240
  # If set, will overwrite :attr:`_freqlc` and :attr:`_freqhc` according to the range. The
257
241
  # freq_range interval will be the smallest discrete frequency inside the half-open interval
258
242
  # [_freqlc, _freqhc[ and the smallest upper frequency outside of the interval.
259
243
 
260
244
  #: The sequence of frequency indices between :attr:`ind_low` and :attr:`ind_high`. (read-only)
261
- indices = Property(desc='index range')
245
+ indices = Property()
262
246
 
263
247
  #: The name of the cache file (without the file extension) used for storing results. (read-only)
264
- basename = Property(depends_on=['source.digest'], desc='basename for cache file')
248
+ basename = Property(depends_on=['source.digest'])
265
249
 
266
250
  #: The cross-spectral matrix, represented as an array of shape ``(n, m, m)`` of complex values
267
251
  #: for ``n`` frequencies and ``m`` channels as in :attr:`~BaseSpectra.num_channels`. (read-only)
268
- csm = Property(desc='cross spectral matrix')
252
+ csm = Property()
269
253
 
270
254
  #: The eigenvalues of the CSM, stored as an array of shape ``(n,)`` of floats for ``n``
271
255
  #: frequencies. (read-only)
272
- eva = Property(desc='eigenvalues of cross spectral matrix')
256
+ eva = Property()
273
257
 
274
258
  #: The eigenvectors of the cross spectral matrix, stored as an array of shape ``(n, m, m)`` of
275
259
  #: floats for ``n`` frequencies and ``m`` channels as in :attr:`~BaseSpectra.num_channels`.
276
260
  #: (read-only)
277
- eve = Property(desc='eigenvectors of cross spectral matrix')
261
+ eve = Property()
278
262
 
279
263
  #: A unique identifier for the spectra, based on its properties. (read-only)
280
264
  digest = Property(
@@ -293,7 +277,7 @@ class PowerSpectra(BaseSpectra):
293
277
  fftfreq = self.fftfreq()
294
278
  if fftfreq is not None:
295
279
  if self._ind_high is None:
296
- return array([fftfreq[self.ind_low], None])
280
+ return np.array([fftfreq[self.ind_low], None])
297
281
  return fftfreq[[self.ind_low, self.ind_high]]
298
282
  return None
299
283
 
@@ -309,7 +293,7 @@ class PowerSpectra(BaseSpectra):
309
293
  if fftfreq is not None:
310
294
  if self._index_set_last:
311
295
  return min(self._ind_low, fftfreq.shape[0] - 1)
312
- return searchsorted(fftfreq[:-1], self._freqlc)
296
+ return np.searchsorted(fftfreq[:-1], self._freqlc)
313
297
  return 0
314
298
 
315
299
  @property_depends_on(['source.sample_freq', 'block_size', '_ind_high', '_freqhc'])
@@ -322,7 +306,7 @@ class PowerSpectra(BaseSpectra):
322
306
  return min(self._ind_high, fftfreq.shape[0] - 1)
323
307
  if self._freqhc is None:
324
308
  return None
325
- return searchsorted(fftfreq[:-1], self._freqhc)
309
+ return np.searchsorted(fftfreq[:-1], self._freqhc)
326
310
  return None
327
311
 
328
312
  def _set_ind_high(self, ind_high): # by setting this the user sets the lower index
@@ -338,7 +322,7 @@ class PowerSpectra(BaseSpectra):
338
322
  fftfreq = self.fftfreq()
339
323
  if fftfreq is not None:
340
324
  try:
341
- indices = arange(fftfreq.shape[0], dtype=int)
325
+ indices = np.arange(fftfreq.shape[0], dtype=int)
342
326
  if self.ind_high is None:
343
327
  return indices[self.ind_low :]
344
328
  return indices[self.ind_low : self.ind_high]
@@ -385,18 +369,18 @@ class PowerSpectra(BaseSpectra):
385
369
  """
386
370
  t = self.source
387
371
  wind = self.window_(self.block_size)
388
- weight = dot(wind, wind)
389
- wind = wind[newaxis, :].swapaxes(0, 1)
372
+ weight = np.dot(wind, wind)
373
+ wind = wind[np.newaxis, :].swapaxes(0, 1)
390
374
  numfreq = int(self.block_size / 2 + 1)
391
375
  csm_shape = (numfreq, t.num_channels, t.num_channels)
392
- csm_upper = zeros(csm_shape, dtype=self.precision)
376
+ csm_upper = np.zeros(csm_shape, dtype=self.precision)
393
377
  # get time data blockwise
394
378
  for data in self._get_source_data():
395
379
  ft = fft.rfft(data * wind, None, 0).astype(self.precision)
396
380
  calcCSM(csm_upper, ft) # only upper triangular part of matrix is calculated (for speed reasons)
397
381
  # create the full csm matrix via transposing and complex conj.
398
382
  csm_lower = csm_upper.conj().transpose(0, 2, 1)
399
- [fill_diagonal(csm_lower[cntFreq, :, :], 0) for cntFreq in range(csm_lower.shape[0])]
383
+ [np.fill_diagonal(csm_lower[cntFreq, :, :], 0) for cntFreq in range(csm_lower.shape[0])]
400
384
  csm = csm_lower + csm_upper
401
385
  # onesided spectrum: multiplication by 2.0=sqrt(2)^2
402
386
  return csm * (2.0 / self.block_size / weight / self.num_blocks)
@@ -445,10 +429,10 @@ class PowerSpectra(BaseSpectra):
445
429
  eva_dtype = 'float32'
446
430
  # csm = self.csm #trigger calculation
447
431
  csm_shape = self.csm.shape
448
- eva = empty(csm_shape[0:2], dtype=eva_dtype)
449
- eve = empty(csm_shape, dtype=self.precision)
432
+ eva = np.empty(csm_shape[0:2], dtype=eva_dtype)
433
+ eve = np.empty(csm_shape, dtype=self.precision)
450
434
  for i in range(csm_shape[0]):
451
- (eva[i], eve[i]) = linalg.eigh(self.csm[i])
435
+ (eva[i], eve[i]) = np.linalg.eigh(self.csm[i])
452
436
  return (eva, eve)
453
437
 
454
438
  def calc_eva(self):
@@ -605,12 +589,12 @@ class PowerSpectra(BaseSpectra):
605
589
  f = self.fftfreq()
606
590
  if num == 0:
607
591
  # 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))
592
+ return self.eva[np.searchsorted(f, freq)]
593
+ f1 = np.searchsorted(f, freq * 2.0 ** (-0.5 / num))
594
+ f2 = np.searchsorted(f, freq * 2.0 ** (0.5 / num))
611
595
  if f1 == f2:
612
596
  return self.eva[f1]
613
- return sum(self.eva[f1:f2], 0)
597
+ return np.sum(self.eva[f1:f2], 0)
614
598
 
615
599
 
616
600
  class PowerSpectraImport(PowerSpectra):
@@ -628,50 +612,46 @@ class PowerSpectraImport(PowerSpectra):
628
612
 
629
613
  #: The cross-spectral matrix stored in an array of shape ``(n, m, m)`` of complex for ``n``
630
614
  #: frequencies and ``m`` channels.
631
- csm = Property(desc='cross spectral matrix')
615
+ csm = Property()
632
616
 
633
617
  #: The frequencies included in the CSM in ascending order. Accepts list, array, or a single
634
618
  #: float value.
635
- frequencies = Union(None, CArray, Float, desc='frequencies included in the cross-spectral matrix')
619
+ frequencies = Union(None, CArray, Float)
636
620
 
637
621
  #: Number of time data channels, inferred from the shape of the CSM.
638
622
  num_channels = Property(depends_on=['digest'])
639
623
 
640
624
  #: :class:`PowerSpectraImport` does not consume time data; source is always ``None``.
641
- source = Enum(None, desc='PowerSpectraImport cannot consume time data')
625
+ source = Enum(None)
642
626
 
643
627
  #: Sampling frequency of the signal. Default is ``None``
644
- sample_freq = Enum(None, desc='sampling frequency')
628
+ sample_freq = Enum(None)
645
629
 
646
630
  #: Block size for FFT, non-functional in this class.
647
- block_size = Enum(None, desc='PowerSpectraImport does not operate on blocks of time data')
631
+ block_size = Enum(None)
648
632
 
649
633
  #: Windowing method, non-functional in this class.
650
- window = Enum(None, desc='PowerSpectraImport does not perform windowing')
634
+ window = Enum(None)
651
635
 
652
636
  #: Overlap between blocks, non-functional in this class.
653
- overlap = Enum(None, desc='PowerSpectraImport does not consume time data')
637
+ overlap = Enum(None)
654
638
 
655
639
  #: Caching capability, always disabled.
656
- cached = Enum(False, desc='PowerSpectraImport has no caching capabilities')
640
+ cached = Enum(False)
657
641
 
658
642
  #: Number of FFT blocks, always ``None``.
659
- num_blocks = Enum(None, desc='PowerSpectraImport cannot determine the number of blocks')
660
-
661
- # Shadow trait, should not be set directly, for internal use.
662
- _ind_low = Int(0, desc='index of lowest frequency line')
643
+ num_blocks = Enum(None)
663
644
 
664
- # Shadow trait, should not be set directly, for internal use.
665
- _ind_high = Union(None, Int, desc='index of highest frequency line')
645
+ _ind_low = Int(0)
646
+ _ind_high = Union(None, Int)
666
647
 
667
648
  #: A unique identifier for the spectra, based on its properties. (read-only)
668
649
  digest = Property(depends_on=['_csmsum'])
669
650
 
670
651
  #: Name of the cache file without extension. (read-only)
671
- basename = Property(depends_on=['digest'], desc='basename for cache file')
652
+ basename = Property(depends_on=['digest'])
672
653
 
673
- # Shadow trait for storing the CSM, for internal use only.
674
- _csm = Union(None, CArray(shape=(None, None, None)), desc='cross spectral matrix')
654
+ _csm = Union(None, CArray(shape=(None, None, None)))
675
655
 
676
656
  # Checksum for the CSM to trigger digest calculation, for internal use only.
677
657
  _csmsum = Float()
@@ -696,7 +676,7 @@ class PowerSpectraImport(PowerSpectra):
696
676
  (number of frequencies, num_channels, num_channels)!'
697
677
  raise ValueError(msg)
698
678
  self._csm = csm
699
- self._csmsum = real(self._csm).sum() + (imag(self._csm) ** 2).sum() # to trigger new digest creation
679
+ self._csmsum = np.real(self._csm).sum() + (np.imag(self._csm) ** 2).sum() # to trigger new digest creation
700
680
 
701
681
  @property_depends_on(['digest'])
702
682
  def _get_eva(self):
@@ -719,7 +699,7 @@ class PowerSpectraImport(PowerSpectra):
719
699
  Array containing the frequencies.
720
700
  """
721
701
  if isinstance(self.frequencies, float):
722
- return array([self.frequencies])
723
- if isinstance(self.frequencies, ndarray):
702
+ return np.array([self.frequencies])
703
+ if isinstance(self.frequencies, np.ndarray):
724
704
  return self.frequencies
725
705
  return self.frequencies