acoular 24.3__py3-none-any.whl → 24.7__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.
Files changed (139) hide show
  1. acoular/__init__.py +119 -54
  2. acoular/calib.py +29 -38
  3. acoular/configuration.py +132 -82
  4. acoular/demo/__init__.py +10 -4
  5. acoular/demo/acoular_demo.py +73 -55
  6. acoular/environments.py +270 -264
  7. acoular/fastFuncs.py +366 -196
  8. acoular/fbeamform.py +1797 -1934
  9. acoular/grids.py +504 -548
  10. acoular/h5cache.py +74 -83
  11. acoular/h5files.py +159 -142
  12. acoular/internal.py +13 -14
  13. acoular/microphones.py +57 -53
  14. acoular/sdinput.py +57 -53
  15. acoular/signals.py +180 -178
  16. acoular/sources.py +920 -724
  17. acoular/spectra.py +353 -363
  18. acoular/tbeamform.py +416 -416
  19. acoular/tfastfuncs.py +180 -104
  20. acoular/tools/__init__.py +25 -0
  21. acoular/tools/aiaa.py +185 -0
  22. acoular/tools/helpers.py +189 -0
  23. acoular/tools/metrics.py +165 -0
  24. acoular/tprocess.py +1240 -1182
  25. acoular/traitsviews.py +513 -501
  26. acoular/trajectory.py +50 -52
  27. acoular/version.py +5 -6
  28. acoular/xml/minidsp_uma-16.xml +20 -0
  29. acoular/xml/{minidsp_uma16.xml → minidsp_uma-16_mirrored.xml} +3 -0
  30. {acoular-24.3.dist-info → acoular-24.7.dist-info}/METADATA +58 -39
  31. acoular-24.7.dist-info/RECORD +50 -0
  32. {acoular-24.3.dist-info → acoular-24.7.dist-info}/WHEEL +1 -1
  33. acoular-24.7.dist-info/licenses/LICENSE +28 -0
  34. acoular/fileimport.py +0 -380
  35. acoular/nidaqimport.py +0 -273
  36. acoular/tests/reference_data/BeamformerBase.npy +0 -0
  37. acoular/tests/reference_data/BeamformerBaseFalse1.npy +0 -0
  38. acoular/tests/reference_data/BeamformerBaseFalse2.npy +0 -0
  39. acoular/tests/reference_data/BeamformerBaseFalse3.npy +0 -0
  40. acoular/tests/reference_data/BeamformerBaseFalse4.npy +0 -0
  41. acoular/tests/reference_data/BeamformerBaseTrue1.npy +0 -0
  42. acoular/tests/reference_data/BeamformerBaseTrue2.npy +0 -0
  43. acoular/tests/reference_data/BeamformerBaseTrue3.npy +0 -0
  44. acoular/tests/reference_data/BeamformerBaseTrue4.npy +0 -0
  45. acoular/tests/reference_data/BeamformerCMFLassoLarsBIC.npy +0 -0
  46. acoular/tests/reference_data/BeamformerCMFNNLS.npy +0 -0
  47. acoular/tests/reference_data/BeamformerCapon.npy +0 -0
  48. acoular/tests/reference_data/BeamformerClean.npy +0 -0
  49. acoular/tests/reference_data/BeamformerCleansc.npy +0 -0
  50. acoular/tests/reference_data/BeamformerCleant.npy +0 -0
  51. acoular/tests/reference_data/BeamformerCleantSq.npy +0 -0
  52. acoular/tests/reference_data/BeamformerCleantSqTraj.npy +0 -0
  53. acoular/tests/reference_data/BeamformerCleantTraj.npy +0 -0
  54. acoular/tests/reference_data/BeamformerDamas.npy +0 -0
  55. acoular/tests/reference_data/BeamformerDamasPlus.npy +0 -0
  56. acoular/tests/reference_data/BeamformerEig.npy +0 -0
  57. acoular/tests/reference_data/BeamformerEigFalse1.npy +0 -0
  58. acoular/tests/reference_data/BeamformerEigFalse2.npy +0 -0
  59. acoular/tests/reference_data/BeamformerEigFalse3.npy +0 -0
  60. acoular/tests/reference_data/BeamformerEigFalse4.npy +0 -0
  61. acoular/tests/reference_data/BeamformerEigTrue1.npy +0 -0
  62. acoular/tests/reference_data/BeamformerEigTrue2.npy +0 -0
  63. acoular/tests/reference_data/BeamformerEigTrue3.npy +0 -0
  64. acoular/tests/reference_data/BeamformerEigTrue4.npy +0 -0
  65. acoular/tests/reference_data/BeamformerFunctional.npy +0 -0
  66. acoular/tests/reference_data/BeamformerGIB.npy +0 -0
  67. acoular/tests/reference_data/BeamformerGridlessOrth.npy +0 -0
  68. acoular/tests/reference_data/BeamformerMusic.npy +0 -0
  69. acoular/tests/reference_data/BeamformerOrth.npy +0 -0
  70. acoular/tests/reference_data/BeamformerSODIX.npy +0 -0
  71. acoular/tests/reference_data/BeamformerTime.npy +0 -0
  72. acoular/tests/reference_data/BeamformerTimeSq.npy +0 -0
  73. acoular/tests/reference_data/BeamformerTimeSqTraj.npy +0 -0
  74. acoular/tests/reference_data/BeamformerTimeTraj.npy +0 -0
  75. acoular/tests/reference_data/Environment.npy +0 -0
  76. acoular/tests/reference_data/Example1_numerical_values_testsum.h5 +0 -0
  77. acoular/tests/reference_data/FiltFiltOctave__.npy +0 -0
  78. acoular/tests/reference_data/FiltFiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
  79. acoular/tests/reference_data/FiltFreqWeight_weight_A_.npy +0 -0
  80. acoular/tests/reference_data/FiltFreqWeight_weight_C_.npy +0 -0
  81. acoular/tests/reference_data/FiltFreqWeight_weight_Z_.npy +0 -0
  82. acoular/tests/reference_data/FiltOctave__.npy +0 -0
  83. acoular/tests/reference_data/FiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
  84. acoular/tests/reference_data/Filter__.npy +0 -0
  85. acoular/tests/reference_data/GeneralFlowEnvironment.npy +0 -0
  86. acoular/tests/reference_data/OctaveFilterBank__.npy +0 -0
  87. acoular/tests/reference_data/OpenJet.npy +0 -0
  88. acoular/tests/reference_data/PointSource.npy +0 -0
  89. acoular/tests/reference_data/PowerSpectra_csm.npy +0 -0
  90. acoular/tests/reference_data/PowerSpectra_ev.npy +0 -0
  91. acoular/tests/reference_data/RotatingFlow.npy +0 -0
  92. acoular/tests/reference_data/SlotJet.npy +0 -0
  93. acoular/tests/reference_data/TimeAverage__.npy +0 -0
  94. acoular/tests/reference_data/TimeCumAverage__.npy +0 -0
  95. acoular/tests/reference_data/TimeExpAverage_weight_F_.npy +0 -0
  96. acoular/tests/reference_data/TimeExpAverage_weight_I_.npy +0 -0
  97. acoular/tests/reference_data/TimeExpAverage_weight_S_.npy +0 -0
  98. acoular/tests/reference_data/TimeInOut__.npy +0 -0
  99. acoular/tests/reference_data/TimePower__.npy +0 -0
  100. acoular/tests/reference_data/TimeReverse__.npy +0 -0
  101. acoular/tests/reference_data/UniformFlowEnvironment.npy +0 -0
  102. acoular/tests/reference_data/beamformer_traj_time_data.h5 +0 -0
  103. acoular/tests/run_tests.sh +0 -18
  104. acoular/tests/run_tests_osx.sh +0 -16
  105. acoular/tests/test.npy +0 -0
  106. acoular/tests/test_beamformer_results.py +0 -213
  107. acoular/tests/test_classes.py +0 -60
  108. acoular/tests/test_digest.py +0 -125
  109. acoular/tests/test_environments.py +0 -73
  110. acoular/tests/test_example1.py +0 -124
  111. acoular/tests/test_grid.py +0 -92
  112. acoular/tests/test_integrate.py +0 -102
  113. acoular/tests/test_signals.py +0 -60
  114. acoular/tests/test_sources.py +0 -65
  115. acoular/tests/test_spectra.py +0 -38
  116. acoular/tests/test_timecache.py +0 -35
  117. acoular/tests/test_tprocess.py +0 -90
  118. acoular/tests/test_traj_beamformer_results.py +0 -164
  119. acoular/tests/unsupported/SpeedComparison/OvernightTestcasesBeamformer_nMics32_nGridPoints100_nFreqs4_nTrials10.png +0 -0
  120. acoular/tests/unsupported/SpeedComparison/cythonBeamformer.pyx +0 -237
  121. acoular/tests/unsupported/SpeedComparison/mainForCython.py +0 -103
  122. acoular/tests/unsupported/SpeedComparison/mainForParallelJit.py +0 -143
  123. acoular/tests/unsupported/SpeedComparison/setupCythonOpenMP.py +0 -63
  124. acoular/tests/unsupported/SpeedComparison/sharedFunctions.py +0 -153
  125. acoular/tests/unsupported/SpeedComparison/timeOverNMics_AllImportantMethods.png +0 -0
  126. acoular/tests/unsupported/SpeedComparison/timeOverNMics_faverage.png +0 -0
  127. acoular/tests/unsupported/SpeedComparison/vglOptimierungFAverage.py +0 -204
  128. acoular/tests/unsupported/SpeedComparison/vglOptimierungGaussSeidel.py +0 -182
  129. acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAMFULL_INVERSE.py +0 -764
  130. acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAM_OS.py +0 -231
  131. acoular/tests/unsupported/SpeedComparison/whatsFastestWayFor_absASquared.py +0 -48
  132. acoular/tests/unsupported/functionalBeamformer.py +0 -123
  133. acoular/tests/unsupported/precisionTest.py +0 -153
  134. acoular/tests/unsupported/validationOfBeamformerFuncsPOSTAcoularIntegration.py +0 -254
  135. acoular/tests/unsupported/validationOfBeamformerFuncsPREeAcoularIntegration.py +0 -531
  136. acoular/tools.py +0 -422
  137. acoular-24.3.dist-info/RECORD +0 -148
  138. acoular-24.3.dist-info/licenses/LICENSE +0 -29
  139. {acoular-24.3.dist-info → acoular-24.7.dist-info}/licenses/AUTHORS.rst +0 -0
acoular/signals.py CHANGED
@@ -1,8 +1,6 @@
1
- # -*- coding: utf-8 -*-
2
- #pylint: disable-msg=E0611, E1101, C0103, R0901, R0902, R0903, R0904, W0232
3
- #------------------------------------------------------------------------------
1
+ # ------------------------------------------------------------------------------
4
2
  # Copyright (c) Acoular Development Team.
5
- #------------------------------------------------------------------------------
3
+ # ------------------------------------------------------------------------------
6
4
  """Implements signal generators for the simulation of acoustic sources.
7
5
 
8
6
  .. autosummary::
@@ -18,352 +16,356 @@
18
16
  """
19
17
 
20
18
  # imports from other packages
21
- from __future__ import print_function, division
22
- from numpy import pi, arange, sin, sqrt, repeat, tile, log, zeros, array
19
+ from warnings import warn
20
+
21
+ from numpy import arange, array, log, pi, repeat, sin, sqrt, tile, zeros
23
22
  from numpy.random import RandomState
24
- from traits.api import HasPrivateTraits, Trait, Float, Int, CLong, Bool, \
25
- Property, cached_property, Delegate, CArray
26
23
  from scipy.signal import resample, sosfilt, tf2sos
27
- from warnings import warn
24
+ from traits.api import Bool, CArray, CLong, Delegate, Float, HasPrivateTraits, Int, Property, Trait, cached_property
25
+
26
+ from .internal import digest
28
27
 
29
28
  # acoular imports
30
29
  from .tprocess import SamplesGenerator
31
- from .internal import digest
32
30
 
33
- class SignalGenerator( HasPrivateTraits ):
34
- """
35
- Virtual base class for a simple one-channel signal generator.
36
-
31
+
32
+ class SignalGenerator(HasPrivateTraits):
33
+ """Virtual base class for a simple one-channel signal generator.
34
+
37
35
  Defines the common interface for all SignalGenerator classes. This class
38
36
  may be used as a base for specialized SignalGenerator implementations. It
39
37
  should not be used directly as it contains no real functionality.
40
38
  """
41
39
 
42
40
  #: RMS amplitude of source signal (for point source: in 1 m distance).
43
- rms = Float(1.0,
44
- desc="rms amplitude")
45
-
41
+ rms = Float(1.0, desc='rms amplitude')
42
+
46
43
  #: Sampling frequency of the signal.
47
- sample_freq = Float(1.0,
48
- desc="sampling frequency")
49
-
44
+ sample_freq = Float(1.0, desc='sampling frequency')
45
+
50
46
  #: Number of samples to generate.
51
47
  numsamples = CLong
52
-
48
+
53
49
  # internal identifier
54
50
  digest = Property
55
51
 
56
- def _get_digest( self ):
52
+ def _get_digest(self):
57
53
  return ''
58
54
 
59
55
  def signal(self):
60
- """
61
- Deliver the signal.
62
- """
63
- pass
64
-
56
+ """Deliver the signal."""
57
+
65
58
  def usignal(self, factor):
66
- """
67
- Delivers the signal resampled with a multiple of the sampling freq.
68
-
59
+ """Delivers the signal resampled with a multiple of the sampling freq.
60
+
69
61
  Uses fourier transform method for resampling (from scipy.signal).
70
-
62
+
71
63
  Parameters
72
64
  ----------
73
65
  factor : integer
74
66
  The factor defines how many times the new sampling frequency is
75
67
  larger than :attr:`sample_freq`.
76
-
68
+
77
69
  Returns
78
70
  -------
79
71
  array of floats
80
72
  The resulting signal of length `factor` * :attr:`numsamples`.
73
+
81
74
  """
82
- return resample(self.signal(), factor*self.numsamples)
75
+ return resample(self.signal(), factor * self.numsamples)
83
76
 
84
- class WNoiseGenerator( SignalGenerator ):
85
- """
86
- White noise signal generator.
87
- """
77
+
78
+ class WNoiseGenerator(SignalGenerator):
79
+ """White noise signal generator."""
88
80
 
89
81
  #: Seed for random number generator, defaults to 0.
90
82
  #: This parameter should be set differently for different instances
91
83
  #: to guarantee statistically independent (non-correlated) outputs.
92
- seed = Int(0,
93
- desc="random seed value")
84
+ seed = Int(0, desc='random seed value')
94
85
 
95
86
  # internal identifier
96
- digest = Property(
97
- depends_on = ['rms', 'numsamples', \
98
- 'sample_freq', 'seed', '__class__'],
99
- )
100
-
87
+ digest = Property(
88
+ depends_on=['rms', 'numsamples', 'sample_freq', 'seed', '__class__'],
89
+ )
90
+
101
91
  @cached_property
102
- def _get_digest( self ):
92
+ def _get_digest(self):
103
93
  return digest(self)
104
94
 
105
95
  def signal(self):
106
- """
107
- Deliver the signal.
96
+ """Deliver the signal.
108
97
 
109
98
  Returns
110
99
  -------
111
100
  Array of floats
112
101
  The resulting signal as an array of length :attr:`~SignalGenerator.numsamples`.
102
+
113
103
  """
114
104
  rnd_gen = RandomState(self.seed)
115
- return self.rms*rnd_gen.standard_normal(self.numsamples)
116
-
105
+ return self.rms * rnd_gen.standard_normal(self.numsamples)
106
+
107
+
108
+ class PNoiseGenerator(SignalGenerator):
109
+ """Pink noise signal generator.
117
110
 
118
- class PNoiseGenerator( SignalGenerator ):
119
- """
120
- Pink noise signal generator.
121
-
122
111
  Simulation of pink noise is based on the Voss-McCartney algorithm.
123
112
  Ref.:
124
-
113
+
125
114
  * S.J. Orfanidis: Signal Processing (2010), pp. 729-733
126
115
  * online discussion: http://www.firstpr.com.au/dsp/pink-noise/
127
-
128
- The idea is to iteratively add larger-wavelength noise to get 1/f
116
+
117
+ The idea is to iteratively add larger-wavelength noise to get 1/f
129
118
  characteristic.
130
119
  """
131
-
120
+
132
121
  #: Seed for random number generator, defaults to 0.
133
122
  #: This parameter should be set differently for different instances
134
123
  #: to guarantee statistically independent (non-correlated) outputs.
135
- seed = Int(0,
136
- desc="random seed value")
137
-
138
- #: "Octave depth" -- higher values for 1/f spectrum at low frequencies,
124
+ seed = Int(0, desc='random seed value')
125
+
126
+ #: "Octave depth" -- higher values for 1/f spectrum at low frequencies,
139
127
  #: but longer calculation, defaults to 16.
140
- depth = Int(16,
141
- desc="octave depth")
128
+ depth = Int(16, desc='octave depth')
142
129
 
143
130
  # internal identifier
144
- digest = Property(
145
- depends_on = ['rms', 'numsamples', \
146
- 'sample_freq', 'seed', 'depth', '__class__'],
147
- )
148
-
131
+ digest = Property(
132
+ depends_on=['rms', 'numsamples', 'sample_freq', 'seed', 'depth', '__class__'],
133
+ )
134
+
149
135
  @cached_property
150
- def _get_digest( self ):
136
+ def _get_digest(self):
151
137
  return digest(self)
152
138
 
153
139
  def signal(self):
154
140
  nums = self.numsamples
155
141
  depth = self.depth
156
142
  # maximum depth depending on number of samples
157
- max_depth = int( log(nums) / log(2) )
158
-
143
+ max_depth = int(log(nums) / log(2))
144
+
159
145
  if depth > max_depth:
160
146
  depth = max_depth
161
- print("Pink noise filter depth set to maximum possible value of %d." % max_depth)
162
-
147
+ print('Pink noise filter depth set to maximum possible value of %d.' % max_depth)
148
+
163
149
  rnd_gen = RandomState(self.seed)
164
150
  s = rnd_gen.standard_normal(nums)
165
151
  for _ in range(depth):
166
- ind = 2**_-1
167
- lind = nums-ind
168
- dind = 2**(_+1)
169
- s[ind:] += repeat( rnd_gen.standard_normal(nums // dind+1 ), dind)[:lind]
152
+ ind = 2**_ - 1
153
+ lind = nums - ind
154
+ dind = 2 ** (_ + 1)
155
+ s[ind:] += repeat(rnd_gen.standard_normal(nums // dind + 1), dind)[:lind]
170
156
  # divide by sqrt(depth+1.5) to get same overall level as white noise
171
- return self.rms/sqrt(depth+1.5) * s
157
+ return self.rms / sqrt(depth + 1.5) * s
172
158
 
173
159
 
174
160
  class FiltWNoiseGenerator(WNoiseGenerator):
175
- """
176
- Filtered white noise signal following an autoregressive (AR), moving-average
161
+ """Filtered white noise signal following an autoregressive (AR), moving-average
177
162
  (MA) or autoregressive moving-average (ARMA) process.
178
-
179
- The desired frequency response of the filter can be defined by specifying
180
- the filter coefficients :attr:`ar` and :attr:`ma`.
181
- The RMS value specified via the :attr:`rms` attribute belongs to the white noise
182
- signal and differs from the RMS value of the filtered signal.
183
- For numerical stability at high orders, the filter is a combination of second order
184
- sections (sos).
163
+
164
+ The desired frequency response of the filter can be defined by specifying
165
+ the filter coefficients :attr:`ar` and :attr:`ma`.
166
+ The RMS value specified via the :attr:`rms` attribute belongs to the white noise
167
+ signal and differs from the RMS value of the filtered signal.
168
+ For numerical stability at high orders, the filter is a combination of second order
169
+ sections (sos).
185
170
  """
186
171
 
187
- ar = CArray(value=array([]),dtype=float,
188
- desc="autoregressive coefficients (coefficients of the denominator)")
189
-
190
- ma = CArray(value=array([]),dtype=float,
191
- desc="moving-average coefficients (coefficients of the numerator)")
192
-
172
+ ar = CArray(value=array([]), dtype=float, desc='autoregressive coefficients (coefficients of the denominator)')
173
+
174
+ ma = CArray(value=array([]), dtype=float, desc='moving-average coefficients (coefficients of the numerator)')
175
+
193
176
  # internal identifier
194
- digest = Property(
195
- depends_on = [
196
- 'ar', 'ma', 'rms', 'numsamples', \
197
- 'sample_freq', 'seed', '__class__'
198
- ],
199
- )
200
-
177
+ digest = Property(
178
+ depends_on=[
179
+ 'ar',
180
+ 'ma',
181
+ 'rms',
182
+ 'numsamples',
183
+ 'sample_freq',
184
+ 'seed',
185
+ '__class__',
186
+ ],
187
+ )
188
+
201
189
  @cached_property
202
- def _get_digest( self ):
190
+ def _get_digest(self):
203
191
  return digest(self)
204
192
 
205
- def handle_empty_coefficients(self,coefficients):
193
+ def handle_empty_coefficients(self, coefficients):
206
194
  if coefficients.size == 0:
207
195
  return array([1.0])
208
- else:
209
- return coefficients
210
-
196
+ return coefficients
197
+
211
198
  def signal(self):
212
- """
213
- Deliver the signal.
199
+ """Deliver the signal.
214
200
 
215
201
  Returns
216
202
  -------
217
203
  Array of floats
218
204
  The resulting signal as an array of length :attr:`~SignalGenerator.numsamples`.
205
+
219
206
  """
220
207
  rnd_gen = RandomState(self.seed)
221
208
  ma = self.handle_empty_coefficients(self.ma)
222
209
  ar = self.handle_empty_coefficients(self.ar)
223
210
  sos = tf2sos(ma, ar)
224
211
  ntaps = ma.shape[0]
225
- sdelay = round(0.5*(ntaps-1))
226
- wnoise = self.rms*rnd_gen.standard_normal(self.numsamples+sdelay) # create longer signal to compensate delay
212
+ sdelay = round(0.5 * (ntaps - 1))
213
+ wnoise = self.rms * rnd_gen.standard_normal(
214
+ self.numsamples + sdelay,
215
+ ) # create longer signal to compensate delay
227
216
  return sosfilt(sos, x=wnoise)[sdelay:]
228
217
 
229
218
 
230
- class SineGenerator( SignalGenerator ):
231
- """
232
- Sine signal generator with adjustable frequency and phase.
233
- """
219
+ class SineGenerator(SignalGenerator):
220
+ """Sine signal generator with adjustable frequency and phase."""
234
221
 
235
222
  #: Sine wave frequency, float, defaults to 1000.0.
236
- freq = Float(1000.0,
237
- desc="Frequency")
223
+ freq = Float(1000.0, desc='Frequency')
238
224
 
239
225
  #: Sine wave phase (in radians), float, defaults to 0.0.
240
- phase = Float(0.0,
241
- desc="Phase")
226
+ phase = Float(0.0, desc='Phase')
242
227
 
243
228
  # Internal shadow trait for rms/amplitude values.
244
229
  # Do not set directly.
245
230
  _amp = Float(1.0)
246
-
231
+
247
232
  #: RMS of source signal (for point source: in 1 m distance).
248
233
  #: Deprecated. For amplitude use :attr:`amplitude`.
249
234
  rms = Property(desc='rms amplitude')
250
-
235
+
251
236
  def _get_rms(self):
252
- return self._amp/2**0.5
253
-
237
+ return self._amp / 2**0.5
238
+
254
239
  def _set_rms(self, rms):
255
- warn("Up to Acoular 20.02, rms is interpreted as sine amplitude. "
256
- "This has since been corrected (rms now is 1/sqrt(2) of amplitude). "
257
- "Use 'amplitude' trait to directly set the ampltiude.",
258
- Warning, stacklevel = 2)
240
+ warn(
241
+ 'Up to Acoular 20.02, rms is interpreted as sine amplitude. '
242
+ 'This has since been corrected (rms now is 1/sqrt(2) of amplitude). '
243
+ "Use 'amplitude' trait to directly set the ampltiude.",
244
+ Warning,
245
+ stacklevel=2,
246
+ )
259
247
  self._amp = rms * 2**0.5
260
-
261
- #: Amplitude of source signal (for point source: in 1 m distance).
248
+
249
+ #: Amplitude of source signal (for point source: in 1 m distance).
262
250
  #: Defaults to 1.0.
263
251
  amplitude = Property(desc='amplitude')
264
-
252
+
265
253
  def _get_amplitude(self):
266
254
  return self._amp
267
-
255
+
268
256
  def _set_amplitude(self, amp):
269
257
  self._amp = amp
270
-
258
+
271
259
  # internal identifier
272
- digest = Property(
273
- depends_on = ['_amp', 'numsamples', \
274
- 'sample_freq', 'freq', 'phase', '__class__'],
275
- )
276
-
260
+ digest = Property(
261
+ depends_on=['_amp', 'numsamples', 'sample_freq', 'freq', 'phase', '__class__'],
262
+ )
263
+
277
264
  @cached_property
278
- def _get_digest( self ):
265
+ def _get_digest(self):
279
266
  return digest(self)
280
267
 
281
268
  def signal(self):
282
- """
283
- Deliver the signal.
269
+ """Deliver the signal.
284
270
 
285
271
  Returns
286
272
  -------
287
273
  array of floats
288
274
  The resulting signal as an array of length :attr:`~SignalGenerator.numsamples`.
275
+
289
276
  """
290
- t = arange(self.numsamples, dtype=float)/self.sample_freq
291
- return self.amplitude * sin(2*pi*self.freq * t + self.phase)
277
+ t = arange(self.numsamples, dtype=float) / self.sample_freq
278
+ return self.amplitude * sin(2 * pi * self.freq * t + self.phase)
292
279
 
293
280
 
294
- class GenericSignalGenerator( SignalGenerator ):
295
- """
296
- Generate signal from output of :class:`~acoular.tprocess.SamplesGenerator` object.
281
+ class GenericSignalGenerator(SignalGenerator):
282
+ """Generate signal from output of :class:`~acoular.tprocess.SamplesGenerator` object.
283
+
284
+ This class can be used to inject arbitrary signals into Acoular processing
285
+ chains. For example, it can be used to read signals from a HDF5 file or create any signal
286
+ by using the :class:`acoular.sources.TimeSamples` class.
287
+
288
+ Example
289
+ -------
290
+ >>> import numpy as np
291
+ >>> from acoular import TimeSamples, GenericSignalGenerator
292
+ >>> data = np.random.rand(1000, 1)
293
+ >>> ts = TimeSamples(data=data, sample_freq=51200)
294
+ >>> sig = GenericSignalGenerator(source=ts)
295
+
297
296
  """
297
+
298
298
  #: Data source; :class:`~acoular.tprocess.SamplesGenerator` or derived object.
299
299
  source = Trait(SamplesGenerator)
300
-
300
+
301
301
  #: Sampling frequency of output signal, as given by :attr:`source`.
302
302
  sample_freq = Delegate('source')
303
-
303
+
304
304
  _numsamples = CLong(0)
305
-
305
+
306
306
  #: Number of samples to generate. Is set to source.numsamples by default.
307
307
  numsamples = Property()
308
-
309
- def _get_numsamples( self ):
308
+
309
+ def _get_numsamples(self):
310
310
  if self._numsamples:
311
311
  return self._numsamples
312
- else:
313
- return self.source.numsamples
314
-
315
- def _set_numsamples( self, numsamples ):
312
+ return self.source.numsamples
313
+
314
+ def _set_numsamples(self, numsamples):
316
315
  self._numsamples = numsamples
317
316
 
318
- #: Boolean flag, if 'True' (default), signal track is repeated if requested
317
+ #: Boolean flag, if 'True' (default), signal track is repeated if requested
319
318
  #: :attr:`numsamples` is higher than available sample number
320
319
  loop_signal = Bool(True)
321
-
320
+
322
321
  # internal identifier
323
- digest = Property(
324
- depends_on = ['source.digest', 'loop_signal', 'numsamples', \
325
- 'rms', '__class__'],
326
- )
327
-
322
+ digest = Property(
323
+ depends_on=['source.digest', 'loop_signal', 'numsamples', 'rms', '__class__'],
324
+ )
325
+
328
326
  @cached_property
329
- def _get_digest( self ):
327
+ def _get_digest(self):
330
328
  return digest(self)
331
-
329
+
332
330
  def signal(self):
333
- """
334
- Deliver the signal.
331
+ """Deliver the signal.
335
332
 
336
333
  Returns
337
334
  -------
338
335
  array of floats
339
336
  The resulting signal as an array of length :attr:`~GenericSignalGenerator.numsamples`.
337
+
340
338
  """
341
339
  block = 1024
342
340
  if self.source.numchannels > 1:
343
- warn("Signal source has more than one channel. Only channel 0 will be used for signal.", Warning, stacklevel = 2)
341
+ warn(
342
+ 'Signal source has more than one channel. Only channel 0 will be used for signal.',
343
+ Warning,
344
+ stacklevel=2,
345
+ )
344
346
  nums = self.numsamples
345
347
  track = zeros(nums)
346
-
348
+
347
349
  # iterate through source generator to fill signal track
348
350
  for i, temp in enumerate(self.source.result(block)):
349
- start = block*i
350
- stop = start + len(temp[:,0])
351
+ start = block * i
352
+ stop = start + len(temp[:, 0])
351
353
  if nums > stop:
352
- track[start:stop] = temp[:,0]
353
- else: # exit loop preliminarily if wanted signal samples are reached
354
- track[start:nums] = temp[:nums-start,0]
354
+ track[start:stop] = temp[:, 0]
355
+ else: # exit loop preliminarily if wanted signal samples are reached
356
+ track[start:nums] = temp[: nums - start, 0]
355
357
  break
356
-
358
+
357
359
  # if the signal should be repeated after finishing and there are still samples open
358
360
  if self.loop_signal and (nums > stop):
359
-
360
361
  # fill up empty track with as many full source signals as possible
361
362
  nloops = nums // stop
362
- if nloops>1: track[stop:stop*nloops] = tile(track[:stop], nloops-1)
363
+ if nloops > 1:
364
+ track[stop : stop * nloops] = tile(track[:stop], nloops - 1)
363
365
  # fill up remaining empty track
364
- res = nums % stop # last part of unfinished loop
365
- if res > 0: track[stop*nloops:] = track[:res]
366
-
366
+ res = nums % stop # last part of unfinished loop
367
+ if res > 0:
368
+ track[stop * nloops :] = track[:res]
369
+
367
370
  # The rms value is just an amplification here
368
- return self.rms*track
369
-
371
+ return self.rms * track