acoular 24.7__py3-none-any.whl → 25.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
acoular/sources.py CHANGED
@@ -51,13 +51,13 @@ from numpy import (
51
51
  )
52
52
  from numpy import min as npmin
53
53
  from numpy.fft import fft, ifft
54
- from numpy.linalg import norm
54
+ from scipy.linalg import norm
55
55
  from scipy.special import sph_harm, spherical_jn, spherical_yn
56
56
  from traits.api import (
57
57
  Any,
58
58
  Bool,
59
59
  CArray,
60
- CLong,
60
+ CInt,
61
61
  Delegate,
62
62
  Dict,
63
63
  Enum,
@@ -66,32 +66,35 @@ from traits.api import (
66
66
  Instance,
67
67
  Int,
68
68
  List,
69
- ListInt,
70
69
  Property,
71
70
  Str,
72
- Trait,
73
71
  Tuple,
72
+ Union,
74
73
  cached_property,
75
74
  observe,
76
75
  on_trait_change,
77
76
  )
78
77
 
78
+ from .base import SamplesGenerator
79
+
79
80
  # acoular imports
80
81
  from .calib import Calib
82
+ from .deprecation import deprecated_alias
81
83
  from .environments import Environment
82
84
  from .h5files import H5FileBase, _get_h5file_class
83
85
  from .internal import digest, ldigest
84
86
  from .microphones import MicGeom
85
- from .signals import SignalGenerator
86
- from .tprocess import SamplesGenerator, TimeConvolve
87
+ from .signals import NoiseGenerator, SignalGenerator
88
+ from .tools.utils import get_file_basename
89
+ from .tprocess import TimeConvolve
87
90
  from .trajectory import Trajectory
88
91
 
89
92
 
90
- @nb.njit(cache=True, error_model='numpy') # jit with nopython
91
- def _fill_mic_signal_block(out, signal, rm, ind, blocksize, numchannels, up, prepadding):
93
+ @nb.njit(cache=True, error_model='numpy') # pragma: no cover
94
+ def _fill_mic_signal_block(out, signal, rm, ind, blocksize, num_channels, up, prepadding):
92
95
  if prepadding:
93
96
  for b in range(blocksize):
94
- for m in range(numchannels):
97
+ for m in range(num_channels):
95
98
  if ind[0, m] < 0:
96
99
  out[b, m] = 0
97
100
  else:
@@ -99,7 +102,7 @@ def _fill_mic_signal_block(out, signal, rm, ind, blocksize, numchannels, up, pre
99
102
  ind += up
100
103
  else:
101
104
  for b in range(blocksize):
102
- for m in range(numchannels):
105
+ for m in range(num_channels):
103
106
  out[b, m] = signal[int(0.5 + ind[0, m])] / rm[0, m]
104
107
  ind += up
105
108
  return out
@@ -180,11 +183,12 @@ def get_modes(lOrder, direction, mpos, sourceposition=None): # noqa: N803
180
183
  return modes
181
184
 
182
185
 
186
+ @deprecated_alias({'name': 'file'})
183
187
  class TimeSamples(SamplesGenerator):
184
188
  """Container for processing time data in `*.h5` or NumPy array format.
185
189
 
186
- This class loads measured data from HDF5 files and provides information about this data.
187
- It also serves as an interface where the data can be accessed (e.g. for use in a block chain) via the
190
+ This class loads measured data from HDF5 files and provides information about this data. It also
191
+ serves as an interface where the data can be accessed (e.g. for use in a block chain) via the
188
192
  :meth:`result` generator.
189
193
 
190
194
  Examples
@@ -192,9 +196,9 @@ class TimeSamples(SamplesGenerator):
192
196
  Data can be loaded from a HDF5 file as follows:
193
197
 
194
198
  >>> from acoular import TimeSamples
195
- >>> name = <some_h5_file.h5> # doctest: +SKIP
196
- >>> ts = TimeSamples(name=name) # doctest: +SKIP
197
- >>> print(f'number of channels: {ts.numchannels}') # doctest: +SKIP
199
+ >>> file = <some_h5_file.h5> # doctest: +SKIP
200
+ >>> ts = TimeSamples(file=file) # doctest: +SKIP
201
+ >>> print(f'number of channels: {ts.num_channels}') # doctest: +SKIP
198
202
  number of channels: 56 # doctest: +SKIP
199
203
 
200
204
  Alternatively, the time data can be specified directly as a numpy array.
@@ -204,8 +208,9 @@ class TimeSamples(SamplesGenerator):
204
208
  >>> data = np.random.rand(1000, 4)
205
209
  >>> ts = TimeSamples(data=data, sample_freq=51200)
206
210
 
207
- Chunks of the time data can be accessed iteratively via the :meth:`result` generator.
208
- The last block will be shorter than the block size if the number of samples is not a multiple of the block size.
211
+ Chunks of the time data can be accessed iteratively via the :meth:`result` generator. The last
212
+ block will be shorter than the block size if the number of samples is not a multiple of the
213
+ block size.
209
214
 
210
215
  >>> blocksize = 512
211
216
  >>> generator = ts.result(num=blocksize)
@@ -216,30 +221,27 @@ class TimeSamples(SamplesGenerator):
216
221
 
217
222
  See Also
218
223
  --------
219
- acoular.sources.MaskedTimeSamples :
220
- Extends the functionality of class :class:`TimeSamples` by enabling the definition of start and stop samples
221
- as well as the specification of invalid channels.
224
+ acoular.sources.MaskedTimeSamples:
225
+ Extends the functionality of class :class:`TimeSamples` by enabling the definition of start
226
+ and stop samples as well as the specification of invalid channels.
222
227
  """
223
228
 
224
229
  #: Full name of the .h5 file with data.
225
- name = File(filter=['*.h5'], desc='name of data file')
230
+ file = File(filter=['*.h5'], exists=True, desc='name of data file')
226
231
 
227
232
  #: Basename of the .h5 file with data, is set automatically.
228
- basename = Property(
229
- depends_on='name', # filter=['*.h5'],
230
- desc='basename of data file',
231
- )
233
+ basename = Property(depends_on=['file'], desc='basename of data file')
232
234
 
233
235
  #: Calibration data, instance of :class:`~acoular.calib.Calib` class, optional .
234
- calib = Trait(Calib, desc='Calibration data')
236
+ calib = Instance(Calib, desc='Calibration data')
235
237
 
236
238
  #: Number of channels, is set automatically / read from file.
237
- numchannels = CLong(0, desc='number of input channels')
239
+ num_channels = CInt(0, desc='number of input channels')
238
240
 
239
241
  #: Number of time data samples, is set automatically / read from file.
240
- numsamples = CLong(0, desc='number of samples')
242
+ num_samples = CInt(0, desc='number of samples')
241
243
 
242
- #: The time data as array of floats with dimension (numsamples, numchannels).
244
+ #: The time data as array of floats with dimension (num_samples, num_channels).
243
245
  data = Any(transient=True, desc='the actual time data array')
244
246
 
245
247
  #: HDF5 file object
@@ -252,7 +254,9 @@ class TimeSamples(SamplesGenerator):
252
254
  _datachecksum = Property()
253
255
 
254
256
  # internal identifier
255
- digest = Property(depends_on=['basename', 'calib.digest', '_datachecksum'])
257
+ digest = Property(
258
+ depends_on=['basename', 'calib.digest', '_datachecksum', 'sample_freq', 'num_channels', 'num_samples']
259
+ )
256
260
 
257
261
  def _get__datachecksum(self):
258
262
  return self.data[0, :].sum()
@@ -263,27 +267,24 @@ class TimeSamples(SamplesGenerator):
263
267
 
264
268
  @cached_property
265
269
  def _get_basename(self):
266
- return path.splitext(path.basename(self.name))[0]
270
+ return get_file_basename(self.file)
267
271
 
268
272
  @on_trait_change('basename')
269
273
  def _load_data(self):
270
274
  """Open the .h5 file and set attributes."""
271
- if not path.isfile(self.name):
272
- self.sample_freq = 0
273
- raise OSError('No such file: %s' % self.name)
274
275
  if self.h5f is not None:
275
276
  with contextlib.suppress(OSError):
276
277
  self.h5f.close()
277
278
  file = _get_h5file_class()
278
- self.h5f = file(self.name)
279
+ self.h5f = file(self.file)
279
280
  self._load_timedata()
280
281
  self._load_metadata()
281
282
 
282
283
  @on_trait_change('data')
283
284
  def _load_shapes(self):
284
- """Set numchannels and numsamples from data."""
285
+ """Set num_channels and num_samples from data."""
285
286
  if self.data is not None:
286
- self.numsamples, self.numchannels = self.data.shape
287
+ self.num_samples, self.num_channels = self.data.shape
287
288
 
288
289
  def _load_timedata(self):
289
290
  """Loads timedata from .h5 file. Only for internal use."""
@@ -312,46 +313,61 @@ class TimeSamples(SamplesGenerator):
312
313
  Yields
313
314
  ------
314
315
  numpy.ndarray
315
- Samples in blocks of shape (num, numchannels).
316
+ Samples in blocks of shape (num, num_channels).
316
317
  The last block may be shorter than num.
317
318
 
318
319
  """
319
- if self.numsamples == 0:
320
+ if self.num_samples == 0:
320
321
  msg = 'no samples available'
321
322
  raise OSError(msg)
322
323
  self._datachecksum # trigger checksum calculation # noqa: B018
323
324
  i = 0
324
325
  if self.calib:
325
- if self.calib.num_mics == self.numchannels:
326
+ warn(
327
+ 'The use of the calibration functionality in TimeSamples is deprecated and will be removed in \
328
+ Acoular 25.10. Use the Calib class as an additional processing block instead.',
329
+ DeprecationWarning,
330
+ stacklevel=2,
331
+ )
332
+ if self.calib.num_mics == self.num_channels:
326
333
  cal_factor = self.calib.data[newaxis]
327
334
  else:
328
- raise ValueError('calibration data not compatible: %i, %i' % (self.calib.num_mics, self.numchannels))
329
- while i < self.numsamples:
335
+ msg = f'calibration data not compatible: {self.calib.num_mics:d}, {self.num_channels:d}'
336
+ raise ValueError(msg)
337
+ while i < self.num_samples:
330
338
  yield self.data[i : i + num] * cal_factor
331
339
  i += num
332
340
  else:
333
- while i < self.numsamples:
341
+ while i < self.num_samples:
334
342
  yield self.data[i : i + num]
335
343
  i += num
336
344
 
337
345
 
346
+ @deprecated_alias(
347
+ {
348
+ 'numchannels_total': 'num_channels_total',
349
+ 'numsamples_total': 'num_samples_total',
350
+ 'numchannels': 'num_channels',
351
+ 'numsamples': 'num_samples',
352
+ },
353
+ read_only=['numchannels', 'numsamples'],
354
+ )
338
355
  class MaskedTimeSamples(TimeSamples):
339
356
  """Container for processing time data in `*.h5` or NumPy array format.
340
357
 
341
- This class loads measured data from HDF5 files and provides information about this data.
342
- It supports storing information about (in)valid samples and (in)valid channels and allows
343
- to specify a start and stop index for the valid samples.
344
- It also serves as an interface where the data can be accessed (e.g. for use in a block chain) via the
345
- :meth:`result` generator.
358
+ This class loads measured data from HDF5 files and provides information about this data. It
359
+ supports storing information about (in)valid samples and (in)valid channels and allows to
360
+ specify a start and stop index for the valid samples. It also serves as an interface where the
361
+ data can be accessed (e.g. for use in a block chain) via the :meth:`result` generator.
346
362
 
347
363
  Examples
348
364
  --------
349
365
  Data can be loaded from a HDF5 file and invalid channels can be specified as follows:
350
366
 
351
367
  >>> from acoular import MaskedTimeSamples
352
- >>> name = <some_h5_file.h5> # doctest: +SKIP
353
- >>> ts = MaskedTimeSamples(name=name, invalid_channels=[0, 1]) # doctest: +SKIP
354
- >>> print(f'number of valid channels: {ts.numchannels}') # doctest: +SKIP
368
+ >>> file = <some_h5_file.h5> # doctest: +SKIP
369
+ >>> ts = MaskedTimeSamples(file=file, invalid_channels=[0, 1]) # doctest: +SKIP
370
+ >>> print(f'number of valid channels: {ts.num_channels}') # doctest: +SKIP
355
371
  number of valid channels: 54 # doctest: +SKIP
356
372
 
357
373
  Alternatively, the time data can be specified directly as a numpy array.
@@ -364,8 +380,8 @@ class MaskedTimeSamples(TimeSamples):
364
380
 
365
381
  Chunks of the time data can be accessed iteratively via the :meth:`result` generator:
366
382
 
367
- >>> blocksize = 512
368
- >>> generator = ts.result(num=blocksize)
383
+ >>> block_size = 512
384
+ >>> generator = ts.result(num=block_size)
369
385
  >>> for block in generator:
370
386
  ... print(block.shape)
371
387
  (512, 4)
@@ -373,28 +389,32 @@ class MaskedTimeSamples(TimeSamples):
373
389
  """
374
390
 
375
391
  #: Index of the first sample to be considered valid.
376
- start = CLong(0, desc='start of valid samples')
392
+ start = CInt(0, desc='start of valid samples')
377
393
 
378
394
  #: Index of the last sample to be considered valid.
379
- stop = Trait(None, None, CLong, desc='stop of valid samples')
395
+ stop = Union(None, CInt, desc='stop of valid samples')
380
396
 
381
397
  #: Channels that are to be treated as invalid.
382
- invalid_channels = ListInt(desc='list of invalid channels')
398
+ invalid_channels = List(int, desc='list of invalid channels')
383
399
 
384
400
  #: Channel mask to serve as an index for all valid channels, is set automatically.
385
- channels = Property(depends_on=['invalid_channels', 'numchannels_total'], desc='channel mask')
401
+ channels = Property(depends_on=['invalid_channels', 'num_channels_total'], desc='channel mask')
386
402
 
387
403
  #: Number of channels (including invalid channels), is set automatically.
388
- numchannels_total = CLong(0, desc='total number of input channels')
404
+ num_channels_total = CInt(0, desc='total number of input channels')
389
405
 
390
406
  #: Number of time data samples (including invalid samples), is set automatically.
391
- numsamples_total = CLong(0, desc='total number of samples per channel')
407
+ num_samples_total = CInt(0, desc='total number of samples per channel')
392
408
 
393
409
  #: Number of valid channels, is set automatically.
394
- numchannels = Property(depends_on=['invalid_channels', 'numchannels_total'], desc='number of valid input channels')
410
+ num_channels = Property(
411
+ depends_on=['invalid_channels', 'num_channels_total'], desc='number of valid input channels'
412
+ )
395
413
 
396
414
  #: Number of valid time data samples, is set automatically.
397
- numsamples = Property(depends_on=['start', 'stop', 'numsamples_total'], desc='number of valid samples per channel')
415
+ num_samples = Property(
416
+ depends_on=['start', 'stop', 'num_samples_total'], desc='number of valid samples per channel'
417
+ )
398
418
 
399
419
  # internal identifier
400
420
  digest = Property(depends_on=['basename', 'start', 'stop', 'calib.digest', 'invalid_channels', '_datachecksum'])
@@ -403,55 +423,52 @@ class MaskedTimeSamples(TimeSamples):
403
423
  def _get_digest(self):
404
424
  return digest(self)
405
425
 
406
- @cached_property
407
- def _get_basename(self):
408
- return path.splitext(path.basename(self.name))[0]
409
-
410
426
  @cached_property
411
427
  def _get_channels(self):
412
428
  if len(self.invalid_channels) == 0:
413
429
  return slice(0, None, None)
414
- allr = [i for i in range(self.numchannels_total) if i not in self.invalid_channels]
430
+ allr = [i for i in range(self.num_channels_total) if i not in self.invalid_channels]
415
431
  return array(allr)
416
432
 
417
433
  @cached_property
418
- def _get_numchannels(self):
434
+ def _get_num_channels(self):
419
435
  if len(self.invalid_channels) == 0:
420
- return self.numchannels_total
436
+ return self.num_channels_total
421
437
  return len(self.channels)
422
438
 
423
439
  @cached_property
424
- def _get_numsamples(self):
425
- sli = slice(self.start, self.stop).indices(self.numsamples_total)
440
+ def _get_num_samples(self):
441
+ sli = slice(self.start, self.stop).indices(self.num_samples_total)
426
442
  return sli[1] - sli[0]
427
443
 
428
444
  @on_trait_change('basename')
429
445
  def _load_data(self):
430
446
  # """ open the .h5 file and set attributes
431
447
  # """
432
- if not path.isfile(self.name):
448
+ if not path.isfile(self.file):
433
449
  # no file there
434
450
  self.sample_freq = 0
435
- raise OSError('No such file: %s' % self.name)
451
+ msg = f'No such file: {self.file}'
452
+ raise OSError(msg)
436
453
  if self.h5f is not None:
437
454
  with contextlib.suppress(OSError):
438
455
  self.h5f.close()
439
456
  file = _get_h5file_class()
440
- self.h5f = file(self.name)
457
+ self.h5f = file(self.file)
441
458
  self._load_timedata()
442
459
  self._load_metadata()
443
460
 
444
461
  @on_trait_change('data')
445
462
  def _load_shapes(self):
446
- """Set numchannels and numsamples from data."""
463
+ """Set num_channels and num_samples from data."""
447
464
  if self.data is not None:
448
- self.numsamples_total, self.numchannels_total = self.data.shape
465
+ self.num_samples_total, self.num_channels_total = self.data.shape
449
466
 
450
467
  def _load_timedata(self):
451
468
  """Loads timedata from .h5 file. Only for internal use."""
452
469
  self.data = self.h5f.get_data_by_reference('time_data')
453
470
  self.sample_freq = self.h5f.get_node_attribute(self.data, 'sample_freq')
454
- (self.numsamples_total, self.numchannels_total) = self.data.shape
471
+ (self.num_samples_total, self.num_channels_total) = self.data.shape
455
472
 
456
473
  def result(self, num=128):
457
474
  """Python generator that yields the output block-wise.
@@ -469,11 +486,11 @@ class MaskedTimeSamples(TimeSamples):
469
486
  Yields
470
487
  ------
471
488
  numpy.ndarray
472
- Samples in blocks of shape (num, numchannels).
489
+ Samples in blocks of shape (num, num_channels).
473
490
  The last block may be shorter than num.
474
491
 
475
492
  """
476
- sli = slice(self.start, self.stop).indices(self.numsamples_total)
493
+ sli = slice(self.start, self.stop).indices(self.num_samples_total)
477
494
  i = sli[0]
478
495
  stop = sli[1]
479
496
  cal_factor = 1.0
@@ -482,19 +499,27 @@ class MaskedTimeSamples(TimeSamples):
482
499
  raise OSError(msg)
483
500
  self._datachecksum # trigger checksum calculation # noqa: B018
484
501
  if self.calib:
485
- if self.calib.num_mics == self.numchannels_total:
502
+ warn(
503
+ 'The use of the calibration functionality in MaskedTimeSamples is deprecated and will be removed in \
504
+ Acoular 25.10. Use the Calib class as an additional processing block instead.',
505
+ DeprecationWarning,
506
+ stacklevel=2,
507
+ )
508
+ if self.calib.num_mics == self.num_channels_total:
486
509
  cal_factor = self.calib.data[self.channels][newaxis]
487
- elif self.calib.num_mics == self.numchannels:
510
+ elif self.calib.num_mics == self.num_channels:
488
511
  cal_factor = self.calib.data[newaxis]
489
512
  elif self.calib.num_mics == 0:
490
513
  warn('No calibration data used.', Warning, stacklevel=2)
491
514
  else:
492
- raise ValueError('calibration data not compatible: %i, %i' % (self.calib.num_mics, self.numchannels))
515
+ msg = f'calibration data not compatible: {self.calib.num_mics:d}, {self.num_channels:d}'
516
+ raise ValueError(msg)
493
517
  while i < stop:
494
518
  yield self.data[i : min(i + num, stop)][:, self.channels] * cal_factor
495
519
  i += num
496
520
 
497
521
 
522
+ @deprecated_alias({'numchannels': 'num_channels', 'numsamples': 'num_samples'}, read_only=True)
498
523
  class PointSource(SamplesGenerator):
499
524
  """Class to define a fixed point source with an arbitrary signal.
500
525
  This can be used in simulations.
@@ -503,58 +528,31 @@ class PointSource(SamplesGenerator):
503
528
  """
504
529
 
505
530
  #: Emitted signal, instance of the :class:`~acoular.signals.SignalGenerator` class.
506
- signal = Trait(SignalGenerator)
531
+ signal = Instance(SignalGenerator)
507
532
 
508
533
  #: Location of source in (`x`, `y`, `z`) coordinates (left-oriented system).
509
534
  loc = Tuple((0.0, 0.0, 1.0), desc='source location')
510
535
 
511
536
  #: Number of channels in output, is set automatically /
512
537
  #: depends on used microphone geometry.
513
- numchannels = Delegate('mics', 'num_mics')
538
+ num_channels = Delegate('mics', 'num_mics')
514
539
 
515
540
  #: :class:`~acoular.microphones.MicGeom` object that provides the microphone locations.
516
- mics = Trait(MicGeom, desc='microphone geometry')
541
+ mics = Instance(MicGeom, desc='microphone geometry')
517
542
 
518
543
  def _validate_locations(self):
519
- dist = self.env._r(array(self.loc).reshape((3, 1)), self.mics.mpos)
544
+ dist = self.env._r(array(self.loc).reshape((3, 1)), self.mics.pos)
520
545
  if npany(dist < 1e-7):
521
546
  warn('Source and microphone locations are identical.', Warning, stacklevel=2)
522
547
 
523
548
  #: :class:`~acoular.environments.Environment` or derived object,
524
549
  #: which provides information about the sound propagation in the medium.
525
- env = Trait(Environment(), Environment)
526
-
527
- # --- List of backwards compatibility traits and their setters/getters -----------
528
-
529
- # Microphone locations.
530
- # Deprecated! Use :attr:`mics` trait instead.
531
- mpos = Property()
532
-
533
- def _get_mpos(self):
534
- return self.mics
535
-
536
- def _set_mpos(self, mpos):
537
- warn("Deprecated use of 'mpos' trait. ", Warning, stacklevel=2)
538
- self.mics = mpos
539
-
540
- # The speed of sound.
541
- # Deprecated! Only kept for backwards compatibility.
542
- # Now governed by :attr:`env` trait.
543
- c = Property()
544
-
545
- def _get_c(self):
546
- return self.env.c
547
-
548
- def _set_c(self, c):
549
- warn("Deprecated use of 'c' trait. ", Warning, stacklevel=2)
550
- self.env.c = c
551
-
552
- # --- End of backwards compatibility traits --------------------------------------
550
+ env = Instance(Environment(), Environment)
553
551
 
554
552
  #: Start time of the signal in seconds, defaults to 0 s.
555
553
  start_t = Float(0.0, desc='signal start time')
556
554
 
557
- #: Start time of the data aquisition at microphones in seconds,
555
+ #: Start time of the data acquisition at microphones in seconds,
558
556
  #: defaults to 0 s.
559
557
  start = Float(0.0, desc='sample start time')
560
558
 
@@ -562,14 +560,14 @@ class PointSource(SamplesGenerator):
562
560
  #: `loop` take values from the end of :attr:`signal.signal()` array.
563
561
  #: `zeros` set source signal to zero, advisable for deterministic signals.
564
562
  #: defaults to `loop`.
565
- prepadding = Trait('loop', 'zeros', desc='Behaviour for negative time indices.')
563
+ prepadding = Enum('loop', 'zeros', desc='Behaviour for negative time indices.')
566
564
 
567
565
  #: Upsampling factor, internal use, defaults to 16.
568
566
  up = Int(16, desc='upsampling factor')
569
567
 
570
568
  #: Number of samples, is set automatically /
571
569
  #: depends on :attr:`signal`.
572
- numsamples = Delegate('signal')
570
+ num_samples = Delegate('signal')
573
571
 
574
572
  #: Sampling frequency of the signal, is set automatically /
575
573
  #: depends on :attr:`signal`.
@@ -586,7 +584,6 @@ class PointSource(SamplesGenerator):
586
584
  'start',
587
585
  'up',
588
586
  'prepadding',
589
- '__class__',
590
587
  ],
591
588
  )
592
589
 
@@ -605,16 +602,16 @@ class PointSource(SamplesGenerator):
605
602
 
606
603
  Returns
607
604
  -------
608
- Samples in blocks of shape (num, numchannels).
605
+ Samples in blocks of shape (num, num_channels).
609
606
  The last block may be shorter than num.
610
607
 
611
608
  """
612
609
  self._validate_locations()
613
- N = int(ceil(self.numsamples / num)) # number of output blocks
610
+ N = int(ceil(self.num_samples / num)) # number of output blocks
614
611
  signal = self.signal.usignal(self.up)
615
- out = empty((num, self.numchannels))
612
+ out = empty((num, self.num_channels))
616
613
  # distances
617
- rm = self.env._r(array(self.loc).reshape((3, 1)), self.mics.mpos).reshape(1, -1)
614
+ rm = self.env._r(array(self.loc).reshape((3, 1)), self.mics.pos).reshape(1, -1)
618
615
  # emission time relative to start_t (in samples) for first sample
619
616
  ind = (-rm / self.env.c - self.start_t + self.start) * self.sample_freq * self.up
620
617
 
@@ -625,16 +622,16 @@ class PointSource(SamplesGenerator):
625
622
  # if signal stops during prepadding, terminate
626
623
  if pre >= N:
627
624
  for _nb in range(N - 1):
628
- out = _fill_mic_signal_block(out, signal, rm, ind, num, self.numchannels, self.up, True)
625
+ out = _fill_mic_signal_block(out, signal, rm, ind, num, self.num_channels, self.up, True)
629
626
  yield out
630
627
 
631
- blocksize = self.numsamples % num or num
632
- out = _fill_mic_signal_block(out, signal, rm, ind, blocksize, self.numchannels, self.up, True)
628
+ blocksize = self.num_samples % num or num
629
+ out = _fill_mic_signal_block(out, signal, rm, ind, blocksize, self.num_channels, self.up, True)
633
630
  yield out[:blocksize]
634
631
  return
635
632
  else:
636
633
  for _nb in range(pre):
637
- out = _fill_mic_signal_block(out, signal, rm, ind, num, self.numchannels, self.up, True)
634
+ out = _fill_mic_signal_block(out, signal, rm, ind, num, self.num_channels, self.up, True)
638
635
  yield out
639
636
 
640
637
  else:
@@ -642,12 +639,12 @@ class PointSource(SamplesGenerator):
642
639
 
643
640
  # main generator
644
641
  for _nb in range(N - pre - 1):
645
- out = _fill_mic_signal_block(out, signal, rm, ind, num, self.numchannels, self.up, False)
642
+ out = _fill_mic_signal_block(out, signal, rm, ind, num, self.num_channels, self.up, False)
646
643
  yield out
647
644
 
648
645
  # last block of variable size
649
- blocksize = self.numsamples % num or num
650
- out = _fill_mic_signal_block(out, signal, rm, ind, blocksize, self.numchannels, self.up, False)
646
+ blocksize = self.num_samples % num or num
647
+ out = _fill_mic_signal_block(out, signal, rm, ind, blocksize, self.num_channels, self.up, False)
651
648
  yield out[:blocksize]
652
649
 
653
650
 
@@ -678,7 +675,6 @@ class SphericalHarmonicSource(PointSource):
678
675
  'start_t',
679
676
  'start',
680
677
  'up',
681
- '__class__',
682
678
  'alpha',
683
679
  'lOrder',
684
680
  'prepadding',
@@ -693,7 +689,7 @@ class SphericalHarmonicSource(PointSource):
693
689
  Y_lm = get_modes(
694
690
  lOrder=self.lOrder,
695
691
  direction=self.direction,
696
- mpos=self.mics.mpos,
692
+ mpos=self.mics.pos,
697
693
  sourceposition=array(self.loc),
698
694
  )
699
695
  return real(ifft(fft(signals, axis=0) * (Y_lm @ self.alpha), axis=0))
@@ -709,7 +705,7 @@ class SphericalHarmonicSource(PointSource):
709
705
 
710
706
  Returns
711
707
  -------
712
- Samples in blocks of shape (num, numchannels).
708
+ Samples in blocks of shape (num, num_channels).
713
709
  The last block may be shorter than num.
714
710
 
715
711
  """
@@ -718,11 +714,11 @@ class SphericalHarmonicSource(PointSource):
718
714
 
719
715
  signal = self.signal.usignal(self.up)
720
716
  # emission time relative to start_t (in samples) for first sample
721
- rm = self.env._r(array(self.loc).reshape((3, 1)), self.mics.mpos)
717
+ rm = self.env._r(array(self.loc).reshape((3, 1)), self.mics.pos)
722
718
  ind = (-rm / self.env.c - self.start_t + self.start) * self.sample_freq + pi / 30
723
719
  i = 0
724
- n = self.numsamples
725
- out = empty((num, self.numchannels))
720
+ n = self.num_samples
721
+ out = empty((num, self.num_channels))
726
722
  while n:
727
723
  n -= 1
728
724
  try:
@@ -752,7 +748,7 @@ class MovingPointSource(PointSource):
752
748
  #: Trajectory of the source,
753
749
  #: instance of the :class:`~acoular.trajectory.Trajectory` class.
754
750
  #: The start time is assumed to be the same as for the samples.
755
- trajectory = Trait(Trajectory, desc='trajectory of the source')
751
+ trajectory = Instance(Trajectory, desc='trajectory of the source')
756
752
 
757
753
  prepadding = Enum('loop', desc='Behaviour for negative time indices.')
758
754
 
@@ -768,7 +764,6 @@ class MovingPointSource(PointSource):
768
764
  'start',
769
765
  'trajectory.digest',
770
766
  'prepadding',
771
- '__class__',
772
767
  ],
773
768
  )
774
769
 
@@ -787,7 +782,7 @@ class MovingPointSource(PointSource):
787
782
 
788
783
  Returns
789
784
  -------
790
- Samples in blocks of shape (num, numchannels).
785
+ Samples in blocks of shape (num, num_channels).
791
786
  The last block may be shorter than num.
792
787
 
793
788
  """
@@ -795,15 +790,15 @@ class MovingPointSource(PointSource):
795
790
  # from the end of the calculated signal.
796
791
 
797
792
  signal = self.signal.usignal(self.up)
798
- out = empty((num, self.numchannels))
799
- # shortcuts and intial values
793
+ out = empty((num, self.num_channels))
794
+ # shortcuts and initial values
800
795
  m = self.mics
801
796
  t = self.start * ones(m.num_mics)
802
797
  i = 0
803
798
  epslim = 0.1 / self.up / self.sample_freq
804
799
  c0 = self.env.c
805
800
  tr = self.trajectory
806
- n = self.numsamples
801
+ n = self.num_samples
807
802
  while n:
808
803
  n -= 1
809
804
  eps = ones(m.num_mics)
@@ -812,7 +807,7 @@ class MovingPointSource(PointSource):
812
807
  # Newton-Rhapson iteration
813
808
  while abs(eps).max() > epslim and j < 100:
814
809
  loc = array(tr.location(te))
815
- rm = loc - m.mpos # distance vectors to microphones
810
+ rm = loc - m.pos # distance vectors to microphones
816
811
  rm = sqrt((rm * rm).sum(0)) # absolute distance
817
812
  loc /= sqrt((loc * loc).sum(0)) # distance unit vector
818
813
  der = array(tr.location(te, der=1))
@@ -867,7 +862,6 @@ class PointSourceDipole(PointSource):
867
862
  'up',
868
863
  'direction',
869
864
  'prepadding',
870
- '__class__',
871
865
  ],
872
866
  )
873
867
 
@@ -886,14 +880,14 @@ class PointSourceDipole(PointSource):
886
880
 
887
881
  Returns
888
882
  -------
889
- Samples in blocks of shape (num, numchannels).
883
+ Samples in blocks of shape (num, num_channels).
890
884
  The last block may be shorter than num.
891
885
 
892
886
  """
893
887
  # If signal samples are needed for te < t_start, then samples are taken
894
888
  # from the end of the calculated signal.
895
889
 
896
- mpos = self.mics.mpos
890
+ mpos = self.mics.pos
897
891
  # position of the dipole as (3,1) vector
898
892
  loc = array(self.loc, dtype=float).reshape((3, 1))
899
893
  # direction vector from tuple
@@ -912,7 +906,7 @@ class PointSourceDipole(PointSource):
912
906
  dir2 = (direc_n * dist / 2.0).reshape((3, 1))
913
907
 
914
908
  signal = self.signal.usignal(self.up)
915
- out = empty((num, self.numchannels))
909
+ out = empty((num, self.num_channels))
916
910
 
917
911
  # distance from dipole center to microphones
918
912
  rm = self.env._r(loc, mpos)
@@ -926,7 +920,7 @@ class PointSourceDipole(PointSource):
926
920
  ind2 = (-rm2 / c - self.start_t + self.start) * self.sample_freq
927
921
 
928
922
  i = 0
929
- n = self.numsamples
923
+ n = self.num_samples
930
924
  while n:
931
925
  n -= 1
932
926
  try:
@@ -964,7 +958,6 @@ class MovingPointSourceDipole(PointSourceDipole, MovingPointSource):
964
958
  'start',
965
959
  'up',
966
960
  'direction',
967
- '__class__',
968
961
  ],
969
962
  )
970
963
 
@@ -986,7 +979,7 @@ class MovingPointSourceDipole(PointSourceDipole, MovingPointSource):
986
979
  xs = array(self.trajectory.location(te))
987
980
  loc = xs.copy()
988
981
  loc += direction
989
- rm = loc - self.mics.mpos # distance vectors to microphones
982
+ rm = loc - self.mics.pos # distance vectors to microphones
990
983
  rm = sqrt((rm * rm).sum(0)) # absolute distance
991
984
  loc /= sqrt((loc * loc).sum(0)) # distance unit vector
992
985
  der = array(self.trajectory.location(te, der=1))
@@ -1021,13 +1014,13 @@ class MovingPointSourceDipole(PointSourceDipole, MovingPointSource):
1021
1014
 
1022
1015
  Returns
1023
1016
  -------
1024
- Samples in blocks of shape (num, numchannels).
1017
+ Samples in blocks of shape (num, num_channels).
1025
1018
  The last block may be shorter than num.
1026
1019
 
1027
1020
  """
1028
1021
  # If signal samples are needed for te < t_start, then samples are taken
1029
1022
  # from the end of the calculated signal.
1030
- mpos = self.mics.mpos
1023
+ mpos = self.mics.pos
1031
1024
 
1032
1025
  # direction vector from tuple
1033
1026
  direc = array(self.direction, dtype=float) * 1e-5
@@ -1042,13 +1035,13 @@ class MovingPointSourceDipole(PointSourceDipole, MovingPointSource):
1042
1035
  dir2 = (direc_n * dist / 2.0).reshape((3, 1))
1043
1036
 
1044
1037
  signal = self.signal.usignal(self.up)
1045
- out = empty((num, self.numchannels))
1046
- # shortcuts and intial values
1038
+ out = empty((num, self.num_channels))
1039
+ # shortcuts and initial values
1047
1040
  m = self.mics
1048
1041
  t = self.start * ones(m.num_mics)
1049
1042
 
1050
1043
  i = 0
1051
- n = self.numsamples
1044
+ n = self.num_samples
1052
1045
  while n:
1053
1046
  n -= 1
1054
1047
  te, rm, Mr, locs = self.get_emission_time(t, 0)
@@ -1106,7 +1099,7 @@ class LineSource(PointSource):
1106
1099
  source_strength = CArray(desc='coefficients of the source strength')
1107
1100
 
1108
1101
  #:coherence
1109
- coherence = Trait('coherent', 'incoherent', desc='coherence mode')
1102
+ coherence = Enum('coherent', 'incoherent', desc='coherence mode')
1110
1103
 
1111
1104
  # internal identifier
1112
1105
  digest = Property(
@@ -1121,7 +1114,6 @@ class LineSource(PointSource):
1121
1114
  'direction',
1122
1115
  'source_strength',
1123
1116
  'coherence',
1124
- '__class__',
1125
1117
  ],
1126
1118
  )
1127
1119
 
@@ -1140,14 +1132,14 @@ class LineSource(PointSource):
1140
1132
 
1141
1133
  Returns
1142
1134
  -------
1143
- Samples in blocks of shape (num, numchannels).
1135
+ Samples in blocks of shape (num, num_channels).
1144
1136
  The last block may be shorter than num.
1145
1137
 
1146
1138
  """
1147
1139
  # If signal samples are needed for te < t_start, then samples are taken
1148
1140
  # from the end of the calculated signal.
1149
1141
 
1150
- mpos = self.mics.mpos
1142
+ mpos = self.mics.pos
1151
1143
 
1152
1144
  # direction vector from tuple
1153
1145
  direc = array(self.direction, dtype=float)
@@ -1159,14 +1151,14 @@ class LineSource(PointSource):
1159
1151
  dist = self.length / self.num_sources
1160
1152
 
1161
1153
  # blocwise output
1162
- out = zeros((num, self.numchannels))
1154
+ out = zeros((num, self.num_channels))
1163
1155
 
1164
1156
  # distance from line start position to microphones
1165
1157
  loc = array(self.loc, dtype=float).reshape((3, 1))
1166
1158
 
1167
1159
  # distances from monopoles in the line to microphones
1168
- rms = empty((self.numchannels, self.num_sources))
1169
- inds = empty((self.numchannels, self.num_sources))
1160
+ rms = empty((self.num_channels, self.num_sources))
1161
+ inds = empty((self.num_channels, self.num_sources))
1170
1162
  signals = empty((self.num_sources, len(self.signal.usignal(self.up))))
1171
1163
  # for every source - distances
1172
1164
  for s in range(self.num_sources):
@@ -1178,7 +1170,7 @@ class LineSource(PointSource):
1178
1170
  self.signal.rms = self.signal.rms * self.source_strength[s]
1179
1171
  signals[s] = self.signal.usignal(self.up)
1180
1172
  i = 0
1181
- n = self.numsamples
1173
+ n = self.num_samples
1182
1174
  while n:
1183
1175
  n -= 1
1184
1176
  try:
@@ -1190,7 +1182,7 @@ class LineSource(PointSource):
1190
1182
  i += 1
1191
1183
  if i == num:
1192
1184
  yield out
1193
- out = zeros((num, self.numchannels))
1185
+ out = zeros((num, self.num_channels))
1194
1186
  i = 0
1195
1187
  except IndexError:
1196
1188
  break
@@ -1210,7 +1202,6 @@ class MovingLineSource(LineSource, MovingPointSource):
1210
1202
  'start',
1211
1203
  'up',
1212
1204
  'direction',
1213
- '__class__',
1214
1205
  ],
1215
1206
  )
1216
1207
 
@@ -1246,7 +1237,7 @@ class MovingLineSource(LineSource, MovingPointSource):
1246
1237
  xs = array(self.trajectory.location(te))
1247
1238
  loc = xs.copy()
1248
1239
  loc += direction
1249
- rm = loc - self.mics.mpos # distance vectors to microphones
1240
+ rm = loc - self.mics.pos # distance vectors to microphones
1250
1241
  rm = sqrt((rm * rm).sum(0)) # absolute distance
1251
1242
  loc /= sqrt((loc * loc).sum(0)) # distance unit vector
1252
1243
  der = array(self.trajectory.location(te, der=1))
@@ -1267,13 +1258,13 @@ class MovingLineSource(LineSource, MovingPointSource):
1267
1258
 
1268
1259
  Returns
1269
1260
  -------
1270
- Samples in blocks of shape (num, numchannels).
1261
+ Samples in blocks of shape (num, num_channels).
1271
1262
  The last block may be shorter than num.
1272
1263
 
1273
1264
  """
1274
1265
  # If signal samples are needed for te < t_start, then samples are taken
1275
1266
  # from the end of the calculated signal.
1276
- mpos = self.mics.mpos
1267
+ mpos = self.mics.pos
1277
1268
 
1278
1269
  # direction vector from tuple
1279
1270
  direc = array(self.direction, dtype=float)
@@ -1285,11 +1276,11 @@ class MovingLineSource(LineSource, MovingPointSource):
1285
1276
  dir2 = (direc_n * dist).reshape((3, 1))
1286
1277
 
1287
1278
  # blocwise output
1288
- out = zeros((num, self.numchannels))
1279
+ out = zeros((num, self.num_channels))
1289
1280
 
1290
1281
  # distances from monopoles in the line to microphones
1291
- rms = empty((self.numchannels, self.num_sources))
1292
- inds = empty((self.numchannels, self.num_sources))
1282
+ rms = empty((self.num_channels, self.num_sources))
1283
+ inds = empty((self.num_channels, self.num_sources))
1293
1284
  signals = empty((self.num_sources, len(self.signal.usignal(self.up))))
1294
1285
  # coherence
1295
1286
  for s in range(self.num_sources):
@@ -1298,13 +1289,13 @@ class MovingLineSource(LineSource, MovingPointSource):
1298
1289
  self.signal.seed = s + abs(int(hash(self.digest) // 10e12))
1299
1290
  self.signal.rms = self.signal.rms * self.source_strength[s]
1300
1291
  signals[s] = self.signal.usignal(self.up)
1301
- mpos = self.mics.mpos
1292
+ mpos = self.mics.pos
1302
1293
 
1303
- # shortcuts and intial values
1294
+ # shortcuts and initial values
1304
1295
  m = self.mics
1305
1296
  t = self.start * ones(m.num_mics)
1306
1297
  i = 0
1307
- n = self.numsamples
1298
+ n = self.num_samples
1308
1299
  while n:
1309
1300
  n -= 1
1310
1301
  t += 1.0 / self.sample_freq
@@ -1314,7 +1305,7 @@ class MovingLineSource(LineSource, MovingPointSource):
1314
1305
  # get distance and ind for every source in the line
1315
1306
  for s in range(self.num_sources):
1316
1307
  diff = self.get_moving_direction(dir2, te1)
1317
- te, rm, Mr, locs = self.get_emission_time(t, tile((diff * s).T, (self.numchannels, 1)).T)
1308
+ te, rm, Mr, locs = self.get_emission_time(t, tile((diff * s).T, (self.num_channels, 1)).T)
1318
1309
  loc = array(self.trajectory.location(te), dtype=float)[:, 0][:, newaxis]
1319
1310
  diff = self.get_moving_direction(dir2, te)
1320
1311
  rms[:, s] = self.env._r((loc + diff * s), mpos)
@@ -1332,13 +1323,14 @@ class MovingLineSource(LineSource, MovingPointSource):
1332
1323
  i += 1
1333
1324
  if i == num:
1334
1325
  yield out
1335
- out = zeros((num, self.numchannels))
1326
+ out = zeros((num, self.num_channels))
1336
1327
  i = 0
1337
1328
  except IndexError:
1338
1329
  break
1339
1330
  yield out[:i]
1340
1331
 
1341
1332
 
1333
+ @deprecated_alias({'numchannels': 'num_channels'}, read_only=True)
1342
1334
  class UncorrelatedNoiseSource(SamplesGenerator):
1343
1335
  """Class to simulate white or pink noise as uncorrelated signal at each
1344
1336
  channel.
@@ -1349,45 +1341,30 @@ class UncorrelatedNoiseSource(SamplesGenerator):
1349
1341
  #: Type of noise to generate at the channels.
1350
1342
  #: The `~acoular.signals.SignalGenerator`-derived class has to
1351
1343
  # feature the parameter "seed" (i.e. white or pink noise).
1352
- signal = Trait(SignalGenerator, desc='type of noise')
1344
+ signal = Instance(NoiseGenerator, desc='type of noise')
1353
1345
 
1354
1346
  #: Array with seeds for random number generator.
1355
- #: When left empty, arange(:attr:`numchannels`) + :attr:`signal`.seed
1347
+ #: When left empty, arange(:attr:`num_channels`) + :attr:`signal`.seed
1356
1348
  #: will be used.
1357
1349
  seed = CArray(dtype=uint32, desc='random seed values')
1358
1350
 
1359
1351
  #: Number of channels in output; is set automatically /
1360
1352
  #: depends on used microphone geometry.
1361
- numchannels = Delegate('mics', 'num_mics')
1353
+ num_channels = Delegate('mics', 'num_mics')
1362
1354
 
1363
1355
  #: :class:`~acoular.microphones.MicGeom` object that provides the microphone locations.
1364
- mics = Trait(MicGeom, desc='microphone geometry')
1365
-
1366
- # --- List of backwards compatibility traits and their setters/getters -----------
1367
-
1368
- # Microphone locations.
1369
- # Deprecated! Use :attr:`mics` trait instead.
1370
- mpos = Property()
1371
-
1372
- def _get_mpos(self):
1373
- return self.mics
1374
-
1375
- def _set_mpos(self, mpos):
1376
- warn("Deprecated use of 'mpos' trait. ", Warning, stacklevel=2)
1377
- self.mics = mpos
1378
-
1379
- # --- End of backwards compatibility traits --------------------------------------
1356
+ mics = Instance(MicGeom, desc='microphone geometry')
1380
1357
 
1381
1358
  #: Start time of the signal in seconds, defaults to 0 s.
1382
1359
  start_t = Float(0.0, desc='signal start time')
1383
1360
 
1384
- #: Start time of the data aquisition at microphones in seconds,
1361
+ #: Start time of the data acquisition at microphones in seconds,
1385
1362
  #: defaults to 0 s.
1386
1363
  start = Float(0.0, desc='sample start time')
1387
1364
 
1388
1365
  #: Number of samples is set automatically /
1389
1366
  #: depends on :attr:`signal`.
1390
- numsamples = Delegate('signal')
1367
+ num_samples = Delegate('signal')
1391
1368
 
1392
1369
  #: Sampling frequency of the signal; is set automatically /
1393
1370
  #: depends on :attr:`signal`.
@@ -1397,15 +1374,11 @@ class UncorrelatedNoiseSource(SamplesGenerator):
1397
1374
  digest = Property(
1398
1375
  depends_on=[
1399
1376
  'mics.digest',
1400
- 'signal.rms',
1401
- 'signal.numsamples',
1402
- 'signal.sample_freq',
1403
- 'signal.__class__',
1377
+ 'signal.digest',
1404
1378
  'seed',
1405
1379
  'loc',
1406
1380
  'start_t',
1407
1381
  'start',
1408
- '__class__',
1409
1382
  ],
1410
1383
  )
1411
1384
 
@@ -1424,45 +1397,43 @@ class UncorrelatedNoiseSource(SamplesGenerator):
1424
1397
 
1425
1398
  Returns
1426
1399
  -------
1427
- Samples in blocks of shape (num, numchannels).
1400
+ Samples in blocks of shape (num, num_channels).
1428
1401
  The last block may be shorter than num.
1429
1402
 
1430
1403
  """
1431
1404
  Noise = self.signal.__class__
1432
1405
  # create or get the array of random seeds
1433
- if not self.seed:
1434
- seed = arange(self.numchannels) + self.signal.seed
1435
- elif self.seed.shape == (self.numchannels,):
1406
+ if not self.seed.size > 0:
1407
+ seed = arange(self.num_channels) + self.signal.seed
1408
+ elif self.seed.shape == (self.num_channels,):
1436
1409
  seed = self.seed
1437
1410
  else:
1438
- raise ValueError(
1439
- 'Seed array expected to be of shape (%i,), but has shape %s.'
1440
- % (self.numchannels, str(self.seed.shape)),
1441
- )
1442
-
1443
- # create array with [numchannels] noise signal tracks
1411
+ msg = f'Seed array expected to be of shape ({self.num_channels:d},), but has shape {self.seed.shape}.'
1412
+ raise ValueError(msg)
1413
+ # create array with [num_channels] noise signal tracks
1444
1414
  signal = array(
1445
1415
  [
1446
- Noise(seed=s, numsamples=self.numsamples, sample_freq=self.sample_freq, rms=self.signal.rms).signal()
1416
+ Noise(seed=s, num_samples=self.num_samples, sample_freq=self.sample_freq, rms=self.signal.rms).signal()
1447
1417
  for s in seed
1448
1418
  ],
1449
1419
  ).T
1450
1420
 
1451
1421
  n = num
1452
- while n <= self.numsamples:
1422
+ while n <= self.num_samples:
1453
1423
  yield signal[n - num : n, :]
1454
1424
  n += num
1455
1425
  else:
1456
- if (n - num) < self.numsamples:
1426
+ if (n - num) < self.num_samples:
1457
1427
  yield signal[n - num :, :]
1458
1428
  else:
1459
1429
  return
1460
1430
 
1461
1431
 
1432
+ @deprecated_alias({'numchannels': 'num_channels', 'numsamples': 'num_samples'}, read_only=True)
1462
1433
  class SourceMixer(SamplesGenerator):
1463
1434
  """Mixes the signals from several sources."""
1464
1435
 
1465
- #: List of :class:`~acoular.tprocess.SamplesGenerator` objects
1436
+ #: List of :class:`~acoular.base.SamplesGenerator` objects
1466
1437
  #: to be mixed.
1467
1438
  sources = List(Instance(SamplesGenerator, ()))
1468
1439
 
@@ -1470,10 +1441,10 @@ class SourceMixer(SamplesGenerator):
1470
1441
  sample_freq = Property(depends_on=['sdigest'])
1471
1442
 
1472
1443
  #: Number of channels.
1473
- numchannels = Property(depends_on=['sdigest'])
1444
+ num_channels = Property(depends_on=['sdigest'])
1474
1445
 
1475
1446
  #: Number of samples.
1476
- numsamples = Property(depends_on=['sdigest'])
1447
+ num_samples = Property(depends_on=['sdigest'])
1477
1448
 
1478
1449
  #: Amplitude weight(s) for the sources as array. If not set,
1479
1450
  #: all source signals are equally weighted.
@@ -1499,12 +1470,12 @@ class SourceMixer(SamplesGenerator):
1499
1470
  return self.sources[0].sample_freq if self.sources else 0
1500
1471
 
1501
1472
  @cached_property
1502
- def _get_numchannels(self):
1503
- return self.sources[0].numchannels if self.sources else 0
1473
+ def _get_num_channels(self):
1474
+ return self.sources[0].num_channels if self.sources else 0
1504
1475
 
1505
1476
  @cached_property
1506
- def _get_numsamples(self):
1507
- return self.sources[0].numsamples if self.sources else 0
1477
+ def _get_num_samples(self):
1478
+ return self.sources[0].num_samples if self.sources else 0
1508
1479
 
1509
1480
  def validate_sources(self):
1510
1481
  """Validates if sources fit together."""
@@ -1513,11 +1484,14 @@ class SourceMixer(SamplesGenerator):
1513
1484
  raise ValueError(msg)
1514
1485
  for s in self.sources[1:]:
1515
1486
  if self.sample_freq != s.sample_freq:
1516
- raise ValueError('Sample frequency of %s does not fit' % s)
1517
- if self.numchannels != s.numchannels:
1518
- raise ValueError('Channel count of %s does not fit' % s)
1519
- if self.numsamples != s.numsamples:
1520
- raise ValueError('Number of samples of %s does not fit' % s)
1487
+ msg = f'Sample frequency of {s} does not fit'
1488
+ raise ValueError(msg)
1489
+ if self.num_channels != s.num_channels:
1490
+ msg = f'Channel count of {s} does not fit'
1491
+ raise ValueError(msg)
1492
+ if self.num_samples != s.num_samples:
1493
+ msg = f'Number of samples of {s} does not fit'
1494
+ raise ValueError(msg)
1521
1495
 
1522
1496
  def result(self, num):
1523
1497
  """Python generator that yields the output block-wise.
@@ -1531,7 +1505,7 @@ class SourceMixer(SamplesGenerator):
1531
1505
 
1532
1506
  Returns
1533
1507
  -------
1534
- Samples in blocks of shape (num, numchannels).
1508
+ Samples in blocks of shape (num, num_channels).
1535
1509
  The last block may be shorter than num.
1536
1510
 
1537
1511
  """
@@ -1557,10 +1531,10 @@ class SourceMixer(SamplesGenerator):
1557
1531
 
1558
1532
 
1559
1533
  class PointSourceConvolve(PointSource):
1560
- """Class to blockwise convolve an arbitrary source signal with a spatial room impulse response."""
1534
+ """Class to blockwise convolve an arbitrary source signal with a room impulse response."""
1561
1535
 
1562
- #: Convolution kernel in the time domain.
1563
- #: The second dimension of the kernel array has to be either 1 or match :attr:`~SamplesGenerator.numchannels`.
1536
+ #: Convolution kernel in the time domain. The second dimension of the kernel array
1537
+ #: has to be either 1 or match :attr:`~SamplesGenerator.num_channels`.
1564
1538
  #: If only a single kernel is supplied, it is applied to all channels.
1565
1539
  kernel = CArray(dtype=float, desc='Convolution kernel.')
1566
1540
 
@@ -1569,7 +1543,7 @@ class PointSourceConvolve(PointSource):
1569
1543
  #: Start time of the signal in seconds, defaults to 0 s.
1570
1544
  start_t = Enum(0.0, desc='signal start time')
1571
1545
 
1572
- #: Start time of the data aquisition at microphones in seconds,
1546
+ #: Start time of the data acquisition at microphones in seconds,
1573
1547
  #: defaults to 0 s.
1574
1548
  start = Enum(0.0, desc='sample start time')
1575
1549
 
@@ -1584,7 +1558,7 @@ class PointSourceConvolve(PointSource):
1584
1558
 
1585
1559
  # internal identifier
1586
1560
  digest = Property(
1587
- depends_on=['mics.digest', 'signal.digest', 'loc', 'kernel', '__class__'],
1561
+ depends_on=['mics.digest', 'signal.digest', 'loc', 'kernel'],
1588
1562
  )
1589
1563
 
1590
1564
  @cached_property
@@ -1602,7 +1576,7 @@ class PointSourceConvolve(PointSource):
1602
1576
 
1603
1577
  Returns
1604
1578
  -------
1605
- Samples in blocks of shape (num, numchannels).
1579
+ Samples in blocks of shape (num, num_channels).
1606
1580
  The last block may be shorter than num.
1607
1581
 
1608
1582
  """
@@ -1610,8 +1584,8 @@ class PointSourceConvolve(PointSource):
1610
1584
  source = TimeSamples(
1611
1585
  data=data,
1612
1586
  sample_freq=self.sample_freq,
1613
- numsamples=self.numsamples,
1614
- numchannels=self.mics.num_mics,
1587
+ num_samples=self.num_samples,
1588
+ num_channels=self.mics.num_mics,
1615
1589
  )
1616
1590
  time_convolve = TimeConvolve(
1617
1591
  source=source,