acoular 24.10__tar.gz → 25.3__tar.gz

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.
Files changed (69) hide show
  1. {acoular-24.10 → acoular-25.3}/PKG-INFO +39 -17
  2. {acoular-24.10 → acoular-25.3}/README.md +23 -13
  3. {acoular-24.10 → acoular-25.3}/acoular/__init__.py +5 -2
  4. acoular-25.3/acoular/aiaa/__init__.py +12 -0
  5. {acoular-24.10/acoular/tools → acoular-25.3/acoular/aiaa}/aiaa.py +23 -28
  6. {acoular-24.10 → acoular-25.3}/acoular/base.py +75 -55
  7. acoular-25.3/acoular/calib.py +173 -0
  8. {acoular-24.10 → acoular-25.3}/acoular/configuration.py +11 -9
  9. {acoular-24.10 → acoular-25.3}/acoular/demo/__init__.py +1 -0
  10. {acoular-24.10 → acoular-25.3}/acoular/demo/acoular_demo.py +31 -18
  11. acoular-25.3/acoular/deprecation.py +85 -0
  12. acoular-25.3/acoular/environments.py +941 -0
  13. {acoular-24.10 → acoular-25.3}/acoular/fastFuncs.py +90 -84
  14. {acoular-24.10 → acoular-25.3}/acoular/fbeamform.py +203 -411
  15. acoular-25.3/acoular/fprocess.py +478 -0
  16. acoular-25.3/acoular/grids.py +1589 -0
  17. {acoular-24.10 → acoular-25.3}/acoular/h5cache.py +29 -40
  18. {acoular-24.10 → acoular-25.3}/acoular/h5files.py +2 -6
  19. acoular-25.3/acoular/microphones.py +262 -0
  20. acoular-25.3/acoular/process.py +975 -0
  21. {acoular-24.10 → acoular-25.3}/acoular/sdinput.py +23 -20
  22. acoular-25.3/acoular/signals.py +673 -0
  23. acoular-25.3/acoular/sources.py +2455 -0
  24. acoular-25.3/acoular/spectra.py +725 -0
  25. {acoular-24.10 → acoular-25.3}/acoular/tbeamform.py +79 -202
  26. {acoular-24.10 → acoular-25.3}/acoular/tfastfuncs.py +21 -21
  27. {acoular-24.10 → acoular-25.3}/acoular/tools/__init__.py +2 -8
  28. acoular-25.3/acoular/tools/helpers.py +403 -0
  29. {acoular-24.10 → acoular-25.3}/acoular/tools/metrics.py +4 -4
  30. acoular-25.3/acoular/tools/utils.py +116 -0
  31. {acoular-24.10 → acoular-25.3}/acoular/tprocess.py +348 -309
  32. {acoular-24.10 → acoular-25.3}/acoular/traitsviews.py +10 -10
  33. acoular-25.3/acoular/trajectory.py +197 -0
  34. {acoular-24.10 → acoular-25.3}/acoular/version.py +2 -2
  35. {acoular-24.10 → acoular-25.3}/pyproject.toml +50 -8
  36. acoular-24.10/acoular/calib.py +0 -78
  37. acoular-24.10/acoular/environments.py +0 -689
  38. acoular-24.10/acoular/fprocess.py +0 -368
  39. acoular-24.10/acoular/grids.py +0 -1220
  40. acoular-24.10/acoular/microphones.py +0 -139
  41. acoular-24.10/acoular/process.py +0 -464
  42. acoular-24.10/acoular/signals.py +0 -371
  43. acoular-24.10/acoular/sources.py +0 -1633
  44. acoular-24.10/acoular/spectra.py +0 -749
  45. acoular-24.10/acoular/tools/helpers.py +0 -189
  46. acoular-24.10/acoular/tools/utils.py +0 -210
  47. acoular-24.10/acoular/trajectory.py +0 -124
  48. {acoular-24.10 → acoular-25.3}/.gitignore +0 -0
  49. {acoular-24.10 → acoular-25.3}/AUTHORS.rst +0 -0
  50. {acoular-24.10 → acoular-25.3}/LICENSE +0 -0
  51. {acoular-24.10 → acoular-25.3}/acoular/internal.py +0 -0
  52. {acoular-24.10 → acoular-25.3}/acoular/xml/HW90D240_f10.xml +0 -0
  53. {acoular-24.10 → acoular-25.3}/acoular/xml/W90_D105_f10.xml +0 -0
  54. {acoular-24.10 → acoular-25.3}/acoular/xml/acousticam_2c.xml +0 -0
  55. {acoular-24.10 → acoular-25.3}/acoular/xml/acousticam_4c.xml +0 -0
  56. {acoular-24.10 → acoular-25.3}/acoular/xml/array38.xml +0 -0
  57. {acoular-24.10 → acoular-25.3}/acoular/xml/array92x.xml +0 -0
  58. {acoular-24.10 → acoular-25.3}/acoular/xml/array_56.xml +0 -0
  59. {acoular-24.10 → acoular-25.3}/acoular/xml/array_56_10_9.xml +0 -0
  60. {acoular-24.10 → acoular-25.3}/acoular/xml/array_56_bomb.xml +0 -0
  61. {acoular-24.10 → acoular-25.3}/acoular/xml/array_56_v2.xml +0 -0
  62. {acoular-24.10 → acoular-25.3}/acoular/xml/array_64.xml +0 -0
  63. {acoular-24.10 → acoular-25.3}/acoular/xml/array_84_10_9.xml +0 -0
  64. {acoular-24.10 → acoular-25.3}/acoular/xml/array_84_bomb_v3.xml +0 -0
  65. {acoular-24.10 → acoular-25.3}/acoular/xml/calib_vw_ring32.xml +0 -0
  66. {acoular-24.10 → acoular-25.3}/acoular/xml/gfai_ring32.xml +0 -0
  67. {acoular-24.10 → acoular-25.3}/acoular/xml/minidsp_uma-16.xml +0 -0
  68. {acoular-24.10 → acoular-25.3}/acoular/xml/minidsp_uma-16_mirrored.xml +0 -0
  69. {acoular-24.10 → acoular-25.3}/acoular/xml/tub_vogel64.xml +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: acoular
3
- Version: 24.10
3
+ Version: 25.3
4
4
  Summary: Python library for acoustic beamforming
5
5
  Project-URL: homepage, https://acoular.org
6
6
  Project-URL: documentation, https://acoular.org
@@ -45,8 +45,9 @@ Classifier: License :: OSI Approved :: BSD License
45
45
  Classifier: Programming Language :: Python :: 3.10
46
46
  Classifier: Programming Language :: Python :: 3.11
47
47
  Classifier: Programming Language :: Python :: 3.12
48
+ Classifier: Programming Language :: Python :: 3.13
48
49
  Classifier: Topic :: Scientific/Engineering :: Physics
49
- Requires-Python: <=12,>=3.10
50
+ Requires-Python: <3.14,>=3.10
50
51
  Requires-Dist: numba
51
52
  Requires-Dist: numpy
52
53
  Requires-Dist: scikit-learn
@@ -63,9 +64,14 @@ Requires-Dist: numpydoc; extra == 'dev'
63
64
  Requires-Dist: pickleshare; extra == 'dev'
64
65
  Requires-Dist: pylops; extra == 'dev'
65
66
  Requires-Dist: pytest; extra == 'dev'
67
+ Requires-Dist: pytest-cases; extra == 'dev'
66
68
  Requires-Dist: pytest-cov; extra == 'dev'
69
+ Requires-Dist: pytest-env; extra == 'dev'
70
+ Requires-Dist: pytest-mock; extra == 'dev'
71
+ Requires-Dist: pytest-profiling; extra == 'dev'
72
+ Requires-Dist: pytest-regtest; extra == 'dev'
67
73
  Requires-Dist: pyyaml; extra == 'dev'
68
- Requires-Dist: ruff==0.4.1; extra == 'dev'
74
+ Requires-Dist: ruff==0.8.1; extra == 'dev'
69
75
  Requires-Dist: setuptools; extra == 'dev'
70
76
  Requires-Dist: sounddevice; extra == 'dev'
71
77
  Requires-Dist: sphinx; extra == 'dev'
@@ -89,8 +95,14 @@ Requires-Dist: pylops; extra == 'full'
89
95
  Requires-Dist: sounddevice; extra == 'full'
90
96
  Provides-Extra: tests
91
97
  Requires-Dist: h5py; extra == 'tests'
98
+ Requires-Dist: pylops; extra == 'tests'
92
99
  Requires-Dist: pytest; extra == 'tests'
100
+ Requires-Dist: pytest-cases; extra == 'tests'
93
101
  Requires-Dist: pytest-cov; extra == 'tests'
102
+ Requires-Dist: pytest-env; extra == 'tests'
103
+ Requires-Dist: pytest-mock; extra == 'tests'
104
+ Requires-Dist: pytest-profiling; extra == 'tests'
105
+ Requires-Dist: pytest-regtest; extra == 'tests'
94
106
  Requires-Dist: pyyaml; extra == 'tests'
95
107
  Requires-Dist: sounddevice; extra == 'tests'
96
108
  Requires-Dist: traitsui; extra == 'tests'
@@ -185,35 +197,45 @@ If you are interested in contributing, have a look at the [CONTRIBUTING.md](CONT
185
197
  This reads data from 64 microphone channels and computes a beamforming map for the 8kHz third octave band:
186
198
 
187
199
  ```python
188
- from os import path
189
- import acoular
190
- from matplotlib.pylab import figure, plot, axis, imshow, colorbar, show
200
+ from pathlib import Path
201
+
202
+ import acoular as ac
203
+ import matplotlib.pylab as plt
191
204
 
192
205
  # this file contains the microphone coordinates
193
- micgeofile = path.join(path.split(acoular.__file__)[0],'xml','array_64.xml')
206
+ micgeofile = Path(ac.__file__).parent / 'xml' / 'array_64.xml'
194
207
  # set up object managing the microphone coordinates
195
- mg = acoular.MicGeom( from_file=micgeofile )
208
+ mg = ac.MicGeom( file=micgeofile )
209
+ # generate test data, in real life this would come from an array measurement
210
+ p = ac.demo.create_three_sources(mg, h5savefile='three_sources.h5')
196
211
  # set up object managing the microphone array data (usually from measurement)
197
- ts = acoular.TimeSamples( name='three_sources.h5' )
212
+ ts = ac.TimeSamples( file='three_sources.h5')
198
213
  # set up object managing the cross spectral matrix computation
199
- ps = acoular.PowerSpectra( source=ts, block_size=128, window='Hanning' )
214
+ ps = ac.PowerSpectra( source=ts, block_size=128, window='Hanning' )
215
+ # alternatively, you can use the in-memory Mixer object directly:
216
+ # ps = ac.PowerSpectra( source=p, block_size=128, window='Hanning' )
200
217
  # set up object managing the mapping grid
201
- rg = acoular.RectGrid( x_min=-0.2, x_max=0.2, y_min=-0.2, y_max=0.2, z=0.3, \
218
+ rg = ac.RectGrid( x_min=-0.2, x_max=0.2, y_min=-0.2, y_max=0.2, z=-0.3, \
202
219
  increment=0.01 )
203
220
  # set up steering vector, implicitely contains also the standard quiescent
204
221
  # environment with standard speed of sound
205
- st = acoular.SteeringVector( grid = rg, mics=mg )
222
+ st = ac.SteeringVector( grid = rg, mics=mg )
206
223
  # set up the object managing the delay & sum beamformer
207
- bb = acoular.BeamformerBase( freq_data=ps, steer=st )
224
+ bb = ac.BeamformerBase( freq_data=ps, steer=st )
208
225
  # request the result in the 8kHz third octave band from approriate FFT-Lines
209
226
  # this starts the actual computation (data intake, FFT, Welch CSM, beamforming)
210
227
  pm = bb.synthetic( 8000, 3 )
211
228
  # compute the sound pressure level
212
- Lm = acoular.L_p( pm )
229
+ Lm = ac.L_p( pm )
213
230
  # plot the map
214
- imshow( Lm.T, origin='lower', vmin=Lm.max()-10, extent=rg.extend(), \
231
+ plt.imshow( Lm.T, origin='lower', vmin=Lm.max()-10, extent=rg.extend(), \
215
232
  interpolation='bicubic')
216
- colorbar()
233
+ plt.title('Beamformer (base) for 3 sources measured for 8000 Hz')
234
+ plt.xlabel('x in m')
235
+ plt.ylabel('y in m')
236
+ plt.colorbar(label=r'$L_p$')
237
+ plt.savefig('three_sources.png', dpi=300, bbox_inches='tight')
238
+ plt.show()
217
239
  ```
218
240
 
219
241
  ![result](https://github.com/acoular/acoular/blob/master/docs/source/get_started/three_source_py3_colormap.png?raw=true)
@@ -87,35 +87,45 @@ If you are interested in contributing, have a look at the [CONTRIBUTING.md](CONT
87
87
  This reads data from 64 microphone channels and computes a beamforming map for the 8kHz third octave band:
88
88
 
89
89
  ```python
90
- from os import path
91
- import acoular
92
- from matplotlib.pylab import figure, plot, axis, imshow, colorbar, show
90
+ from pathlib import Path
91
+
92
+ import acoular as ac
93
+ import matplotlib.pylab as plt
93
94
 
94
95
  # this file contains the microphone coordinates
95
- micgeofile = path.join(path.split(acoular.__file__)[0],'xml','array_64.xml')
96
+ micgeofile = Path(ac.__file__).parent / 'xml' / 'array_64.xml'
96
97
  # set up object managing the microphone coordinates
97
- mg = acoular.MicGeom( from_file=micgeofile )
98
+ mg = ac.MicGeom( file=micgeofile )
99
+ # generate test data, in real life this would come from an array measurement
100
+ p = ac.demo.create_three_sources(mg, h5savefile='three_sources.h5')
98
101
  # set up object managing the microphone array data (usually from measurement)
99
- ts = acoular.TimeSamples( name='three_sources.h5' )
102
+ ts = ac.TimeSamples( file='three_sources.h5')
100
103
  # set up object managing the cross spectral matrix computation
101
- ps = acoular.PowerSpectra( source=ts, block_size=128, window='Hanning' )
104
+ ps = ac.PowerSpectra( source=ts, block_size=128, window='Hanning' )
105
+ # alternatively, you can use the in-memory Mixer object directly:
106
+ # ps = ac.PowerSpectra( source=p, block_size=128, window='Hanning' )
102
107
  # set up object managing the mapping grid
103
- rg = acoular.RectGrid( x_min=-0.2, x_max=0.2, y_min=-0.2, y_max=0.2, z=0.3, \
108
+ rg = ac.RectGrid( x_min=-0.2, x_max=0.2, y_min=-0.2, y_max=0.2, z=-0.3, \
104
109
  increment=0.01 )
105
110
  # set up steering vector, implicitely contains also the standard quiescent
106
111
  # environment with standard speed of sound
107
- st = acoular.SteeringVector( grid = rg, mics=mg )
112
+ st = ac.SteeringVector( grid = rg, mics=mg )
108
113
  # set up the object managing the delay & sum beamformer
109
- bb = acoular.BeamformerBase( freq_data=ps, steer=st )
114
+ bb = ac.BeamformerBase( freq_data=ps, steer=st )
110
115
  # request the result in the 8kHz third octave band from approriate FFT-Lines
111
116
  # this starts the actual computation (data intake, FFT, Welch CSM, beamforming)
112
117
  pm = bb.synthetic( 8000, 3 )
113
118
  # compute the sound pressure level
114
- Lm = acoular.L_p( pm )
119
+ Lm = ac.L_p( pm )
115
120
  # plot the map
116
- imshow( Lm.T, origin='lower', vmin=Lm.max()-10, extent=rg.extend(), \
121
+ plt.imshow( Lm.T, origin='lower', vmin=Lm.max()-10, extent=rg.extend(), \
117
122
  interpolation='bicubic')
118
- colorbar()
123
+ plt.title('Beamformer (base) for 3 sources measured for 8000 Hz')
124
+ plt.xlabel('x in m')
125
+ plt.ylabel('y in m')
126
+ plt.colorbar(label=r'$L_p$')
127
+ plt.savefig('three_sources.png', dpi=300, bbox_inches='tight')
128
+ plt.show()
119
129
  ```
120
130
 
121
131
  ![result](https://github.com/acoular/acoular/blob/master/docs/source/get_started/three_source_py3_colormap.png?raw=true)
@@ -9,7 +9,7 @@ import os # noqa: I001
9
9
  # config must be imported before any submodules containing numpy, see #322.
10
10
  from .configuration import config
11
11
 
12
- from . import demo, tools
12
+ from . import demo, tools, aiaa
13
13
  from .base import (
14
14
  Generator,
15
15
  InOut,
@@ -74,6 +74,8 @@ from .sdinput import SoundDeviceSamplesGenerator
74
74
  from .signals import (
75
75
  FiltWNoiseGenerator,
76
76
  GenericSignalGenerator,
77
+ NoiseGenerator,
78
+ PeriodicSignalGenerator,
77
79
  PNoiseGenerator,
78
80
  SignalGenerator,
79
81
  SineGenerator,
@@ -93,7 +95,8 @@ from .sources import (
93
95
  TimeSamples,
94
96
  UncorrelatedNoiseSource,
95
97
  )
96
- from .spectra import BaseSpectra, PowerSpectra, PowerSpectraImport, synthetic
98
+ from .tools.helpers import synthetic
99
+ from .spectra import BaseSpectra, PowerSpectra, PowerSpectraImport
97
100
  from .spectra import PowerSpectra as EigSpectra
98
101
  from .tbeamform import (
99
102
  BeamformerCleant,
@@ -0,0 +1,12 @@
1
+ # ------------------------------------------------------------------------------
2
+ # Copyright (c) Acoular Development Team.
3
+ # ------------------------------------------------------------------------------
4
+ """Provides classes for importing AIAA Array Benchmarks.
5
+
6
+ .. autosummary::
7
+ :toctree: generated/
8
+
9
+ aiaa
10
+ """
11
+
12
+ from .aiaa import CsmAIAABenchmark, MicAIAABenchmark, TimeSamplesAIAABenchmark, TriggerAIAABenchmark
@@ -1,8 +1,8 @@
1
1
  # ------------------------------------------------------------------------------
2
2
  # Copyright (c) Acoular Development Team.
3
3
  # ------------------------------------------------------------------------------
4
- """Classes for importing AIAA Array Benchmarks
5
- from . import aiaa
4
+ """Classes for importing AIAA Array Benchmarks.
5
+
6
6
  These classes allow importing data from HDF5 files following the specifications of
7
7
  the AIAA microphone array methods benchmarking effort:
8
8
  https://www-docs.b-tu.de/fg-akustik/public/veroeffentlichungen/ArrayMethodsFileFormatsR2P4Release.pdf .
@@ -12,8 +12,8 @@ the framework.
12
12
 
13
13
  Examples
14
14
  --------
15
- >>> micgeom = MicAIAABenchmark(name='some_benchmarkdata.h5') # doctest: +SKIP
16
- >>> timedata = TimeSamplesAIAABenchmark(name='some_benchmarkdata.h5') # doctest: +SKIP
15
+ >>> micgeom = MicAIAABenchmark(file='some_benchmarkdata.h5') # doctest: +SKIP
16
+ >>> timedata = TimeSamplesAIAABenchmark(file='some_benchmarkdata.h5') # doctest: +SKIP
17
17
 
18
18
 
19
19
  .. autosummary::
@@ -23,10 +23,9 @@ Examples
23
23
  TriggerAIAABenchmark
24
24
  CsmAIAABenchmark
25
25
  MicAIAABenchmark
26
- """
26
+ """ # noqa: W505
27
27
 
28
28
  import contextlib
29
- from os import path
30
29
 
31
30
  from numpy import array
32
31
  from traits.api import (
@@ -38,11 +37,13 @@ from traits.api import (
38
37
  property_depends_on,
39
38
  )
40
39
 
40
+ from acoular.deprecation import deprecated_alias
41
41
  from acoular.h5files import H5FileBase, _get_h5file_class
42
42
  from acoular.internal import digest
43
43
  from acoular.microphones import MicGeom
44
44
  from acoular.sources import TimeSamples
45
45
  from acoular.spectra import PowerSpectraImport
46
+ from acoular.tools.utils import get_file_basename
46
47
 
47
48
 
48
49
  class TimeSamplesAIAABenchmark(TimeSamples):
@@ -58,7 +59,7 @@ class TimeSamplesAIAABenchmark(TimeSamples):
58
59
  """Loads timedata from .h5 file. Only for internal use."""
59
60
  self.data = self.h5f.get_data_by_reference('MicrophoneData/microphoneDataPa')
60
61
  self.sample_freq = self.h5f.get_node_attribute(self.data, 'sampleRateHz')
61
- (self.numsamples, self.numchannels) = self.data.shape
62
+ (self.num_samples, self.num_channels) = self.data.shape
62
63
 
63
64
  def _load_metadata(self):
64
65
  """Loads metadata from .h5 file. Only for internal use."""
@@ -80,23 +81,24 @@ class TriggerAIAABenchmark(TimeSamplesAIAABenchmark):
80
81
  """Loads timedata from .h5 file. Only for internal use."""
81
82
  self.data = self.h5f.get_data_by_reference('TachoData/tachoDataV')
82
83
  self.sample_freq = self.h5f.get_node_attribute(self.data, 'sampleRateHz')
83
- (self.numsamples, self.numchannels) = self.data.shape
84
+ (self.num_samples, self.num_channels) = self.data.shape
84
85
 
85
86
 
87
+ @deprecated_alias({'name': 'file'})
86
88
  class CsmAIAABenchmark(PowerSpectraImport):
87
89
  """Class to load the CSM that is stored in AIAA Benchmark HDF5 file."""
88
90
 
89
91
  #: Full name of the .h5 file with data
90
- name = File(filter=['*.h5'], desc='name of data file')
92
+ file = File(filter=['*.h5'], exists=True, desc='name of data file')
91
93
 
92
94
  #: Basename of the .h5 file with data, is set automatically.
93
95
  basename = Property(
94
- depends_on='name',
96
+ depends_on=['file'],
95
97
  desc='basename of data file',
96
98
  )
97
99
 
98
100
  #: number of channels
99
- numchannels = Property()
101
+ num_channels = Property()
100
102
 
101
103
  #: HDF5 file object
102
104
  h5f = Instance(H5FileBase, transient=True)
@@ -110,19 +112,16 @@ class CsmAIAABenchmark(PowerSpectraImport):
110
112
 
111
113
  @cached_property
112
114
  def _get_basename(self):
113
- return path.splitext(path.basename(self.name))[0]
115
+ return get_file_basename(self.file)
114
116
 
115
117
  @on_trait_change('basename')
116
118
  def load_data(self):
117
119
  """Open the .h5 file and set attributes."""
118
- if not path.isfile(self.name):
119
- # no file there
120
- raise OSError('No such file: %s' % self.name)
121
120
  if self.h5f is not None:
122
121
  with contextlib.suppress(OSError):
123
122
  self.h5f.close()
124
123
  file = _get_h5file_class()
125
- self.h5f = file(self.name)
124
+ self.h5f = file(self.file)
126
125
 
127
126
  # @property_depends_on( 'block_size, ind_low, ind_high' )
128
127
  def _get_indices(self):
@@ -131,15 +130,15 @@ class CsmAIAABenchmark(PowerSpectraImport):
131
130
  except IndexError:
132
131
  return range(0)
133
132
 
134
- @property_depends_on('digest')
135
- def _get_numchannels(self):
133
+ @property_depends_on(['digest'])
134
+ def _get_num_channels(self):
136
135
  try:
137
136
  attrs = self.h5f.get_data_by_reference('MetaData/ArrayAttributes')
138
137
  return self.h5f.get_node_attribute(attrs, 'microphoneCount')
139
138
  except IndexError:
140
139
  return 0
141
140
 
142
- @property_depends_on('digest')
141
+ @property_depends_on(['digest'])
143
142
  def _get_csm(self):
144
143
  """Loads cross spectral matrix from file."""
145
144
  csmre = self.h5f.get_data_by_reference('/CsmData/csmReal')[:].transpose((2, 0, 1))
@@ -167,19 +166,15 @@ class MicAIAABenchmark(MicGeom):
167
166
  file containing the measurement data.
168
167
  """
169
168
 
170
- #: Name of the .h5-file from wich to read the data.
171
- from_file = File(filter=['*.h5'], desc='name of the h5 file containing the microphone geometry')
169
+ #: Name of the .h5-file from which to read the data.
170
+ file = File(filter=['*.h5'], exists=True, desc='name of the h5 file containing the microphone geometry')
172
171
 
173
- @on_trait_change('basename')
172
+ @on_trait_change('file')
174
173
  def import_mpos(self):
175
174
  """Import the microphone positions from .h5 file.
176
175
  Called when :attr:`basename` changes.
177
176
  """
178
- if not path.isfile(self.from_file):
179
- # no file there
180
- raise OSError('No such file: %s' % self.from_file)
181
-
182
177
  file = _get_h5file_class()
183
- h5f = file(self.from_file, mode='r')
184
- self.mpos_tot = h5f.get_data_by_reference('MetaData/ArrayAttributes/microphonePositionsM')[:].swapaxes(0, 1)
178
+ h5f = file(self.file, mode='r')
179
+ self.pos_total = h5f.get_data_by_reference('MetaData/ArrayAttributes/microphonePositionsM')[:].swapaxes(0, 1)
185
180
  h5f.close()
@@ -3,9 +3,9 @@
3
3
  # ------------------------------------------------------------------------------
4
4
  """Implements base classes for signal processing blocks in Acoular.
5
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.
6
+ The classes in this module are abstract base classes that provide a common interface for all classes
7
+ that generate an output via the generator :meth:`result` in block-wise manner. They are not intended
8
+ to be used directly, but to be subclassed by classes that implement the actual signal processing.
9
9
 
10
10
  .. autosummary::
11
11
  :toctree: generated/
@@ -19,42 +19,54 @@ subclassed by classes that implement the actual signal processing.
19
19
  TimeInOut
20
20
  """
21
21
 
22
+ from abc import abstractmethod
23
+
22
24
  from traits.api import (
25
+ ABCHasStrictTraits,
23
26
  CArray,
24
- CLong,
27
+ CInt,
25
28
  Delegate,
26
29
  Float,
27
- HasPrivateTraits,
28
30
  Instance,
29
31
  Property,
30
32
  cached_property,
31
33
  )
32
34
 
33
- from acoular.internal import digest
35
+ # acoular imports
36
+ from .deprecation import deprecated_alias
37
+ from .internal import digest
34
38
 
35
39
 
36
- class Generator(HasPrivateTraits):
40
+ @deprecated_alias({'numchannels': 'num_channels', 'numsamples': 'num_samples'})
41
+ class Generator(ABCHasStrictTraits):
37
42
  """Interface for any generating signal processing block.
38
43
 
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
+ It provides a common interface for all classes, which generate an output via the generator
45
+ :meth:`result` in block-wise manner. It has a common set of traits that are used by all classes
46
+ that implement this interface. This includes the sampling frequency of the signal
47
+ (:attr:`sample_freq`), the number of samples (:attr:`num_samples`), and the number of channels
48
+ (:attr:`num_channels`). A private trait :attr:`digest` is used to store the internal identifier
49
+ of the object, which is a hash of the object's attributes.
50
+ This is used to check if the object's internal state has changed.
51
+
44
52
  """
45
53
 
46
54
  #: Sampling frequency of the signal, defaults to 1.0
47
55
  sample_freq = Float(1.0, desc='sampling frequency')
48
56
 
49
57
  #: Number of signal samples
50
- numsamples = CLong
58
+ num_samples = CInt
59
+
60
+ #: Number of channels
61
+ num_channels = CInt
51
62
 
52
63
  # internal identifier
53
- digest = Property(depends_on=['sample_freq', 'numsamples'])
64
+ digest = Property(depends_on=['sample_freq', 'num_samples', 'num_channels'])
54
65
 
55
66
  def _get_digest(self):
56
67
  return digest(self)
57
68
 
69
+ @abstractmethod
58
70
  def result(self, num):
59
71
  """Python generator that yields the output block-wise.
60
72
 
@@ -75,19 +87,19 @@ class Generator(HasPrivateTraits):
75
87
  class SamplesGenerator(Generator):
76
88
  """Interface for any generating multi-channel time domain signal processing block.
77
89
 
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
- """
90
+ It provides a common interface for all SamplesGenerator classes, which generate an output via
91
+ the generator :meth:`result` in block-wise manner. This class has no real functionality on its
92
+ own and should not be used directly.
81
93
 
82
- #: Number of channels
83
- numchannels = CLong
94
+ """
84
95
 
85
96
  # internal identifier
86
- digest = Property(depends_on=['sample_freq', 'numchannels', 'numsamples'])
97
+ digest = Property(depends_on=['sample_freq', 'num_samples', 'num_channels'])
87
98
 
88
99
  def _get_digest(self):
89
100
  return digest(self)
90
101
 
102
+ @abstractmethod
91
103
  def result(self, num):
92
104
  """Python generator that yields the output block-wise.
93
105
 
@@ -100,35 +112,35 @@ class SamplesGenerator(Generator):
100
112
  Yields
101
113
  ------
102
114
  numpy.ndarray
103
- The two-dimensional time-data block of shape (num, numchannels).
115
+ The two-dimensional time-data block of shape (num, num_channels).
104
116
  """
105
117
 
106
118
 
107
119
  class SpectraGenerator(Generator):
108
120
  """Interface for any generating multi-channel signal frequency domain processing block.
109
121
 
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
- """
122
+ It provides a common interface for all SpectraGenerator classes, which generate an output via
123
+ the generator :meth:`result` in block-wise manner. This class has no real functionality on its
124
+ own and should not be used directly.
113
125
 
114
- #: Number of channels
115
- numchannels = CLong
126
+ """
116
127
 
117
128
  #: Number of frequencies
118
- numfreqs = CLong
129
+ num_freqs = CInt
119
130
 
120
131
  #: 1-D array of frequencies
121
132
  freqs = CArray
122
133
 
123
134
  #: The length of the block used to calculate the spectra
124
- block_size = CLong
135
+ block_size = CInt
125
136
 
126
137
  # internal identifier
127
- digest = Property(depends_on=['sample_freq', 'numchannels', 'numsamples', 'numfreqs', 'block_size'])
138
+ digest = Property(depends_on=['sample_freq', 'num_samples', 'num_channels', 'num_freqs', 'block_size'])
128
139
 
129
140
  def _get_digest(self):
130
141
  return digest(self)
131
142
 
143
+ @abstractmethod
132
144
  def result(self, num=1):
133
145
  """Python generator that yields the output block-wise.
134
146
 
@@ -141,16 +153,18 @@ class SpectraGenerator(Generator):
141
153
  Yields
142
154
  ------
143
155
  numpy.ndarray
144
- A two-dimensional block of shape (num, numchannels*numfreqs).
156
+ A two-dimensional block of shape (num, num_channels * num_freqs).
145
157
  """
146
158
 
147
159
 
160
+ @deprecated_alias({'numchannels': 'num_channels', 'numsamples': 'num_samples'}, read_only=True)
148
161
  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.
162
+ """Abstract base class for any signal processing block that receives data from any
163
+ :attr:`source` domain and returns time domain signals.
151
164
 
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.
165
+ It provides a base class that can be used to create signal processing blocks that receive data
166
+ from any generating :attr:`source` and generates a time signal output via the generator
167
+ :meth:`result` in block-wise manner.
154
168
  """
155
169
 
156
170
  #: Data source; :class:`~acoular.base.Generator` or derived object.
@@ -160,10 +174,10 @@ class TimeOut(SamplesGenerator):
160
174
  sample_freq = Delegate('source')
161
175
 
162
176
  #: Number of channels in output, as given by :attr:`source`.
163
- numchannels = Delegate('source')
177
+ num_channels = Delegate('source')
164
178
 
165
179
  #: Number of samples in output, as given by :attr:`source`.
166
- numsamples = Delegate('source')
180
+ num_samples = Delegate('source')
167
181
 
168
182
  # internal identifier
169
183
  digest = Property(depends_on=['source.digest'])
@@ -172,6 +186,7 @@ class TimeOut(SamplesGenerator):
172
186
  def _get_digest(self):
173
187
  return digest(self)
174
188
 
189
+ @abstractmethod
175
190
  def result(self, num):
176
191
  """Python generator that processes the source data and yields the time-signal block-wise.
177
192
 
@@ -186,18 +201,18 @@ class TimeOut(SamplesGenerator):
186
201
  Yields
187
202
  ------
188
203
  numpy.ndarray
189
- Two-dimensional output data block of shape (num, numchannels)
204
+ Two-dimensional output data block of shape (num, num_channels)
190
205
  """
191
- yield from self.source.result(num)
192
206
 
193
207
 
208
+ @deprecated_alias({'numchannels': 'num_channels', 'numsamples': 'num_samples', 'numfreqs': 'num_freqs'}, read_only=True)
194
209
  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.
210
+ """Abstract base class for any signal processing block that receives data from any
211
+ :attr:`source` domain and returns frequency domain signals.
197
212
 
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.
213
+ It provides a base class that can be used to create signal processing blocks that receive data
214
+ from any generating :attr:`source` domain and generates a frequency domain output via the
215
+ generator :meth:`result` in block-wise manner.
201
216
  """
202
217
 
203
218
  #: Data source; :class:`~acoular.base.Generator` or derived object.
@@ -207,13 +222,13 @@ class SpectraOut(SpectraGenerator):
207
222
  sample_freq = Delegate('source')
208
223
 
209
224
  #: Number of channels in output, as given by :attr:`source`.
210
- numchannels = Delegate('source')
225
+ num_channels = Delegate('source')
211
226
 
212
227
  #: Number of snapshots in output, as given by :attr:`source`.
213
- numsamples = Delegate('source')
228
+ num_samples = Delegate('source')
214
229
 
215
230
  #: Number of frequencies in output, as given by :attr:`source`.
216
- numfreqs = Delegate('source')
231
+ num_freqs = Delegate('source')
217
232
 
218
233
  #: 1-D array of frequencies, as given by :attr:`source`.
219
234
  freqs = Delegate('source')
@@ -228,6 +243,7 @@ class SpectraOut(SpectraGenerator):
228
243
  def _get_digest(self):
229
244
  return digest(self)
230
245
 
246
+ @abstractmethod
231
247
  def result(self, num=1):
232
248
  """Python generator that processes the source data and yields the output block-wise.
233
249
 
@@ -240,17 +256,18 @@ class SpectraOut(SpectraGenerator):
240
256
  Yields
241
257
  ------
242
258
  numpy.ndarray
243
- A two-dimensional block of shape (num, numchannels*numfreqs).
259
+ A two-dimensional block of shape (num, num_channels * num_freqs).
244
260
  """
245
- yield from self.source.result(num)
246
261
 
247
262
 
263
+ @deprecated_alias({'numchannels': 'num_channels', 'numsamples': 'num_samples'}, read_only=True)
248
264
  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.
265
+ """Abstract base class for any signal processing block that receives data from any
266
+ :attr:`source` domain and returns signals in the same domain.
251
267
 
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.
268
+ It provides a base class that can be used to create signal processing blocks that receive data
269
+ from any generating :attr:`source` and generates an output via the generator :meth:`result` in
270
+ block-wise manner.
254
271
  """
255
272
 
256
273
  #: Data source; :class:`~acoular.base.Generator` or derived object.
@@ -260,10 +277,13 @@ class InOut(SamplesGenerator, SpectraGenerator):
260
277
  sample_freq = Delegate('source')
261
278
 
262
279
  #: Number of channels in output, as given by :attr:`source`.
263
- numchannels = Delegate('source')
280
+ num_channels = Delegate('source')
281
+
282
+ #: Number of frequencies in output, as given by :attr:`source`.
283
+ num_freqs = Delegate('source')
264
284
 
265
285
  #: Number of samples / snapshots in output, as given by :attr:`source`.
266
- numsamples = Delegate('source')
286
+ num_samples = Delegate('source')
267
287
 
268
288
  # internal identifier
269
289
  digest = Property(depends_on=['source.digest'])
@@ -272,6 +292,7 @@ class InOut(SamplesGenerator, SpectraGenerator):
272
292
  def _get_digest(self):
273
293
  return digest(self)
274
294
 
295
+ @abstractmethod
275
296
  def result(self, num):
276
297
  """Python generator that processes the source data and yields the output block-wise.
277
298
 
@@ -287,7 +308,6 @@ class InOut(SamplesGenerator, SpectraGenerator):
287
308
  numpy.ndarray
288
309
  Two-dimensional output data block of shape (num, ...)
289
310
  """
290
- yield from self.source.result(num)
291
311
 
292
312
 
293
313
  class TimeInOut(TimeOut):