acoular 24.7__py3-none-any.whl → 24.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 CHANGED
@@ -4,11 +4,22 @@
4
4
 
5
5
  """The Acoular library: several classes for the implementation of acoustic beamforming."""
6
6
 
7
- import os
7
+ import os # noqa: I001
8
+
9
+ # config must be imported before any submodules containing numpy, see #322.
10
+ from .configuration import config
8
11
 
9
12
  from . import demo, tools
13
+ from .base import (
14
+ Generator,
15
+ InOut,
16
+ SamplesGenerator,
17
+ SpectraGenerator,
18
+ SpectraOut,
19
+ TimeInOut,
20
+ TimeOut,
21
+ )
10
22
  from .calib import Calib
11
- from .configuration import config
12
23
  from .environments import (
13
24
  Environment,
14
25
  FlowField,
@@ -41,6 +52,7 @@ from .fbeamform import (
41
52
  SteeringVector,
42
53
  integrate,
43
54
  )
55
+ from .fprocess import IRFFT, RFFT, AutoPowerSpectra, CrossPowerSpectra, FFTSpectra
44
56
  from .grids import (
45
57
  CircSector,
46
58
  ConvexSector,
@@ -57,6 +69,7 @@ from .grids import (
57
69
  Sector,
58
70
  )
59
71
  from .microphones import MicGeom
72
+ from .process import Average, Cache, SampleSplitter, TimeAverage, TimeCache
60
73
  from .sdinput import SoundDeviceSamplesGenerator
61
74
  from .signals import (
62
75
  FiltWNoiseGenerator,
@@ -80,7 +93,7 @@ from .sources import (
80
93
  TimeSamples,
81
94
  UncorrelatedNoiseSource,
82
95
  )
83
- from .spectra import BaseSpectra, FFTSpectra, PowerSpectra, PowerSpectraImport, synthetic
96
+ from .spectra import BaseSpectra, PowerSpectra, PowerSpectraImport, synthetic
84
97
  from .spectra import PowerSpectra as EigSpectra
85
98
  from .tbeamform import (
86
99
  BeamformerCleant,
@@ -102,19 +115,15 @@ from .tprocess import (
102
115
  FiltFreqWeight,
103
116
  FiltOctave,
104
117
  MaskedTimeInOut,
118
+ MaskedTimeOut,
105
119
  Mixer,
106
120
  OctaveFilterBank,
107
- SamplesGenerator,
108
- SampleSplitter,
109
121
  SpatialInterpolator,
110
122
  SpatialInterpolatorConstantRotation,
111
123
  SpatialInterpolatorRotation,
112
- TimeAverage,
113
- TimeCache,
114
124
  TimeConvolve,
115
125
  TimeCumAverage,
116
126
  TimeExpAverage,
117
- TimeInOut,
118
127
  TimePower,
119
128
  TimeReverse,
120
129
  Trigger,
acoular/base.py ADDED
@@ -0,0 +1,312 @@
1
+ # ------------------------------------------------------------------------------
2
+ # Copyright (c) Acoular Development Team.
3
+ # ------------------------------------------------------------------------------
4
+ """Implements base classes for signal processing blocks in Acoular.
5
+
6
+ The classes in this module are abstract base classes that provide a common interface for all classes that generate an
7
+ output via the generator :meth:`result` in block-wise manner. They are not intended to be used directly, but to be
8
+ subclassed by classes that implement the actual signal processing.
9
+
10
+ .. autosummary::
11
+ :toctree: generated/
12
+
13
+ Generator
14
+ SamplesGenerator
15
+ SpectraGenerator
16
+ InOut
17
+ TimeOut
18
+ SpectraOut
19
+ TimeInOut
20
+ """
21
+
22
+ from traits.api import (
23
+ CArray,
24
+ CLong,
25
+ Delegate,
26
+ Float,
27
+ HasPrivateTraits,
28
+ Instance,
29
+ Property,
30
+ cached_property,
31
+ )
32
+
33
+ from acoular.internal import digest
34
+
35
+
36
+ class Generator(HasPrivateTraits):
37
+ """Interface for any generating signal processing block.
38
+
39
+ It provides a common interface for all classes, which generate an output via the generator :meth:`result`
40
+ in block-wise manner. It has a common set of traits that are used by all classes that implement this interface.
41
+ This includes the sampling frequency of the signal (:attr:`sample_freq`) and the number of samples (:attr:`numsamples`).
42
+ A private trait :attr:`digest` is used to store the internal identifier of the object, which is a hash of the object's
43
+ attributes. This is used to check if the object's internal state has changed.
44
+ """
45
+
46
+ #: Sampling frequency of the signal, defaults to 1.0
47
+ sample_freq = Float(1.0, desc='sampling frequency')
48
+
49
+ #: Number of signal samples
50
+ numsamples = CLong
51
+
52
+ # internal identifier
53
+ digest = Property(depends_on=['sample_freq', 'numsamples'])
54
+
55
+ def _get_digest(self):
56
+ return digest(self)
57
+
58
+ def result(self, num):
59
+ """Python generator that yields the output block-wise.
60
+
61
+ This method needs to be implemented by the derived classes.
62
+
63
+ Parameters
64
+ ----------
65
+ num : int
66
+ The size of the first dimension of the blocks to be yielded
67
+
68
+ Yields
69
+ ------
70
+ numpy.ndarray
71
+ Two-dimensional output data block of shape (num, ...)
72
+ """
73
+
74
+
75
+ class SamplesGenerator(Generator):
76
+ """Interface for any generating multi-channel time domain signal processing block.
77
+
78
+ It provides a common interface for all SamplesGenerator classes, which generate an output via the generator :meth:`result`
79
+ in block-wise manner. This class has no real functionality on its own and should not be used directly.
80
+ """
81
+
82
+ #: Number of channels
83
+ numchannels = CLong
84
+
85
+ # internal identifier
86
+ digest = Property(depends_on=['sample_freq', 'numchannels', 'numsamples'])
87
+
88
+ def _get_digest(self):
89
+ return digest(self)
90
+
91
+ def result(self, num):
92
+ """Python generator that yields the output block-wise.
93
+
94
+ Parameters
95
+ ----------
96
+ num : int
97
+ This parameter defines the size of the blocks to be yielded
98
+ (i.e. the number of samples per block)
99
+
100
+ Yields
101
+ ------
102
+ numpy.ndarray
103
+ The two-dimensional time-data block of shape (num, numchannels).
104
+ """
105
+
106
+
107
+ class SpectraGenerator(Generator):
108
+ """Interface for any generating multi-channel signal frequency domain processing block.
109
+
110
+ It provides a common interface for all SpectraGenerator classes, which generate an output via the generator :meth:`result`
111
+ in block-wise manner. This class has no real functionality on its own and should not be used directly.
112
+ """
113
+
114
+ #: Number of channels
115
+ numchannels = CLong
116
+
117
+ #: Number of frequencies
118
+ numfreqs = CLong
119
+
120
+ #: 1-D array of frequencies
121
+ freqs = CArray
122
+
123
+ #: The length of the block used to calculate the spectra
124
+ block_size = CLong
125
+
126
+ # internal identifier
127
+ digest = Property(depends_on=['sample_freq', 'numchannels', 'numsamples', 'numfreqs', 'block_size'])
128
+
129
+ def _get_digest(self):
130
+ return digest(self)
131
+
132
+ def result(self, num=1):
133
+ """Python generator that yields the output block-wise.
134
+
135
+ Parameters
136
+ ----------
137
+ num : integer
138
+ This parameter defines the size of the number of snapshots to be yielded.
139
+ Defaults to 1.
140
+
141
+ Yields
142
+ ------
143
+ numpy.ndarray
144
+ A two-dimensional block of shape (num, numchannels*numfreqs).
145
+ """
146
+
147
+
148
+ class TimeOut(SamplesGenerator):
149
+ """Abstract base class for any signal processing block that receives data from any :attr:`source` domain and returns
150
+ time domain signals.
151
+
152
+ It provides a base class that can be used to create signal processing blocks that receive data from any
153
+ generating :attr:`source` and generates a time signal output via the generator :meth:`result` in block-wise manner.
154
+ """
155
+
156
+ #: Data source; :class:`~acoular.base.Generator` or derived object.
157
+ source = Instance(Generator)
158
+
159
+ #: Sampling frequency of output signal, as given by :attr:`source`.
160
+ sample_freq = Delegate('source')
161
+
162
+ #: Number of channels in output, as given by :attr:`source`.
163
+ numchannels = Delegate('source')
164
+
165
+ #: Number of samples in output, as given by :attr:`source`.
166
+ numsamples = Delegate('source')
167
+
168
+ # internal identifier
169
+ digest = Property(depends_on=['source.digest'])
170
+
171
+ @cached_property
172
+ def _get_digest(self):
173
+ return digest(self)
174
+
175
+ def result(self, num):
176
+ """Python generator that processes the source data and yields the time-signal block-wise.
177
+
178
+ This method needs to be implemented by the derived classes.
179
+
180
+ Parameters
181
+ ----------
182
+ num : int
183
+ This parameter defines the size of the blocks to be yielded
184
+ (i.e. the number of samples per block)
185
+
186
+ Yields
187
+ ------
188
+ numpy.ndarray
189
+ Two-dimensional output data block of shape (num, numchannels)
190
+ """
191
+ yield from self.source.result(num)
192
+
193
+
194
+ class SpectraOut(SpectraGenerator):
195
+ """Abstract base class for any signal processing block that receives data from any :attr:`source` domain and
196
+ returns frequency domain signals.
197
+
198
+ It provides a base class that can be used to create signal processing blocks that receive data from any
199
+ generating :attr:`source` domain and generates a frequency domain output via the generator :meth:`result`
200
+ in block-wise manner.
201
+ """
202
+
203
+ #: Data source; :class:`~acoular.base.Generator` or derived object.
204
+ source = Instance(Generator)
205
+
206
+ #: Sampling frequency of output signal, as given by :attr:`source`.
207
+ sample_freq = Delegate('source')
208
+
209
+ #: Number of channels in output, as given by :attr:`source`.
210
+ numchannels = Delegate('source')
211
+
212
+ #: Number of snapshots in output, as given by :attr:`source`.
213
+ numsamples = Delegate('source')
214
+
215
+ #: Number of frequencies in output, as given by :attr:`source`.
216
+ numfreqs = Delegate('source')
217
+
218
+ #: 1-D array of frequencies, as given by :attr:`source`.
219
+ freqs = Delegate('source')
220
+
221
+ #: The size of the block used to calculate the spectra
222
+ block_size = Delegate('source')
223
+
224
+ # internal identifier
225
+ digest = Property(depends_on=['source.digest'])
226
+
227
+ @cached_property
228
+ def _get_digest(self):
229
+ return digest(self)
230
+
231
+ def result(self, num=1):
232
+ """Python generator that processes the source data and yields the output block-wise.
233
+
234
+ This method needs to be implemented by the derived classes.
235
+
236
+ num : integer
237
+ This parameter defines the the number of snapshots to be yielded.
238
+ Defaults to 1.
239
+
240
+ Yields
241
+ ------
242
+ numpy.ndarray
243
+ A two-dimensional block of shape (num, numchannels*numfreqs).
244
+ """
245
+ yield from self.source.result(num)
246
+
247
+
248
+ class InOut(SamplesGenerator, SpectraGenerator):
249
+ """Abstract base class for any signal processing block that receives data from any :attr:`source` domain and returns
250
+ signals in the same domain.
251
+
252
+ It provides a base class that can be used to create signal processing blocks that receive data from any
253
+ generating :attr:`source` and generates an output via the generator :meth:`result` in block-wise manner.
254
+ """
255
+
256
+ #: Data source; :class:`~acoular.base.Generator` or derived object.
257
+ source = Instance(Generator)
258
+
259
+ #: Sampling frequency of output signal, as given by :attr:`source`.
260
+ sample_freq = Delegate('source')
261
+
262
+ #: Number of channels in output, as given by :attr:`source`.
263
+ numchannels = Delegate('source')
264
+
265
+ #: Number of samples / snapshots in output, as given by :attr:`source`.
266
+ numsamples = Delegate('source')
267
+
268
+ # internal identifier
269
+ digest = Property(depends_on=['source.digest'])
270
+
271
+ @cached_property
272
+ def _get_digest(self):
273
+ return digest(self)
274
+
275
+ def result(self, num):
276
+ """Python generator that processes the source data and yields the output block-wise.
277
+
278
+ This method needs to be implemented by the derived classes.
279
+
280
+ Parameters
281
+ ----------
282
+ num : int
283
+ The size of the first dimension of the blocks to be yielded
284
+
285
+ Yields
286
+ ------
287
+ numpy.ndarray
288
+ Two-dimensional output data block of shape (num, ...)
289
+ """
290
+ yield from self.source.result(num)
291
+
292
+
293
+ class TimeInOut(TimeOut):
294
+ """Deprecated alias for :class:`~acoular.base.TimeOut`.
295
+
296
+ .. deprecated:: 24.10
297
+ Using :class:`~acoular.base.TimeInOut` is deprecated and will be removed in Acoular 25.07.
298
+ Use :class:`~acoular.base.TimeOut` instead.
299
+ """
300
+
301
+ #: Data source; :class:`~acoular.base.SamplesGenerator` or derived object.
302
+ source = Instance(SamplesGenerator)
303
+
304
+ def __init__(self, *args, **kwargs):
305
+ super().__init__(*args, **kwargs)
306
+ import warnings
307
+
308
+ warnings.warn(
309
+ 'TimeInOut is deprecated and will be removed in Acoular 25.07. Use TimeOut instead.',
310
+ DeprecationWarning,
311
+ stacklevel=2,
312
+ )
acoular/configuration.py CHANGED
@@ -35,7 +35,7 @@ if 'numpy' in sys.modules:
35
35
  np.show_config()
36
36
  sys.stdout = orig_stdout
37
37
  # check if it uses OpenBLAS or another library
38
- if 'openblas' in temp_stdout.getvalue().lower():
38
+ if 'openblas' in temp_stdout.getvalue().lower() and environ.get('OPENBLAS_NUM_THREADS') != '1':
39
39
  # it's OpenBLAS, set numba threads=1 to avoid overcommittment
40
40
  import numba
41
41
 
@@ -54,7 +54,7 @@ else:
54
54
  environ['OPENBLAS_NUM_THREADS'] = '1'
55
55
 
56
56
  # this loads numpy, so we have to defer loading until OpenBLAS check is done
57
- from traits.api import Bool, Either, HasStrictTraits, Property, Str, Trait, cached_property
57
+ from traits.api import Bool, Enum, HasStrictTraits, Property, Str, Trait, cached_property
58
58
 
59
59
 
60
60
  class Config(HasStrictTraits):
@@ -97,7 +97,7 @@ class Config(HasStrictTraits):
97
97
  #: If 'pytables' can not be imported, 'h5py' is used.
98
98
  h5library = Property()
99
99
 
100
- _h5library = Either('pytables', 'tables', 'h5py', default='pytables')
100
+ _h5library = Enum('pytables', 'tables', 'h5py')
101
101
 
102
102
  #: Defines the path to the directory containing Acoulars cache files.
103
103
  #: If the specified :attr:`cache_dir` directory does not exist,
@@ -61,7 +61,7 @@ def run():
61
61
 
62
62
  # analyze the data and generate map
63
63
 
64
- ps = ac.PowerSpectra(time_data=pa, block_size=128, window='Hanning')
64
+ ps = ac.PowerSpectra(source=pa, block_size=128, window='Hanning')
65
65
 
66
66
  rg = ac.RectGrid(x_min=-0.2, x_max=0.2, y_min=-0.2, y_max=0.2, z=0.3, increment=0.01)
67
67
  st = ac.SteeringVector(grid=rg, mics=mg)
acoular/environments.py CHANGED
@@ -43,9 +43,9 @@ from numpy import (
43
43
  vstack,
44
44
  zeros_like,
45
45
  )
46
- from numpy.linalg.linalg import norm
47
46
  from scipy.integrate import ode
48
47
  from scipy.interpolate import LinearNDInterpolator
48
+ from scipy.linalg import norm
49
49
  from scipy.spatial import ConvexHull
50
50
  from traits.api import CArray, Dict, Float, HasPrivateTraits, Int, Property, Trait, cached_property
51
51
 
@@ -283,8 +283,9 @@ class FlowField(HasPrivateTraits):
283
283
 
284
284
 
285
285
  class SlotJet(FlowField):
286
- """Provides an analytical approximation of the flow field of a slot jet,
287
- see :ref:`Albertson et al., 1950<Albertson1950>`.
286
+ """Provides an analytical approximation of the flow field of a slot jet.
287
+
288
+ See :cite:`Albertson1950` for details.
288
289
  """
289
290
 
290
291
  #: Exit velocity at jet origin, i.e. the nozzle. Defaults to 0.
@@ -364,8 +365,9 @@ class SlotJet(FlowField):
364
365
 
365
366
 
366
367
  class OpenJet(FlowField):
367
- """Provides an analytical approximation of the flow field of an open jet,
368
- see :ref:`Albertson et al., 1950<Albertson1950>`.
368
+ """Provides an analytical approximation of the flow field of an open jet.
369
+
370
+ See :cite:`Albertson1950` for details.
369
371
 
370
372
  Notes
371
373
  -----