acoular 24.10__py3-none-any.whl → 25.3__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/fprocess.py CHANGED
@@ -1,7 +1,8 @@
1
1
  # ------------------------------------------------------------------------------
2
2
  # Copyright (c) Acoular Development Team.
3
3
  # ------------------------------------------------------------------------------
4
- """Implements blockwise processing methods in the frequency domain.
4
+ """
5
+ Implements blockwise processing methods in the frequency domain.
5
6
 
6
7
  .. autosummary::
7
8
  :toctree: generated/
@@ -17,55 +18,68 @@ from warnings import warn
17
18
 
18
19
  import numpy as np
19
20
  from scipy import fft
20
- from traits.api import Bool, CArray, Enum, Instance, Int, Property, Trait, Union, cached_property
21
+ from traits.api import Bool, CArray, Enum, Instance, Int, Property, Union, cached_property
21
22
 
23
+ # acoular imports
22
24
  from .base import SamplesGenerator, SpectraGenerator, SpectraOut, TimeOut
25
+ from .deprecation import deprecated_alias
23
26
  from .fastFuncs import calcCSM
24
27
  from .internal import digest
28
+ from .process import SamplesBuffer
25
29
  from .spectra import BaseSpectra
26
- from .tools.utils import SamplesBuffer
27
30
 
28
31
 
32
+ @deprecated_alias({'numfreqs': 'num_freqs', 'numsamples': 'num_samples'}, read_only=True)
29
33
  class RFFT(BaseSpectra, SpectraOut):
30
- """Provides the one-sided Fast Fourier Transform (FFT) for real-valued multichannel time data.
34
+ """
35
+ Compute the one-sided Fast Fourier Transform (FFT) for real-valued multichannel time data.
31
36
 
32
- The FFT is calculated block-wise, i.e. the input data is divided into blocks of length
33
- :attr:`block_size` and the FFT is calculated for each block. Optionally, a window function
34
- can be applied to the data before the FFT calculation via the :attr:`window` attribute.
37
+ The FFT is performed block-wise, dividing the input data into blocks of length specified
38
+ by the :attr:`block_size` attribute. A window function can be optionally
39
+ applied to each block before the FFT calculation, controlled via the :attr:`window` attribute.
40
+
41
+ This class provides flexibility in scaling the FFT results for different use cases, such as
42
+ preserving amplitude or energy, by setting the :attr:`scaling` attribute.
35
43
  """
36
44
 
37
- #: Data source; :class:`~acoular.base.SamplesGenerator` or derived object.
45
+ #: Data source; an instance of :class:`~acoular.base.SamplesGenerator` or a derived object.
46
+ #: This provides the input time-domain data for FFT processing.
38
47
  source = Instance(SamplesGenerator)
39
48
 
40
- #: Number of workers to use for the FFT calculation. If negative values are used,
41
- #: all available logical CPUs will be considered (``scipy.fft.rfft`` implementation wraps around from ``os.cpu_count()``).
42
- #: Default is `None` (handled by scipy)
49
+ #: The number of workers to use for FFT calculation.
50
+ #: If set to a negative value, all available logical CPUs are used.
51
+ #: Default is ``None``, which relies on the :func:`scipy.fft.rfft` implementation.
43
52
  workers = Union(Int(), None, default_value=None, desc='number of workers to use')
44
53
 
45
- #: Scaling method, either 'amplitude', 'energy' or :code:`none`.
46
- #: Default is :code:`none`.
47
- #: 'energy': compensates for the energy loss due to truncation of the FFT result. The resulting
48
- #: one-sided spectrum is multiplied by 2.0, except for the DC and Nyquist frequency.
49
- #: 'amplitude': scales the one-sided spectrum so that the amplitude of discrete tones does not depend
50
- #: on the block size.
54
+ #: Defines the scaling method for the FFT result. Options are:
55
+ #:
56
+ #: - ``'none'``: No scaling is applied.
57
+ #: - ``'energy'``: Compensates for energy loss in the FFT result due to truncation,
58
+ #: doubling the values for frequencies other than DC and the Nyquist frequency.
59
+ #: - ``'amplitude'``: Scales the result so that the amplitude
60
+ #: of discrete tones is independent of the block size.
51
61
  scaling = Enum('none', 'energy', 'amplitude')
52
62
 
53
- #: block size of the FFT. Default is 1024.
63
+ #: The length of each block of time-domain data used for the FFT. Must be an even number.
64
+ #: Default is ``1024``.
54
65
  block_size = Property()
55
66
 
56
- #: Number of frequencies in the output.
57
- numfreqs = Property(depends_on='_block_size')
67
+ #: The number of frequency bins in the FFT result, calculated as ``block_size // 2 + 1``.
68
+ num_freqs = Property(depends_on=['_block_size'])
58
69
 
59
- #: Number of snapshots in the output.
60
- numsamples = Property(depends_on='source.numsamples, _block_size')
70
+ #: The total number of snapshots (blocks) available in the FFT result,
71
+ #: determined by the size of the input data and the block size.
72
+ num_samples = Property(depends_on=['source.num_samples', '_block_size'])
61
73
 
62
- #: 1-D array of FFT sample frequencies.
74
+ #: A 1-D array containing the Discrete Fourier Transform
75
+ #: sample frequencies corresponding to the FFT output.
63
76
  freqs = Property()
64
77
 
65
- # internal block size variable
78
+ # Internal representation of the block size for FFT processing.
79
+ # Used for validation and property management.
66
80
  _block_size = Int(1024, desc='block size of the FFT')
67
81
 
68
- # internal identifier
82
+ #: A unique identifier based on the process properties.
69
83
  digest = Property(depends_on=['source.digest', 'scaling', 'precision', '_block_size', 'window', 'overlap'])
70
84
 
71
85
  @cached_property
@@ -73,13 +87,13 @@ class RFFT(BaseSpectra, SpectraOut):
73
87
  return digest(self)
74
88
 
75
89
  @cached_property
76
- def _get_numfreqs(self):
90
+ def _get_num_freqs(self):
77
91
  return int(self.block_size / 2 + 1)
78
92
 
79
93
  @cached_property
80
- def _get_numsamples(self):
81
- if self.source.numsamples >= 0:
82
- return int(np.floor(self.source.numsamples / self.block_size))
94
+ def _get_num_samples(self):
95
+ if self.source.num_samples >= 0:
96
+ return int(np.floor(self.source.num_samples / self.block_size))
83
97
  return -1
84
98
 
85
99
  def _get_block_size(self):
@@ -92,39 +106,49 @@ class RFFT(BaseSpectra, SpectraOut):
92
106
  self._block_size = value
93
107
 
94
108
  def _scale(self, data, scaling_value):
95
- """Corrects the energy of the one-sided FFT data."""
109
+ # Corrects the energy of the one-sided FFT data.
96
110
  if self.scaling == 'amplitude' or self.scaling == 'energy':
97
111
  data[1:-1] *= 2.0
98
112
  data *= scaling_value
99
113
  return data
100
114
 
101
115
  def _get_freqs(self):
102
- """Return the Discrete Fourier Transform sample frequencies.
103
-
104
- Returns
105
- -------
106
- f : ndarray
107
- 1-D Array of length *block_size/2+1* containing the sample frequencies.
116
+ # Return the Discrete Fourier Transform sample frequencies.
108
117
 
109
- """
118
+ # Returns
119
+ # -------
120
+ # f : ndarray
121
+ # 1-D Array of length *block_size // 2 + 1* containing the sample frequencies.
110
122
  if self.source is not None:
111
123
  return abs(fft.fftfreq(self.block_size, 1.0 / self.source.sample_freq)[: int(self.block_size / 2 + 1)])
112
124
  return np.array([])
113
125
 
114
126
  def result(self, num=1):
115
- """Python generator that yields the output block-wise.
127
+ """
128
+ Yield the FFT results block-wise as multi-channel spectra.
129
+
130
+ This generator processes the input data block-by-block, applying the specified
131
+ window function and FFT parameters. The output consists of the FFT spectra for
132
+ each block, scaled according to the selected :attr:`scaling` method.
116
133
 
117
134
  Parameters
118
135
  ----------
119
- num : integer
120
- This parameter defines the number of multi-channel spectra (i.e. snapshots) per block
121
- returned by the generator.
122
-
123
- Returns
124
- -------
125
- Spectra block of shape (num, :attr:`numchannels`*:attr:`numfreqs`).
126
- The last block may be shorter than num.
136
+ num : :class:`int`, optional
137
+ Number of multi-channel spectra (snapshots) per block to return. Default is ``1``.
127
138
 
139
+ Yields
140
+ ------
141
+ :class:`numpy.ndarray`
142
+ A block of FFT spectra with shape (num, :attr:`num_channels` ``*`` :attr:`num_freqs`).
143
+ The final block may contain fewer than ``num`` spectra if the input data is insufficient
144
+ to fill the last block.
145
+
146
+ Notes
147
+ -----
148
+ - The generator compensates for energy or amplitude loss based on the :attr:`scaling`
149
+ attribute.
150
+ - If the input data source provides fewer samples than required for a complete block,
151
+ the remaining spectra are padded or adjusted accordingly.
128
152
  """
129
153
  wind = self.window_(self.block_size)
130
154
  if self.scaling == 'none' or self.scaling == 'energy': # only compensate for the window
@@ -132,7 +156,7 @@ class RFFT(BaseSpectra, SpectraOut):
132
156
  elif self.scaling == 'amplitude': # compensates for the window and the energy loss
133
157
  svalue = 1 / wind.sum()
134
158
  wind = wind[:, np.newaxis]
135
- fftdata = np.zeros((num, self.numchannels * self.numfreqs), dtype=self.precision)
159
+ fftdata = np.zeros((num, self.num_channels * self.num_freqs), dtype=self.precision)
136
160
  j = 0
137
161
  for i, data in enumerate(self._get_source_data()): # yields one block of time data
138
162
  j = i % num
@@ -146,33 +170,46 @@ class RFFT(BaseSpectra, SpectraOut):
146
170
  yield fftdata[: j + 1]
147
171
 
148
172
 
173
+ @deprecated_alias({'numsamples': 'num_samples'}, read_only=True)
149
174
  class IRFFT(TimeOut):
150
- """Calculates the inverse Fast Fourier Transform (IFFT) for one-sided multi-channel spectra."""
175
+ """
176
+ Perform the inverse Fast Fourier Transform (IFFT) for one-sided multi-channel spectra.
177
+
178
+ This class converts spectral data from the frequency domain back into time-domain signals.
179
+ The IFFT is calculated block-wise, where the block size is defined by the spectral data
180
+ source. The output time-domain signals are scaled and processed according to the precision
181
+ defined by the :attr:`precision` attribute.
182
+ """
151
183
 
152
- #: Data source; :class:`~acoular.base.SpectraGenerator` or derived object.
184
+ #: Data source providing one-sided spectra, implemented as an instance of
185
+ # :class:`~acoular.base.SpectraGenerator` or a derived object.
153
186
  source = Instance(SpectraGenerator)
154
187
 
155
- #: Number of workers to use for the FFT calculation. If negative values are used,
156
- #: all available logical CPUs will be considered (``scipy.fft.rfft`` implementation wraps around from ``os.cpu_count()``).
157
- #: Default is `None` (handled by scipy)
188
+ #: The number of workers (threads) to use for the IFFT calculation.
189
+ #: A negative value utilizes all available logical CPUs.
190
+ #: Default is ``None``, which relies on the :func:`scipy.fft.irfft` implementation.
158
191
  workers = Union(Int(), None, default_value=None, desc='number of workers to use')
159
192
 
160
- #: The floating-number-precision of the resulting time signals, corresponding to numpy dtypes.
161
- #: Default is 64 bit.
162
- precision = Trait('float64', 'float32', desc='precision of the time signal after the ifft')
193
+ #: Determines the floating-point precision of the resulting time-domain signals.
194
+ #: Options include ``'float64'`` and ``'float32'``.
195
+ #: Default is ``'float64'``, ensuring high precision.
196
+ precision = Enum('float64', 'float32', desc='precision of the time signal after the ifft')
163
197
 
164
- #: Number of time samples in the output.
165
- numsamples = Property(depends_on='source.numsamples, source._block_size')
198
+ #: The total number of time-domain samples in the output.
199
+ #: Computed as the product of the number of input samples and the block size.
200
+ #: Returns ``-1`` if the number of input samples is negative.
201
+ num_samples = Property(depends_on=['source.num_samples', 'source._block_size'])
166
202
 
167
- # internal time signal buffer to handle arbitrary output block sizes
203
+ # Internal signal buffer used for handling arbitrary output block sizes. Optimizes
204
+ # processing when the requested output block size does not match the source block size.
168
205
  _buffer = CArray(desc='signal buffer')
169
206
 
170
- # internal identifier
207
+ #: A unique identifier based on the process properties.
171
208
  digest = Property(depends_on=['source.digest', 'scaling', 'precision', '_block_size', 'window', 'overlap'])
172
209
 
173
- def _get_numsamples(self):
174
- if self.source.numsamples >= 0:
175
- return int(self.source.numsamples * self.source.block_size)
210
+ def _get_num_samples(self):
211
+ if self.source.num_samples >= 0:
212
+ return int(self.source.num_samples * self.source.block_size)
176
213
  return -1
177
214
 
178
215
  @cached_property
@@ -186,9 +223,9 @@ class IRFFT(TimeOut):
186
223
  'This is likely due to incomplete spectral data from which the inverse FFT cannot be calculated.'
187
224
  )
188
225
  raise ValueError(msg)
189
- if (self.source.numfreqs - 1) * 2 != self.source.block_size:
226
+ if (self.source.num_freqs - 1) * 2 != self.source.block_size:
190
227
  msg = (
191
- f'Block size must be 2*(numfreqs-1) but is {self.source.block_size}.'
228
+ f'Block size must be 2*(num_freqs-1) but is {self.source.block_size}.'
192
229
  'This is likely due to incomplete spectral data from which the inverse FFT cannot be calculated.'
193
230
  )
194
231
  raise ValueError(msg)
@@ -197,18 +234,32 @@ class IRFFT(TimeOut):
197
234
  raise ValueError(msg)
198
235
 
199
236
  def result(self, num):
200
- """Python generator that yields the output block-wise.
237
+ """
238
+ Generate time-domain signal blocks from spectral data.
239
+
240
+ This generator processes spectral data block-by-block, performing an inverse Fast
241
+ Fourier Transform (IFFT) to convert the input spectra into time-domain signals.
242
+ The output is yielded in blocks of the specified size.
201
243
 
202
244
  Parameters
203
245
  ----------
204
- num : integer
205
- This parameter defines the size of the blocks to be yielded
206
- (i.e. the number of samples per block). The last block may be shorter than num.
246
+ num : :class:`int`
247
+ The number of time samples per output block. If ``num`` differs from the
248
+ source block size, an internal buffer is used to assemble the required output.
207
249
 
208
250
  Yields
209
251
  ------
210
- numpy.ndarray
211
- Yields blocks of shape (num, numchannels).
252
+ :class:`numpy.ndarray`
253
+ Blocks of time-domain signals with shape (num, :attr:`num_channels`). The last block may
254
+ contain fewer samples if the input data is insufficient to fill the requested size.
255
+
256
+ Notes
257
+ -----
258
+ - The method ensures that the source block size and frequency data are compatible for IFFT.
259
+ - If the requested block size does not match the source block size, a buffer is used
260
+ to assemble the output, allowing arbitrary block sizes to be generated.
261
+ - For performance optimization, the number of workers (threads) can be specified via
262
+ the :attr:`workers` attribute.
212
263
  """
213
264
  self._validate()
214
265
  bs = self.source.block_size
@@ -219,27 +270,39 @@ class IRFFT(TimeOut):
219
270
  else:
220
271
  for spectra in self.source.result(1):
221
272
  yield fft.irfft(
222
- spectra.reshape(self.source.numfreqs, self.numchannels), n=num, axis=0, workers=self.workers
273
+ spectra.reshape(self.source.num_freqs, self.num_channels), n=num, axis=0, workers=self.workers
223
274
  )
224
275
 
225
276
 
226
277
  class AutoPowerSpectra(SpectraOut):
227
- """Calculates the real-valued auto-power spectra."""
278
+ """
279
+ Compute the real-valued auto-power spectra from multi-channel frequency-domain data.
228
280
 
229
- #: Data source; :class:`~acoular.base.SpectraGenerator` or derived object.
281
+ The auto-power spectra provide a measure of the power contained in each frequency bin
282
+ for each channel. This class processes spectral data from the source block-by-block,
283
+ applying scaling and precision adjustments as configured by the :attr:`scaling` and
284
+ :attr:`precision` attributes.
285
+ """
286
+
287
+ #: The data source that provides frequency-domain spectra,
288
+ #: implemented as an instance of :class:`~acoular.base.SpectraGenerator` or a derived object.
230
289
  source = Instance(SpectraGenerator)
231
290
 
232
- #: Scaling method, either 'power' or 'psd' (Power Spectral Density).
233
- #: Only relevant if the source is a :class:`~acoular.fprocess.FreqInOut` object.
291
+ #: Specifies the scaling method for the auto-power spectra. Options are:
292
+ #:
293
+ #: - ``'power'``: Outputs the raw power of the spectra.
294
+ #: - ``'psd'``: Outputs the Power Spectral Density (PSD),
295
+ #: normalized by the block size and sampling frequency.
234
296
  scaling = Enum('power', 'psd')
235
297
 
236
- #: Determines if the spectra yielded by the source are single-sided spectra.
298
+ #: A Boolean flag indicating whether the input spectra are single-sided. Default is ``True``.
237
299
  single_sided = Bool(True, desc='single sided spectrum')
238
300
 
239
- #: The floating-number-precision of entries, corresponding to numpy dtypes. Default is 64 bit.
240
- precision = Trait('float64', 'float32', desc='floating-number-precision')
301
+ #: Specifies the floating-point precision of the computed auto-power spectra.
302
+ #: Options are ``'float64'`` and ``'float32'``. Default is ``'float64'``.
303
+ precision = Enum('float64', 'float32', desc='floating-number-precision')
241
304
 
242
- # internal identifier
305
+ #: A unique identifier based on the computation properties.
243
306
  digest = Property(depends_on=['source.digest', 'precision', 'scaling', 'single_sided'])
244
307
 
245
308
  @cached_property
@@ -255,57 +318,87 @@ class AutoPowerSpectra(SpectraOut):
255
318
  return scale
256
319
 
257
320
  def result(self, num=1):
258
- """Python generator that yields the real-valued auto-power spectra.
321
+ """
322
+ Generate real-valued auto-power spectra blocks.
323
+
324
+ This generator computes the auto-power spectra by taking the element-wise squared
325
+ magnitude of the input spectra and applying the appropriate scaling. The results
326
+ are yielded block-by-block with the specified number of snapshots.
259
327
 
260
328
  Parameters
261
329
  ----------
262
- num : integer
263
- This parameter defines the number of snapshots within each output data block.
330
+ num : :class:`int`, optional
331
+ Number of snapshots in each output block. Default is ``1``.
264
332
 
265
333
  Yields
266
334
  ------
267
- numpy.ndarray
268
- Yields blocks of shape (num, numchannels*numfreqs).
269
- The last block may be shorter than num.
270
-
335
+ :class:`numpy.ndarray`
336
+ (num, :attr:`num_channels` ``*`` :attr:`num_freqs`). The last block may contain fewer
337
+ snapshots if the input data does not completely fill the requested block size.
338
+
339
+ Notes
340
+ -----
341
+ - The auto-power spectra are computed as the squared magnitude of the spectra
342
+ :math:`|S(f)|^2`, where :math:`S(f)` is the frequency-domain signal.
343
+ - Scaling is applied based on the configuration of the :attr:`scaling` and
344
+ :attr:`single_sided` attributes.
345
+ - The floating-point precision of the output is determined by the
346
+ :attr:`precision` attribute.
271
347
  """
272
348
  scale = self._get_scaling_value()
273
349
  for temp in self.source.result(num):
274
350
  yield ((temp * temp.conjugate()).real * scale).astype(self.precision)
275
351
 
276
352
 
353
+ @deprecated_alias({'numchannels': 'num_channels'}, read_only=True)
277
354
  class CrossPowerSpectra(AutoPowerSpectra):
278
- """Calculates the complex-valued auto- and cross-power spectra.
279
-
280
- Receives the complex-valued spectra from the source and returns the cross-spectral matrix (CSM) in a flattened
281
- representation (i.e. the auto- and cross-power spectra are concatenated along the last axis).
282
- If :attr:`calc_mode` is 'full', the full CSM is calculated, if 'upper', only the upper triangle is calculated.
283
355
  """
356
+ Compute the complex-valued auto- and cross-power spectra from frequency-domain data.
284
357
 
285
- #: Data source; :class:`~acoular.base.SpectraGenerator` or derived object.
286
- source = Trait(SpectraGenerator)
358
+ This class generates the cross-spectral matrix (CSM) in a flattened representation, which
359
+ includes the auto-power spectra (diagonal elements) and cross-power spectra (off-diagonal
360
+ elements). Depending on the :attr:`calc_mode`, the class can compute:
287
361
 
288
- #: The floating-number-precision of entries of csm, eigenvalues and
289
- #: eigenvectors, corresponding to numpy dtypes. Default is 64 bit.
290
- precision = Trait('complex128', 'complex64', desc='precision of the fft')
362
+ - The full CSM, which includes all elements.
363
+ - Only the upper triangle of the CSM.
364
+ - Only the lower triangle of the CSM.
291
365
 
292
- #: Calculation mode, either 'full' or 'upper'.
293
- #: 'full' calculates the full cross-spectral matrix, 'upper' calculates
294
- # only the upper triangle. Default is 'full'.
295
- calc_mode = Trait('full', 'upper', 'lower', desc='calculation mode')
366
+ The results are computed block-by-block and scaled according to the specified configuration.
367
+ """
296
368
 
297
- #: Number of channels in output. If :attr:`calc_mode` is 'full', then
298
- #: :attr:`numchannels` is :math:`n^2`, where :math:`n` is the number of
299
- #: channels in the input. If :attr:`calc_mode` is 'upper', then
300
- #: :attr:`numchannels` is :math:`n + n(n-1)/2`.
301
- numchannels = Property(depends_on='source.numchannels')
369
+ #: The data source providing the input spectra,
370
+ #: implemented as an instance of :class:`~acoular.base.SpectraGenerator` or a derived object.
371
+ source = Instance(SpectraGenerator)
302
372
 
303
- # internal identifier
373
+ #: Specifies the floating-point precision of the computed cross-spectral matrix (CSM).
374
+ #: Options are ``'complex128'`` and ``'complex64'``. Default is ``'complex128'``.
375
+ precision = Enum('complex128', 'complex64', desc='precision of the fft')
376
+
377
+ #: Defines the calculation mode for the cross-spectral matrix:
378
+ #:
379
+ #: - ``'full'``: Computes the full CSM, including all auto- and cross-power spectra.
380
+ #: - ``'upper'``: Computes only the upper triangle of the CSM,
381
+ # excluding redundant lower-triangle elements.
382
+ #: - ``'lower'``: Computes only the lower triangle of the CSM,
383
+ #: excluding redundant upper-triangle elements.
384
+ #:
385
+ #: Default is ``'full'``.
386
+ calc_mode = Enum('full', 'upper', 'lower', desc='calculation mode')
387
+
388
+ #: The number of channels in the output data. The value depends on the number of input channels
389
+ #: :math:`n` and the selected :attr:`calc_mode`:
390
+ #:
391
+ #: - ``'full'``: :math:`n^2` (all elements in the CSM).
392
+ #: - ``'upper'``: :math:`n + n(n-1)/2` (diagonal + upper triangle elements).
393
+ #: - ``'lower'``: :math:`n + n(n-1)/2` (diagonal + lower triangle elements).
394
+ num_channels = Property(depends_on=['source.num_channels'])
395
+
396
+ #: A unique identifier based on the computation properties.
304
397
  digest = Property(depends_on=['source.digest', 'precision', 'scaling', 'single_sided', 'calc_mode'])
305
398
 
306
399
  @cached_property
307
- def _get_numchannels(self):
308
- n = self.source.numchannels
400
+ def _get_num_channels(self):
401
+ n = self.source.num_channels
309
402
  return n**2 if self.calc_mode == 'full' else int(n + n * (n - 1) / 2)
310
403
 
311
404
  @cached_property
@@ -313,22 +406,32 @@ class CrossPowerSpectra(AutoPowerSpectra):
313
406
  return digest(self)
314
407
 
315
408
  def result(self, num=1):
316
- """Python generator that yields the output block-wise.
409
+ """
410
+ Generate blocks of complex-valued auto- and cross-power spectra.
411
+
412
+ This generator computes the cross-spectral matrix (CSM) for input spectra block-by-block.
413
+ Depending on the :attr:`calc_mode`, the resulting CSM is flattened in one of three ways:
414
+
415
+ - ``'full'``: Includes all elements of the CSM.
416
+ - ``'upper'``: Includes only the diagonal and upper triangle.
417
+ - ``'lower'``: Includes only the diagonal and lower triangle.
317
418
 
318
419
  Parameters
319
420
  ----------
320
- num : integer
321
- This parameter defines the size of the blocks to be yielded
322
- (i.e. the number of samples per block).
421
+ num : :class:`int`, optional
422
+ Number of snapshots (blocks) in each output data block. Default is ``1``.
323
423
 
324
424
  Yields
325
425
  ------
326
- numpy.ndarray
327
- Yields blocks of shape (num, numchannels*numfreq).
426
+ :class:`numpy.ndarray`
427
+ Blocks of complex-valued auto- and cross-power spectra with shape
428
+ ``(num, :attr:`num_channels` * :attr:`num_freqs`)``.
429
+ The last block may contain fewer than ``num`` elements if the input data
430
+ does not completely fill the requested block size.
328
431
  """
329
- nc_src = self.source.numchannels
330
- nc = self.numchannels
331
- nf = self.numfreqs
432
+ nc_src = self.source.num_channels
433
+ nc = self.num_channels
434
+ nf = self.num_freqs
332
435
  scale = self._get_scaling_value()
333
436
 
334
437
  csm_flat = np.zeros((num, nc * nf), dtype=self.precision)
@@ -345,18 +448,25 @@ class CrossPowerSpectra(AutoPowerSpectra):
345
448
  else: # lower
346
449
  csm_lower = csm_upper.conj().transpose(0, 2, 1)
347
450
  csm_flat[i] = csm_lower[:, :nc].reshape(-1)
348
- csm_upper[...] = 0 # calcCSM adds cummulative
451
+ csm_upper[...] = 0 # calcCSM adds cumulative
349
452
  yield csm_flat[: i + 1] * scale
350
453
 
351
454
 
352
455
  class FFTSpectra(RFFT):
353
- """Provides the one-sided Fast Fourier Transform (FFT) for multichannel time data.
354
-
355
- Alias for :class:`~acoular.fprocess.RFFT`.
456
+ """
457
+ Provide the one-sided Fast Fourier Transform (FFT) for multichannel time data.
356
458
 
357
459
  .. deprecated:: 24.10
358
- Using :class:`~acoular.fprocess.FFTSpectra` is deprecated and will be removed in Acoular
359
- version 25.07. Use :class:`~acoular.fprocess.RFFT` instead.
460
+ The :class:`~acoular.fprocess.FFTSpectra` class is deprecated and will be removed
461
+ in Acoular version 25.07. Please use :class:`~acoular.fprocess.RFFT` instead.
462
+
463
+ Alias for the :class:`~acoular.fprocess.RFFT` class, which computes the one-sided
464
+ Fast Fourier Transform (FFT) for multichannel time data.
465
+
466
+ Warnings
467
+ --------
468
+ This class remains temporarily available for backward compatibility but should not be used in
469
+ new implementations.
360
470
  """
361
471
 
362
472
  def __init__(self, *args, **kwargs):