acoular 24.10__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
@@ -57,7 +57,7 @@ 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,11 +66,10 @@ 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,
@@ -80,20 +79,22 @@ from .base import SamplesGenerator
80
79
 
81
80
  # acoular imports
82
81
  from .calib import Calib
82
+ from .deprecation import deprecated_alias
83
83
  from .environments import Environment
84
84
  from .h5files import H5FileBase, _get_h5file_class
85
85
  from .internal import digest, ldigest
86
86
  from .microphones import MicGeom
87
- from .signals import SignalGenerator
87
+ from .signals import NoiseGenerator, SignalGenerator
88
+ from .tools.utils import get_file_basename
88
89
  from .tprocess import TimeConvolve
89
90
  from .trajectory import Trajectory
90
91
 
91
92
 
92
- @nb.njit(cache=True, error_model='numpy') # jit with nopython
93
- 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):
94
95
  if prepadding:
95
96
  for b in range(blocksize):
96
- for m in range(numchannels):
97
+ for m in range(num_channels):
97
98
  if ind[0, m] < 0:
98
99
  out[b, m] = 0
99
100
  else:
@@ -101,7 +102,7 @@ def _fill_mic_signal_block(out, signal, rm, ind, blocksize, numchannels, up, pre
101
102
  ind += up
102
103
  else:
103
104
  for b in range(blocksize):
104
- for m in range(numchannels):
105
+ for m in range(num_channels):
105
106
  out[b, m] = signal[int(0.5 + ind[0, m])] / rm[0, m]
106
107
  ind += up
107
108
  return out
@@ -182,11 +183,12 @@ def get_modes(lOrder, direction, mpos, sourceposition=None): # noqa: N803
182
183
  return modes
183
184
 
184
185
 
186
+ @deprecated_alias({'name': 'file'})
185
187
  class TimeSamples(SamplesGenerator):
186
188
  """Container for processing time data in `*.h5` or NumPy array format.
187
189
 
188
- This class loads measured data from HDF5 files and provides information about this data.
189
- 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
190
192
  :meth:`result` generator.
191
193
 
192
194
  Examples
@@ -194,9 +196,9 @@ class TimeSamples(SamplesGenerator):
194
196
  Data can be loaded from a HDF5 file as follows:
195
197
 
196
198
  >>> from acoular import TimeSamples
197
- >>> name = <some_h5_file.h5> # doctest: +SKIP
198
- >>> ts = TimeSamples(name=name) # doctest: +SKIP
199
- >>> 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
200
202
  number of channels: 56 # doctest: +SKIP
201
203
 
202
204
  Alternatively, the time data can be specified directly as a numpy array.
@@ -206,8 +208,9 @@ class TimeSamples(SamplesGenerator):
206
208
  >>> data = np.random.rand(1000, 4)
207
209
  >>> ts = TimeSamples(data=data, sample_freq=51200)
208
210
 
209
- Chunks of the time data can be accessed iteratively via the :meth:`result` generator.
210
- 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.
211
214
 
212
215
  >>> blocksize = 512
213
216
  >>> generator = ts.result(num=blocksize)
@@ -218,30 +221,27 @@ class TimeSamples(SamplesGenerator):
218
221
 
219
222
  See Also
220
223
  --------
221
- acoular.sources.MaskedTimeSamples :
222
- Extends the functionality of class :class:`TimeSamples` by enabling the definition of start and stop samples
223
- 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.
224
227
  """
225
228
 
226
229
  #: Full name of the .h5 file with data.
227
- name = File(filter=['*.h5'], desc='name of data file')
230
+ file = File(filter=['*.h5'], exists=True, desc='name of data file')
228
231
 
229
232
  #: Basename of the .h5 file with data, is set automatically.
230
- basename = Property(
231
- depends_on='name', # filter=['*.h5'],
232
- desc='basename of data file',
233
- )
233
+ basename = Property(depends_on=['file'], desc='basename of data file')
234
234
 
235
235
  #: Calibration data, instance of :class:`~acoular.calib.Calib` class, optional .
236
- calib = Trait(Calib, desc='Calibration data')
236
+ calib = Instance(Calib, desc='Calibration data')
237
237
 
238
238
  #: Number of channels, is set automatically / read from file.
239
- numchannels = CLong(0, desc='number of input channels')
239
+ num_channels = CInt(0, desc='number of input channels')
240
240
 
241
241
  #: Number of time data samples, is set automatically / read from file.
242
- numsamples = CLong(0, desc='number of samples')
242
+ num_samples = CInt(0, desc='number of samples')
243
243
 
244
- #: 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).
245
245
  data = Any(transient=True, desc='the actual time data array')
246
246
 
247
247
  #: HDF5 file object
@@ -255,7 +255,7 @@ class TimeSamples(SamplesGenerator):
255
255
 
256
256
  # internal identifier
257
257
  digest = Property(
258
- depends_on=['basename', 'calib.digest', '_datachecksum', 'sample_freq', 'numchannels', 'numsamples']
258
+ depends_on=['basename', 'calib.digest', '_datachecksum', 'sample_freq', 'num_channels', 'num_samples']
259
259
  )
260
260
 
261
261
  def _get__datachecksum(self):
@@ -267,27 +267,24 @@ class TimeSamples(SamplesGenerator):
267
267
 
268
268
  @cached_property
269
269
  def _get_basename(self):
270
- return path.splitext(path.basename(self.name))[0]
270
+ return get_file_basename(self.file)
271
271
 
272
272
  @on_trait_change('basename')
273
273
  def _load_data(self):
274
274
  """Open the .h5 file and set attributes."""
275
- if not path.isfile(self.name):
276
- self.sample_freq = 0
277
- raise OSError('No such file: %s' % self.name)
278
275
  if self.h5f is not None:
279
276
  with contextlib.suppress(OSError):
280
277
  self.h5f.close()
281
278
  file = _get_h5file_class()
282
- self.h5f = file(self.name)
279
+ self.h5f = file(self.file)
283
280
  self._load_timedata()
284
281
  self._load_metadata()
285
282
 
286
283
  @on_trait_change('data')
287
284
  def _load_shapes(self):
288
- """Set numchannels and numsamples from data."""
285
+ """Set num_channels and num_samples from data."""
289
286
  if self.data is not None:
290
- self.numsamples, self.numchannels = self.data.shape
287
+ self.num_samples, self.num_channels = self.data.shape
291
288
 
292
289
  def _load_timedata(self):
293
290
  """Loads timedata from .h5 file. Only for internal use."""
@@ -316,46 +313,61 @@ class TimeSamples(SamplesGenerator):
316
313
  Yields
317
314
  ------
318
315
  numpy.ndarray
319
- Samples in blocks of shape (num, numchannels).
316
+ Samples in blocks of shape (num, num_channels).
320
317
  The last block may be shorter than num.
321
318
 
322
319
  """
323
- if self.numsamples == 0:
320
+ if self.num_samples == 0:
324
321
  msg = 'no samples available'
325
322
  raise OSError(msg)
326
323
  self._datachecksum # trigger checksum calculation # noqa: B018
327
324
  i = 0
328
325
  if self.calib:
329
- 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:
330
333
  cal_factor = self.calib.data[newaxis]
331
334
  else:
332
- raise ValueError('calibration data not compatible: %i, %i' % (self.calib.num_mics, self.numchannels))
333
- 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:
334
338
  yield self.data[i : i + num] * cal_factor
335
339
  i += num
336
340
  else:
337
- while i < self.numsamples:
341
+ while i < self.num_samples:
338
342
  yield self.data[i : i + num]
339
343
  i += num
340
344
 
341
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
+ )
342
355
  class MaskedTimeSamples(TimeSamples):
343
356
  """Container for processing time data in `*.h5` or NumPy array format.
344
357
 
345
- This class loads measured data from HDF5 files and provides information about this data.
346
- It supports storing information about (in)valid samples and (in)valid channels and allows
347
- to specify a start and stop index for the valid samples.
348
- It also serves as an interface where the data can be accessed (e.g. for use in a block chain) via the
349
- :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.
350
362
 
351
363
  Examples
352
364
  --------
353
365
  Data can be loaded from a HDF5 file and invalid channels can be specified as follows:
354
366
 
355
367
  >>> from acoular import MaskedTimeSamples
356
- >>> name = <some_h5_file.h5> # doctest: +SKIP
357
- >>> ts = MaskedTimeSamples(name=name, invalid_channels=[0, 1]) # doctest: +SKIP
358
- >>> 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
359
371
  number of valid channels: 54 # doctest: +SKIP
360
372
 
361
373
  Alternatively, the time data can be specified directly as a numpy array.
@@ -368,8 +380,8 @@ class MaskedTimeSamples(TimeSamples):
368
380
 
369
381
  Chunks of the time data can be accessed iteratively via the :meth:`result` generator:
370
382
 
371
- >>> blocksize = 512
372
- >>> generator = ts.result(num=blocksize)
383
+ >>> block_size = 512
384
+ >>> generator = ts.result(num=block_size)
373
385
  >>> for block in generator:
374
386
  ... print(block.shape)
375
387
  (512, 4)
@@ -377,28 +389,32 @@ class MaskedTimeSamples(TimeSamples):
377
389
  """
378
390
 
379
391
  #: Index of the first sample to be considered valid.
380
- start = CLong(0, desc='start of valid samples')
392
+ start = CInt(0, desc='start of valid samples')
381
393
 
382
394
  #: Index of the last sample to be considered valid.
383
- stop = Trait(None, None, CLong, desc='stop of valid samples')
395
+ stop = Union(None, CInt, desc='stop of valid samples')
384
396
 
385
397
  #: Channels that are to be treated as invalid.
386
- invalid_channels = ListInt(desc='list of invalid channels')
398
+ invalid_channels = List(int, desc='list of invalid channels')
387
399
 
388
400
  #: Channel mask to serve as an index for all valid channels, is set automatically.
389
- channels = Property(depends_on=['invalid_channels', 'numchannels_total'], desc='channel mask')
401
+ channels = Property(depends_on=['invalid_channels', 'num_channels_total'], desc='channel mask')
390
402
 
391
403
  #: Number of channels (including invalid channels), is set automatically.
392
- numchannels_total = CLong(0, desc='total number of input channels')
404
+ num_channels_total = CInt(0, desc='total number of input channels')
393
405
 
394
406
  #: Number of time data samples (including invalid samples), is set automatically.
395
- numsamples_total = CLong(0, desc='total number of samples per channel')
407
+ num_samples_total = CInt(0, desc='total number of samples per channel')
396
408
 
397
409
  #: Number of valid channels, is set automatically.
398
- 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
+ )
399
413
 
400
414
  #: Number of valid time data samples, is set automatically.
401
- 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
+ )
402
418
 
403
419
  # internal identifier
404
420
  digest = Property(depends_on=['basename', 'start', 'stop', 'calib.digest', 'invalid_channels', '_datachecksum'])
@@ -407,55 +423,52 @@ class MaskedTimeSamples(TimeSamples):
407
423
  def _get_digest(self):
408
424
  return digest(self)
409
425
 
410
- @cached_property
411
- def _get_basename(self):
412
- return path.splitext(path.basename(self.name))[0]
413
-
414
426
  @cached_property
415
427
  def _get_channels(self):
416
428
  if len(self.invalid_channels) == 0:
417
429
  return slice(0, None, None)
418
- 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]
419
431
  return array(allr)
420
432
 
421
433
  @cached_property
422
- def _get_numchannels(self):
434
+ def _get_num_channels(self):
423
435
  if len(self.invalid_channels) == 0:
424
- return self.numchannels_total
436
+ return self.num_channels_total
425
437
  return len(self.channels)
426
438
 
427
439
  @cached_property
428
- def _get_numsamples(self):
429
- 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)
430
442
  return sli[1] - sli[0]
431
443
 
432
444
  @on_trait_change('basename')
433
445
  def _load_data(self):
434
446
  # """ open the .h5 file and set attributes
435
447
  # """
436
- if not path.isfile(self.name):
448
+ if not path.isfile(self.file):
437
449
  # no file there
438
450
  self.sample_freq = 0
439
- raise OSError('No such file: %s' % self.name)
451
+ msg = f'No such file: {self.file}'
452
+ raise OSError(msg)
440
453
  if self.h5f is not None:
441
454
  with contextlib.suppress(OSError):
442
455
  self.h5f.close()
443
456
  file = _get_h5file_class()
444
- self.h5f = file(self.name)
457
+ self.h5f = file(self.file)
445
458
  self._load_timedata()
446
459
  self._load_metadata()
447
460
 
448
461
  @on_trait_change('data')
449
462
  def _load_shapes(self):
450
- """Set numchannels and numsamples from data."""
463
+ """Set num_channels and num_samples from data."""
451
464
  if self.data is not None:
452
- self.numsamples_total, self.numchannels_total = self.data.shape
465
+ self.num_samples_total, self.num_channels_total = self.data.shape
453
466
 
454
467
  def _load_timedata(self):
455
468
  """Loads timedata from .h5 file. Only for internal use."""
456
469
  self.data = self.h5f.get_data_by_reference('time_data')
457
470
  self.sample_freq = self.h5f.get_node_attribute(self.data, 'sample_freq')
458
- (self.numsamples_total, self.numchannels_total) = self.data.shape
471
+ (self.num_samples_total, self.num_channels_total) = self.data.shape
459
472
 
460
473
  def result(self, num=128):
461
474
  """Python generator that yields the output block-wise.
@@ -473,11 +486,11 @@ class MaskedTimeSamples(TimeSamples):
473
486
  Yields
474
487
  ------
475
488
  numpy.ndarray
476
- Samples in blocks of shape (num, numchannels).
489
+ Samples in blocks of shape (num, num_channels).
477
490
  The last block may be shorter than num.
478
491
 
479
492
  """
480
- sli = slice(self.start, self.stop).indices(self.numsamples_total)
493
+ sli = slice(self.start, self.stop).indices(self.num_samples_total)
481
494
  i = sli[0]
482
495
  stop = sli[1]
483
496
  cal_factor = 1.0
@@ -486,19 +499,27 @@ class MaskedTimeSamples(TimeSamples):
486
499
  raise OSError(msg)
487
500
  self._datachecksum # trigger checksum calculation # noqa: B018
488
501
  if self.calib:
489
- 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:
490
509
  cal_factor = self.calib.data[self.channels][newaxis]
491
- elif self.calib.num_mics == self.numchannels:
510
+ elif self.calib.num_mics == self.num_channels:
492
511
  cal_factor = self.calib.data[newaxis]
493
512
  elif self.calib.num_mics == 0:
494
513
  warn('No calibration data used.', Warning, stacklevel=2)
495
514
  else:
496
- 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)
497
517
  while i < stop:
498
518
  yield self.data[i : min(i + num, stop)][:, self.channels] * cal_factor
499
519
  i += num
500
520
 
501
521
 
522
+ @deprecated_alias({'numchannels': 'num_channels', 'numsamples': 'num_samples'}, read_only=True)
502
523
  class PointSource(SamplesGenerator):
503
524
  """Class to define a fixed point source with an arbitrary signal.
504
525
  This can be used in simulations.
@@ -507,63 +528,31 @@ class PointSource(SamplesGenerator):
507
528
  """
508
529
 
509
530
  #: Emitted signal, instance of the :class:`~acoular.signals.SignalGenerator` class.
510
- signal = Trait(SignalGenerator)
531
+ signal = Instance(SignalGenerator)
511
532
 
512
533
  #: Location of source in (`x`, `y`, `z`) coordinates (left-oriented system).
513
534
  loc = Tuple((0.0, 0.0, 1.0), desc='source location')
514
535
 
515
536
  #: Number of channels in output, is set automatically /
516
537
  #: depends on used microphone geometry.
517
- numchannels = Delegate('mics', 'num_mics')
538
+ num_channels = Delegate('mics', 'num_mics')
518
539
 
519
540
  #: :class:`~acoular.microphones.MicGeom` object that provides the microphone locations.
520
- mics = Trait(MicGeom, desc='microphone geometry')
541
+ mics = Instance(MicGeom, desc='microphone geometry')
521
542
 
522
543
  def _validate_locations(self):
523
- 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)
524
545
  if npany(dist < 1e-7):
525
546
  warn('Source and microphone locations are identical.', Warning, stacklevel=2)
526
547
 
527
548
  #: :class:`~acoular.environments.Environment` or derived object,
528
549
  #: which provides information about the sound propagation in the medium.
529
- env = Trait(Environment(), Environment)
530
-
531
- # --- List of backwards compatibility traits and their setters/getters -----------
532
-
533
- # Microphone locations.
534
- # Deprecated! Use :attr:`mics` trait instead.
535
- mpos = Property()
536
-
537
- def _get_mpos(self):
538
- return self.mics
539
-
540
- def _set_mpos(self, mpos):
541
- msg = (
542
- "Deprecated use of 'mpos' trait. Use 'mics' trait instead."
543
- "The 'mpos' trait will be removed in version 25.01."
544
- )
545
- warn(msg, DeprecationWarning, stacklevel=2)
546
- self.mics = mpos
547
-
548
- # The speed of sound.
549
- # Deprecated! Only kept for backwards compatibility.
550
- # Now governed by :attr:`env` trait.
551
- c = Property()
552
-
553
- def _get_c(self):
554
- return self.env.c
555
-
556
- def _set_c(self, c):
557
- msg = "Deprecated use of 'c' trait. Use 'env' trait instead." "The 'c' trait will be removed in version 25.01."
558
- warn(msg, DeprecationWarning, stacklevel=2)
559
- self.env.c = c
560
-
561
- # --- End of backwards compatibility traits --------------------------------------
550
+ env = Instance(Environment(), Environment)
562
551
 
563
552
  #: Start time of the signal in seconds, defaults to 0 s.
564
553
  start_t = Float(0.0, desc='signal start time')
565
554
 
566
- #: Start time of the data aquisition at microphones in seconds,
555
+ #: Start time of the data acquisition at microphones in seconds,
567
556
  #: defaults to 0 s.
568
557
  start = Float(0.0, desc='sample start time')
569
558
 
@@ -571,14 +560,14 @@ class PointSource(SamplesGenerator):
571
560
  #: `loop` take values from the end of :attr:`signal.signal()` array.
572
561
  #: `zeros` set source signal to zero, advisable for deterministic signals.
573
562
  #: defaults to `loop`.
574
- prepadding = Trait('loop', 'zeros', desc='Behaviour for negative time indices.')
563
+ prepadding = Enum('loop', 'zeros', desc='Behaviour for negative time indices.')
575
564
 
576
565
  #: Upsampling factor, internal use, defaults to 16.
577
566
  up = Int(16, desc='upsampling factor')
578
567
 
579
568
  #: Number of samples, is set automatically /
580
569
  #: depends on :attr:`signal`.
581
- numsamples = Delegate('signal')
570
+ num_samples = Delegate('signal')
582
571
 
583
572
  #: Sampling frequency of the signal, is set automatically /
584
573
  #: depends on :attr:`signal`.
@@ -595,7 +584,6 @@ class PointSource(SamplesGenerator):
595
584
  'start',
596
585
  'up',
597
586
  'prepadding',
598
- '__class__',
599
587
  ],
600
588
  )
601
589
 
@@ -614,16 +602,16 @@ class PointSource(SamplesGenerator):
614
602
 
615
603
  Returns
616
604
  -------
617
- Samples in blocks of shape (num, numchannels).
605
+ Samples in blocks of shape (num, num_channels).
618
606
  The last block may be shorter than num.
619
607
 
620
608
  """
621
609
  self._validate_locations()
622
- N = int(ceil(self.numsamples / num)) # number of output blocks
610
+ N = int(ceil(self.num_samples / num)) # number of output blocks
623
611
  signal = self.signal.usignal(self.up)
624
- out = empty((num, self.numchannels))
612
+ out = empty((num, self.num_channels))
625
613
  # distances
626
- 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)
627
615
  # emission time relative to start_t (in samples) for first sample
628
616
  ind = (-rm / self.env.c - self.start_t + self.start) * self.sample_freq * self.up
629
617
 
@@ -634,16 +622,16 @@ class PointSource(SamplesGenerator):
634
622
  # if signal stops during prepadding, terminate
635
623
  if pre >= N:
636
624
  for _nb in range(N - 1):
637
- 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)
638
626
  yield out
639
627
 
640
- blocksize = self.numsamples % num or num
641
- 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)
642
630
  yield out[:blocksize]
643
631
  return
644
632
  else:
645
633
  for _nb in range(pre):
646
- 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)
647
635
  yield out
648
636
 
649
637
  else:
@@ -651,12 +639,12 @@ class PointSource(SamplesGenerator):
651
639
 
652
640
  # main generator
653
641
  for _nb in range(N - pre - 1):
654
- 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)
655
643
  yield out
656
644
 
657
645
  # last block of variable size
658
- blocksize = self.numsamples % num or num
659
- 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)
660
648
  yield out[:blocksize]
661
649
 
662
650
 
@@ -687,7 +675,6 @@ class SphericalHarmonicSource(PointSource):
687
675
  'start_t',
688
676
  'start',
689
677
  'up',
690
- '__class__',
691
678
  'alpha',
692
679
  'lOrder',
693
680
  'prepadding',
@@ -702,7 +689,7 @@ class SphericalHarmonicSource(PointSource):
702
689
  Y_lm = get_modes(
703
690
  lOrder=self.lOrder,
704
691
  direction=self.direction,
705
- mpos=self.mics.mpos,
692
+ mpos=self.mics.pos,
706
693
  sourceposition=array(self.loc),
707
694
  )
708
695
  return real(ifft(fft(signals, axis=0) * (Y_lm @ self.alpha), axis=0))
@@ -718,7 +705,7 @@ class SphericalHarmonicSource(PointSource):
718
705
 
719
706
  Returns
720
707
  -------
721
- Samples in blocks of shape (num, numchannels).
708
+ Samples in blocks of shape (num, num_channels).
722
709
  The last block may be shorter than num.
723
710
 
724
711
  """
@@ -727,11 +714,11 @@ class SphericalHarmonicSource(PointSource):
727
714
 
728
715
  signal = self.signal.usignal(self.up)
729
716
  # emission time relative to start_t (in samples) for first sample
730
- 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)
731
718
  ind = (-rm / self.env.c - self.start_t + self.start) * self.sample_freq + pi / 30
732
719
  i = 0
733
- n = self.numsamples
734
- out = empty((num, self.numchannels))
720
+ n = self.num_samples
721
+ out = empty((num, self.num_channels))
735
722
  while n:
736
723
  n -= 1
737
724
  try:
@@ -761,7 +748,7 @@ class MovingPointSource(PointSource):
761
748
  #: Trajectory of the source,
762
749
  #: instance of the :class:`~acoular.trajectory.Trajectory` class.
763
750
  #: The start time is assumed to be the same as for the samples.
764
- trajectory = Trait(Trajectory, desc='trajectory of the source')
751
+ trajectory = Instance(Trajectory, desc='trajectory of the source')
765
752
 
766
753
  prepadding = Enum('loop', desc='Behaviour for negative time indices.')
767
754
 
@@ -777,7 +764,6 @@ class MovingPointSource(PointSource):
777
764
  'start',
778
765
  'trajectory.digest',
779
766
  'prepadding',
780
- '__class__',
781
767
  ],
782
768
  )
783
769
 
@@ -796,7 +782,7 @@ class MovingPointSource(PointSource):
796
782
 
797
783
  Returns
798
784
  -------
799
- Samples in blocks of shape (num, numchannels).
785
+ Samples in blocks of shape (num, num_channels).
800
786
  The last block may be shorter than num.
801
787
 
802
788
  """
@@ -804,15 +790,15 @@ class MovingPointSource(PointSource):
804
790
  # from the end of the calculated signal.
805
791
 
806
792
  signal = self.signal.usignal(self.up)
807
- out = empty((num, self.numchannels))
808
- # shortcuts and intial values
793
+ out = empty((num, self.num_channels))
794
+ # shortcuts and initial values
809
795
  m = self.mics
810
796
  t = self.start * ones(m.num_mics)
811
797
  i = 0
812
798
  epslim = 0.1 / self.up / self.sample_freq
813
799
  c0 = self.env.c
814
800
  tr = self.trajectory
815
- n = self.numsamples
801
+ n = self.num_samples
816
802
  while n:
817
803
  n -= 1
818
804
  eps = ones(m.num_mics)
@@ -821,7 +807,7 @@ class MovingPointSource(PointSource):
821
807
  # Newton-Rhapson iteration
822
808
  while abs(eps).max() > epslim and j < 100:
823
809
  loc = array(tr.location(te))
824
- rm = loc - m.mpos # distance vectors to microphones
810
+ rm = loc - m.pos # distance vectors to microphones
825
811
  rm = sqrt((rm * rm).sum(0)) # absolute distance
826
812
  loc /= sqrt((loc * loc).sum(0)) # distance unit vector
827
813
  der = array(tr.location(te, der=1))
@@ -876,7 +862,6 @@ class PointSourceDipole(PointSource):
876
862
  'up',
877
863
  'direction',
878
864
  'prepadding',
879
- '__class__',
880
865
  ],
881
866
  )
882
867
 
@@ -895,14 +880,14 @@ class PointSourceDipole(PointSource):
895
880
 
896
881
  Returns
897
882
  -------
898
- Samples in blocks of shape (num, numchannels).
883
+ Samples in blocks of shape (num, num_channels).
899
884
  The last block may be shorter than num.
900
885
 
901
886
  """
902
887
  # If signal samples are needed for te < t_start, then samples are taken
903
888
  # from the end of the calculated signal.
904
889
 
905
- mpos = self.mics.mpos
890
+ mpos = self.mics.pos
906
891
  # position of the dipole as (3,1) vector
907
892
  loc = array(self.loc, dtype=float).reshape((3, 1))
908
893
  # direction vector from tuple
@@ -921,7 +906,7 @@ class PointSourceDipole(PointSource):
921
906
  dir2 = (direc_n * dist / 2.0).reshape((3, 1))
922
907
 
923
908
  signal = self.signal.usignal(self.up)
924
- out = empty((num, self.numchannels))
909
+ out = empty((num, self.num_channels))
925
910
 
926
911
  # distance from dipole center to microphones
927
912
  rm = self.env._r(loc, mpos)
@@ -935,7 +920,7 @@ class PointSourceDipole(PointSource):
935
920
  ind2 = (-rm2 / c - self.start_t + self.start) * self.sample_freq
936
921
 
937
922
  i = 0
938
- n = self.numsamples
923
+ n = self.num_samples
939
924
  while n:
940
925
  n -= 1
941
926
  try:
@@ -973,7 +958,6 @@ class MovingPointSourceDipole(PointSourceDipole, MovingPointSource):
973
958
  'start',
974
959
  'up',
975
960
  'direction',
976
- '__class__',
977
961
  ],
978
962
  )
979
963
 
@@ -995,7 +979,7 @@ class MovingPointSourceDipole(PointSourceDipole, MovingPointSource):
995
979
  xs = array(self.trajectory.location(te))
996
980
  loc = xs.copy()
997
981
  loc += direction
998
- rm = loc - self.mics.mpos # distance vectors to microphones
982
+ rm = loc - self.mics.pos # distance vectors to microphones
999
983
  rm = sqrt((rm * rm).sum(0)) # absolute distance
1000
984
  loc /= sqrt((loc * loc).sum(0)) # distance unit vector
1001
985
  der = array(self.trajectory.location(te, der=1))
@@ -1030,13 +1014,13 @@ class MovingPointSourceDipole(PointSourceDipole, MovingPointSource):
1030
1014
 
1031
1015
  Returns
1032
1016
  -------
1033
- Samples in blocks of shape (num, numchannels).
1017
+ Samples in blocks of shape (num, num_channels).
1034
1018
  The last block may be shorter than num.
1035
1019
 
1036
1020
  """
1037
1021
  # If signal samples are needed for te < t_start, then samples are taken
1038
1022
  # from the end of the calculated signal.
1039
- mpos = self.mics.mpos
1023
+ mpos = self.mics.pos
1040
1024
 
1041
1025
  # direction vector from tuple
1042
1026
  direc = array(self.direction, dtype=float) * 1e-5
@@ -1051,13 +1035,13 @@ class MovingPointSourceDipole(PointSourceDipole, MovingPointSource):
1051
1035
  dir2 = (direc_n * dist / 2.0).reshape((3, 1))
1052
1036
 
1053
1037
  signal = self.signal.usignal(self.up)
1054
- out = empty((num, self.numchannels))
1055
- # shortcuts and intial values
1038
+ out = empty((num, self.num_channels))
1039
+ # shortcuts and initial values
1056
1040
  m = self.mics
1057
1041
  t = self.start * ones(m.num_mics)
1058
1042
 
1059
1043
  i = 0
1060
- n = self.numsamples
1044
+ n = self.num_samples
1061
1045
  while n:
1062
1046
  n -= 1
1063
1047
  te, rm, Mr, locs = self.get_emission_time(t, 0)
@@ -1115,7 +1099,7 @@ class LineSource(PointSource):
1115
1099
  source_strength = CArray(desc='coefficients of the source strength')
1116
1100
 
1117
1101
  #:coherence
1118
- coherence = Trait('coherent', 'incoherent', desc='coherence mode')
1102
+ coherence = Enum('coherent', 'incoherent', desc='coherence mode')
1119
1103
 
1120
1104
  # internal identifier
1121
1105
  digest = Property(
@@ -1130,7 +1114,6 @@ class LineSource(PointSource):
1130
1114
  'direction',
1131
1115
  'source_strength',
1132
1116
  'coherence',
1133
- '__class__',
1134
1117
  ],
1135
1118
  )
1136
1119
 
@@ -1149,14 +1132,14 @@ class LineSource(PointSource):
1149
1132
 
1150
1133
  Returns
1151
1134
  -------
1152
- Samples in blocks of shape (num, numchannels).
1135
+ Samples in blocks of shape (num, num_channels).
1153
1136
  The last block may be shorter than num.
1154
1137
 
1155
1138
  """
1156
1139
  # If signal samples are needed for te < t_start, then samples are taken
1157
1140
  # from the end of the calculated signal.
1158
1141
 
1159
- mpos = self.mics.mpos
1142
+ mpos = self.mics.pos
1160
1143
 
1161
1144
  # direction vector from tuple
1162
1145
  direc = array(self.direction, dtype=float)
@@ -1168,14 +1151,14 @@ class LineSource(PointSource):
1168
1151
  dist = self.length / self.num_sources
1169
1152
 
1170
1153
  # blocwise output
1171
- out = zeros((num, self.numchannels))
1154
+ out = zeros((num, self.num_channels))
1172
1155
 
1173
1156
  # distance from line start position to microphones
1174
1157
  loc = array(self.loc, dtype=float).reshape((3, 1))
1175
1158
 
1176
1159
  # distances from monopoles in the line to microphones
1177
- rms = empty((self.numchannels, self.num_sources))
1178
- 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))
1179
1162
  signals = empty((self.num_sources, len(self.signal.usignal(self.up))))
1180
1163
  # for every source - distances
1181
1164
  for s in range(self.num_sources):
@@ -1187,7 +1170,7 @@ class LineSource(PointSource):
1187
1170
  self.signal.rms = self.signal.rms * self.source_strength[s]
1188
1171
  signals[s] = self.signal.usignal(self.up)
1189
1172
  i = 0
1190
- n = self.numsamples
1173
+ n = self.num_samples
1191
1174
  while n:
1192
1175
  n -= 1
1193
1176
  try:
@@ -1199,7 +1182,7 @@ class LineSource(PointSource):
1199
1182
  i += 1
1200
1183
  if i == num:
1201
1184
  yield out
1202
- out = zeros((num, self.numchannels))
1185
+ out = zeros((num, self.num_channels))
1203
1186
  i = 0
1204
1187
  except IndexError:
1205
1188
  break
@@ -1219,7 +1202,6 @@ class MovingLineSource(LineSource, MovingPointSource):
1219
1202
  'start',
1220
1203
  'up',
1221
1204
  'direction',
1222
- '__class__',
1223
1205
  ],
1224
1206
  )
1225
1207
 
@@ -1255,7 +1237,7 @@ class MovingLineSource(LineSource, MovingPointSource):
1255
1237
  xs = array(self.trajectory.location(te))
1256
1238
  loc = xs.copy()
1257
1239
  loc += direction
1258
- rm = loc - self.mics.mpos # distance vectors to microphones
1240
+ rm = loc - self.mics.pos # distance vectors to microphones
1259
1241
  rm = sqrt((rm * rm).sum(0)) # absolute distance
1260
1242
  loc /= sqrt((loc * loc).sum(0)) # distance unit vector
1261
1243
  der = array(self.trajectory.location(te, der=1))
@@ -1276,13 +1258,13 @@ class MovingLineSource(LineSource, MovingPointSource):
1276
1258
 
1277
1259
  Returns
1278
1260
  -------
1279
- Samples in blocks of shape (num, numchannels).
1261
+ Samples in blocks of shape (num, num_channels).
1280
1262
  The last block may be shorter than num.
1281
1263
 
1282
1264
  """
1283
1265
  # If signal samples are needed for te < t_start, then samples are taken
1284
1266
  # from the end of the calculated signal.
1285
- mpos = self.mics.mpos
1267
+ mpos = self.mics.pos
1286
1268
 
1287
1269
  # direction vector from tuple
1288
1270
  direc = array(self.direction, dtype=float)
@@ -1294,11 +1276,11 @@ class MovingLineSource(LineSource, MovingPointSource):
1294
1276
  dir2 = (direc_n * dist).reshape((3, 1))
1295
1277
 
1296
1278
  # blocwise output
1297
- out = zeros((num, self.numchannels))
1279
+ out = zeros((num, self.num_channels))
1298
1280
 
1299
1281
  # distances from monopoles in the line to microphones
1300
- rms = empty((self.numchannels, self.num_sources))
1301
- 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))
1302
1284
  signals = empty((self.num_sources, len(self.signal.usignal(self.up))))
1303
1285
  # coherence
1304
1286
  for s in range(self.num_sources):
@@ -1307,13 +1289,13 @@ class MovingLineSource(LineSource, MovingPointSource):
1307
1289
  self.signal.seed = s + abs(int(hash(self.digest) // 10e12))
1308
1290
  self.signal.rms = self.signal.rms * self.source_strength[s]
1309
1291
  signals[s] = self.signal.usignal(self.up)
1310
- mpos = self.mics.mpos
1292
+ mpos = self.mics.pos
1311
1293
 
1312
- # shortcuts and intial values
1294
+ # shortcuts and initial values
1313
1295
  m = self.mics
1314
1296
  t = self.start * ones(m.num_mics)
1315
1297
  i = 0
1316
- n = self.numsamples
1298
+ n = self.num_samples
1317
1299
  while n:
1318
1300
  n -= 1
1319
1301
  t += 1.0 / self.sample_freq
@@ -1323,7 +1305,7 @@ class MovingLineSource(LineSource, MovingPointSource):
1323
1305
  # get distance and ind for every source in the line
1324
1306
  for s in range(self.num_sources):
1325
1307
  diff = self.get_moving_direction(dir2, te1)
1326
- 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)
1327
1309
  loc = array(self.trajectory.location(te), dtype=float)[:, 0][:, newaxis]
1328
1310
  diff = self.get_moving_direction(dir2, te)
1329
1311
  rms[:, s] = self.env._r((loc + diff * s), mpos)
@@ -1341,13 +1323,14 @@ class MovingLineSource(LineSource, MovingPointSource):
1341
1323
  i += 1
1342
1324
  if i == num:
1343
1325
  yield out
1344
- out = zeros((num, self.numchannels))
1326
+ out = zeros((num, self.num_channels))
1345
1327
  i = 0
1346
1328
  except IndexError:
1347
1329
  break
1348
1330
  yield out[:i]
1349
1331
 
1350
1332
 
1333
+ @deprecated_alias({'numchannels': 'num_channels'}, read_only=True)
1351
1334
  class UncorrelatedNoiseSource(SamplesGenerator):
1352
1335
  """Class to simulate white or pink noise as uncorrelated signal at each
1353
1336
  channel.
@@ -1358,49 +1341,30 @@ class UncorrelatedNoiseSource(SamplesGenerator):
1358
1341
  #: Type of noise to generate at the channels.
1359
1342
  #: The `~acoular.signals.SignalGenerator`-derived class has to
1360
1343
  # feature the parameter "seed" (i.e. white or pink noise).
1361
- signal = Trait(SignalGenerator, desc='type of noise')
1344
+ signal = Instance(NoiseGenerator, desc='type of noise')
1362
1345
 
1363
1346
  #: Array with seeds for random number generator.
1364
- #: When left empty, arange(:attr:`numchannels`) + :attr:`signal`.seed
1347
+ #: When left empty, arange(:attr:`num_channels`) + :attr:`signal`.seed
1365
1348
  #: will be used.
1366
1349
  seed = CArray(dtype=uint32, desc='random seed values')
1367
1350
 
1368
1351
  #: Number of channels in output; is set automatically /
1369
1352
  #: depends on used microphone geometry.
1370
- numchannels = Delegate('mics', 'num_mics')
1353
+ num_channels = Delegate('mics', 'num_mics')
1371
1354
 
1372
1355
  #: :class:`~acoular.microphones.MicGeom` object that provides the microphone locations.
1373
- mics = Trait(MicGeom, desc='microphone geometry')
1374
-
1375
- # --- List of backwards compatibility traits and their setters/getters -----------
1376
-
1377
- # Microphone locations.
1378
- # Deprecated! Use :attr:`mics` trait instead.
1379
- mpos = Property()
1380
-
1381
- def _get_mpos(self):
1382
- return self.mics
1383
-
1384
- def _set_mpos(self, mpos):
1385
- msg = (
1386
- "Deprecated use of 'mpos' trait. Use 'mics' trait instead."
1387
- "The 'mpos' trait will be removed in version 25.01."
1388
- )
1389
- warn(msg, DeprecationWarning, stacklevel=2)
1390
- self.mics = mpos
1391
-
1392
- # --- End of backwards compatibility traits --------------------------------------
1356
+ mics = Instance(MicGeom, desc='microphone geometry')
1393
1357
 
1394
1358
  #: Start time of the signal in seconds, defaults to 0 s.
1395
1359
  start_t = Float(0.0, desc='signal start time')
1396
1360
 
1397
- #: Start time of the data aquisition at microphones in seconds,
1361
+ #: Start time of the data acquisition at microphones in seconds,
1398
1362
  #: defaults to 0 s.
1399
1363
  start = Float(0.0, desc='sample start time')
1400
1364
 
1401
1365
  #: Number of samples is set automatically /
1402
1366
  #: depends on :attr:`signal`.
1403
- numsamples = Delegate('signal')
1367
+ num_samples = Delegate('signal')
1404
1368
 
1405
1369
  #: Sampling frequency of the signal; is set automatically /
1406
1370
  #: depends on :attr:`signal`.
@@ -1410,15 +1374,11 @@ class UncorrelatedNoiseSource(SamplesGenerator):
1410
1374
  digest = Property(
1411
1375
  depends_on=[
1412
1376
  'mics.digest',
1413
- 'signal.rms',
1414
- 'signal.numsamples',
1415
- 'signal.sample_freq',
1416
- 'signal.__class__',
1377
+ 'signal.digest',
1417
1378
  'seed',
1418
1379
  'loc',
1419
1380
  'start_t',
1420
1381
  'start',
1421
- '__class__',
1422
1382
  ],
1423
1383
  )
1424
1384
 
@@ -1437,41 +1397,39 @@ class UncorrelatedNoiseSource(SamplesGenerator):
1437
1397
 
1438
1398
  Returns
1439
1399
  -------
1440
- Samples in blocks of shape (num, numchannels).
1400
+ Samples in blocks of shape (num, num_channels).
1441
1401
  The last block may be shorter than num.
1442
1402
 
1443
1403
  """
1444
1404
  Noise = self.signal.__class__
1445
1405
  # create or get the array of random seeds
1446
- if not self.seed:
1447
- seed = arange(self.numchannels) + self.signal.seed
1448
- 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,):
1449
1409
  seed = self.seed
1450
1410
  else:
1451
- raise ValueError(
1452
- 'Seed array expected to be of shape (%i,), but has shape %s.'
1453
- % (self.numchannels, str(self.seed.shape)),
1454
- )
1455
-
1456
- # 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
1457
1414
  signal = array(
1458
1415
  [
1459
- 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()
1460
1417
  for s in seed
1461
1418
  ],
1462
1419
  ).T
1463
1420
 
1464
1421
  n = num
1465
- while n <= self.numsamples:
1422
+ while n <= self.num_samples:
1466
1423
  yield signal[n - num : n, :]
1467
1424
  n += num
1468
1425
  else:
1469
- if (n - num) < self.numsamples:
1426
+ if (n - num) < self.num_samples:
1470
1427
  yield signal[n - num :, :]
1471
1428
  else:
1472
1429
  return
1473
1430
 
1474
1431
 
1432
+ @deprecated_alias({'numchannels': 'num_channels', 'numsamples': 'num_samples'}, read_only=True)
1475
1433
  class SourceMixer(SamplesGenerator):
1476
1434
  """Mixes the signals from several sources."""
1477
1435
 
@@ -1483,10 +1441,10 @@ class SourceMixer(SamplesGenerator):
1483
1441
  sample_freq = Property(depends_on=['sdigest'])
1484
1442
 
1485
1443
  #: Number of channels.
1486
- numchannels = Property(depends_on=['sdigest'])
1444
+ num_channels = Property(depends_on=['sdigest'])
1487
1445
 
1488
1446
  #: Number of samples.
1489
- numsamples = Property(depends_on=['sdigest'])
1447
+ num_samples = Property(depends_on=['sdigest'])
1490
1448
 
1491
1449
  #: Amplitude weight(s) for the sources as array. If not set,
1492
1450
  #: all source signals are equally weighted.
@@ -1512,12 +1470,12 @@ class SourceMixer(SamplesGenerator):
1512
1470
  return self.sources[0].sample_freq if self.sources else 0
1513
1471
 
1514
1472
  @cached_property
1515
- def _get_numchannels(self):
1516
- 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
1517
1475
 
1518
1476
  @cached_property
1519
- def _get_numsamples(self):
1520
- 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
1521
1479
 
1522
1480
  def validate_sources(self):
1523
1481
  """Validates if sources fit together."""
@@ -1526,11 +1484,14 @@ class SourceMixer(SamplesGenerator):
1526
1484
  raise ValueError(msg)
1527
1485
  for s in self.sources[1:]:
1528
1486
  if self.sample_freq != s.sample_freq:
1529
- raise ValueError('Sample frequency of %s does not fit' % s)
1530
- if self.numchannels != s.numchannels:
1531
- raise ValueError('Channel count of %s does not fit' % s)
1532
- if self.numsamples != s.numsamples:
1533
- 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)
1534
1495
 
1535
1496
  def result(self, num):
1536
1497
  """Python generator that yields the output block-wise.
@@ -1544,7 +1505,7 @@ class SourceMixer(SamplesGenerator):
1544
1505
 
1545
1506
  Returns
1546
1507
  -------
1547
- Samples in blocks of shape (num, numchannels).
1508
+ Samples in blocks of shape (num, num_channels).
1548
1509
  The last block may be shorter than num.
1549
1510
 
1550
1511
  """
@@ -1570,10 +1531,10 @@ class SourceMixer(SamplesGenerator):
1570
1531
 
1571
1532
 
1572
1533
  class PointSourceConvolve(PointSource):
1573
- """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."""
1574
1535
 
1575
- #: Convolution kernel in the time domain.
1576
- #: 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`.
1577
1538
  #: If only a single kernel is supplied, it is applied to all channels.
1578
1539
  kernel = CArray(dtype=float, desc='Convolution kernel.')
1579
1540
 
@@ -1582,7 +1543,7 @@ class PointSourceConvolve(PointSource):
1582
1543
  #: Start time of the signal in seconds, defaults to 0 s.
1583
1544
  start_t = Enum(0.0, desc='signal start time')
1584
1545
 
1585
- #: Start time of the data aquisition at microphones in seconds,
1546
+ #: Start time of the data acquisition at microphones in seconds,
1586
1547
  #: defaults to 0 s.
1587
1548
  start = Enum(0.0, desc='sample start time')
1588
1549
 
@@ -1597,7 +1558,7 @@ class PointSourceConvolve(PointSource):
1597
1558
 
1598
1559
  # internal identifier
1599
1560
  digest = Property(
1600
- depends_on=['mics.digest', 'signal.digest', 'loc', 'kernel', '__class__'],
1561
+ depends_on=['mics.digest', 'signal.digest', 'loc', 'kernel'],
1601
1562
  )
1602
1563
 
1603
1564
  @cached_property
@@ -1615,7 +1576,7 @@ class PointSourceConvolve(PointSource):
1615
1576
 
1616
1577
  Returns
1617
1578
  -------
1618
- Samples in blocks of shape (num, numchannels).
1579
+ Samples in blocks of shape (num, num_channels).
1619
1580
  The last block may be shorter than num.
1620
1581
 
1621
1582
  """
@@ -1623,8 +1584,8 @@ class PointSourceConvolve(PointSource):
1623
1584
  source = TimeSamples(
1624
1585
  data=data,
1625
1586
  sample_freq=self.sample_freq,
1626
- numsamples=self.numsamples,
1627
- numchannels=self.mics.num_mics,
1587
+ num_samples=self.num_samples,
1588
+ num_channels=self.mics.num_mics,
1628
1589
  )
1629
1590
  time_convolve = TimeConvolve(
1630
1591
  source=source,