acoular 25.3.post1__py3-none-any.whl → 25.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
acoular/fbeamform.py CHANGED
@@ -170,6 +170,7 @@ class SteeringVector(HasStrictTraits):
170
170
  'true level': lambda x: x / einsum('ij,ij->i', x, x.conj())[:, newaxis],
171
171
  'true location': lambda x: x / sqrt(einsum('ij,ij->i', x, x.conj()) * x.shape[-1])[:, newaxis],
172
172
  },
173
+ transient=True,
173
174
  desc='dictionary of frequency domain steering vector functions',
174
175
  )
175
176
 
@@ -180,6 +181,7 @@ class SteeringVector(HasStrictTraits):
180
181
  'true level': _steer_III,
181
182
  'true location': _steer_IV,
182
183
  },
184
+ transient=True,
183
185
  desc='dictionary of time domain steering vector functions',
184
186
  )
185
187
 
@@ -290,7 +292,7 @@ class LazyBfResult:
290
292
  self.bf = bf
291
293
 
292
294
  def __getitem__(self, key):
293
- # 'intelligent' [] operator checks if results are available and triggers calculation
295
+ """'intelligent' [] operator, checks if results are available and triggers calculation."""
294
296
  sl = index_exp[key][0]
295
297
  if isinstance(sl, (int, integer)):
296
298
  sl = slice(sl, sl + 1)
@@ -660,18 +662,15 @@ class BeamformerBase(HasStrictTraits):
660
662
  msg,
661
663
  )
662
664
  gshape = self.steer.grid.shape
665
+ num_freqs = self.freq_data.fftfreq().shape[0]
663
666
  if num == 0 or frange is None:
664
667
  if frange is None:
665
668
  ind_low = self.freq_data.ind_low
666
669
  ind_high = self.freq_data.ind_high
667
670
  if ind_low is None:
668
671
  ind_low = 0
669
- if ind_low < 0:
670
- ind_low += self._numfreq
671
672
  if ind_high is None:
672
- ind_high = self._numfreq
673
- if ind_high < 0:
674
- ind_high += self._numfreq
673
+ ind_high = num_freqs
675
674
  irange = (ind_low, ind_high)
676
675
  num = 0
677
676
  elif len(frange) == 2:
@@ -681,10 +680,10 @@ class BeamformerBase(HasStrictTraits):
681
680
  raise TypeError(
682
681
  msg,
683
682
  )
684
- h = zeros(self._numfreq, dtype=float)
683
+ h = zeros(num_freqs, dtype=float)
685
684
  sl = slice(*irange)
686
685
  r = self.result[sl]
687
- for i in range(*irange):
686
+ for i in range(num_freqs)[sl]:
688
687
  # we do this per frequency because r might not have fancy indexing
689
688
  h[i] = r[i - sl.start].reshape(gshape)[ind].sum()
690
689
  if frange is None:
@@ -1146,14 +1145,6 @@ class BeamformerDamas(BeamformerBase):
1146
1145
  See :cite:`Brooks2006` for details.
1147
1146
  """
1148
1147
 
1149
- #: (only for backward compatibility) :class:`BeamformerBase` object
1150
- #: if set, provides :attr:`freq_data`, :attr:`steer`, :attr:`r_diag`
1151
- #: if not set, these have to be set explicitly.
1152
- beamformer = Property()
1153
-
1154
- # private storage of beamformer instance
1155
- _beamformer = Instance(BeamformerBase)
1156
-
1157
1148
  #: The floating-number-precision of the PSFs. Default is 64 bit.
1158
1149
  psf_precision = Enum('float64', 'float32', desc='precision of PSF')
1159
1150
 
@@ -1172,32 +1163,10 @@ class BeamformerDamas(BeamformerBase):
1172
1163
  depends_on=BEAMFORMER_BASE_DIGEST_DEPENDENCIES + ['n_iter', 'damp', 'psf_precision'],
1173
1164
  )
1174
1165
 
1175
- def _get_beamformer(self):
1176
- return self._beamformer
1177
-
1178
- def _set_beamformer(self, beamformer):
1179
- msg = (
1180
- f"Deprecated use of 'beamformer' trait in class {self.__class__.__name__}. "
1181
- 'Please set :attr:`freq_data`, :attr:`steer`, :attr:`r_diag` directly. '
1182
- "Using the 'beamformer' trait will be removed in version 25.07."
1183
- )
1184
- warn(
1185
- msg,
1186
- DeprecationWarning,
1187
- stacklevel=2,
1188
- )
1189
- self._beamformer = beamformer
1190
-
1191
1166
  @cached_property
1192
1167
  def _get_digest(self):
1193
1168
  return digest(self)
1194
1169
 
1195
- @on_trait_change('_beamformer.digest')
1196
- def delegate_beamformer_traits(self):
1197
- self.freq_data = self.beamformer.freq_data
1198
- self.r_diag = self.beamformer.r_diag
1199
- self.steer = self.beamformer.steer
1200
-
1201
1170
  def _calc(self, ind):
1202
1171
  """Calculates the result for the frequencies defined by :attr:`freq_data`.
1203
1172
 
@@ -1240,7 +1209,7 @@ class BeamformerDamas(BeamformerBase):
1240
1209
  self._fr[i] = 1
1241
1210
 
1242
1211
 
1243
- @deprecated_alias({'max_iter': 'n_iter'})
1212
+ @deprecated_alias({'max_iter': 'n_iter'}, removal_version='25.10')
1244
1213
  class BeamformerDamasPlus(BeamformerDamas):
1245
1214
  """DAMAS deconvolution :cite:`Brooks2006` for solving the system of equations, instead of the
1246
1215
  original Gauss-Seidel iterations, this class employs the NNLS or linear programming solvers from
@@ -1363,14 +1332,6 @@ class BeamformerOrth(BeamformerBase):
1363
1332
  New faster implementation without explicit (:class:`BeamformerEig`).
1364
1333
  """
1365
1334
 
1366
- #: (only for backward compatibility) :class:`BeamformerEig` object
1367
- #: if set, provides :attr:`freq_data`, :attr:`steer`, :attr:`r_diag`
1368
- #: if not set, these have to be set explicitly.
1369
- beamformer = Property()
1370
-
1371
- # private storage of beamformer instance
1372
- _beamformer = Instance(BeamformerEig)
1373
-
1374
1335
  #: List of components to consider, use this to directly set the eigenvalues
1375
1336
  #: used in the beamformer. Alternatively, set :attr:`n`.
1376
1337
  eva_list = CArray(dtype=int, value=array([-1]), desc='components')
@@ -1386,32 +1347,10 @@ class BeamformerOrth(BeamformerBase):
1386
1347
  depends_on=BEAMFORMER_BASE_DIGEST_DEPENDENCIES + ['eva_list'],
1387
1348
  )
1388
1349
 
1389
- def _get_beamformer(self):
1390
- return self._beamformer
1391
-
1392
- def _set_beamformer(self, beamformer):
1393
- msg = (
1394
- f"Deprecated use of 'beamformer' trait in class {self.__class__.__name__}. "
1395
- 'Please set :attr:`freq_data`, :attr:`steer`, :attr:`r_diag` directly. '
1396
- "Using the 'beamformer' trait will be removed in version 25.07."
1397
- )
1398
- warn(
1399
- msg,
1400
- DeprecationWarning,
1401
- stacklevel=2,
1402
- )
1403
- self._beamformer = beamformer
1404
-
1405
1350
  @cached_property
1406
1351
  def _get_digest(self):
1407
1352
  return digest(self)
1408
1353
 
1409
- @on_trait_change('_beamformer.digest')
1410
- def delegate_beamformer_traits(self):
1411
- self.freq_data = self.beamformer.freq_data
1412
- self.r_diag = self.beamformer.r_diag
1413
- self.steer = self.beamformer.steer
1414
-
1415
1354
  @on_trait_change('n')
1416
1355
  def set_eva_list(self):
1417
1356
  """Sets the list of eigenvalues to consider."""
@@ -1454,7 +1393,7 @@ class BeamformerOrth(BeamformerBase):
1454
1393
  self._fr[i] = 1
1455
1394
 
1456
1395
 
1457
- @deprecated_alias({'n': 'n_iter'})
1396
+ @deprecated_alias({'n': 'n_iter'}, removal_version='25.10')
1458
1397
  class BeamformerCleansc(BeamformerBase):
1459
1398
  """CLEAN-SC deconvolution algorithm.
1460
1399
 
@@ -1552,14 +1491,6 @@ class BeamformerClean(BeamformerBase):
1552
1491
  See :cite:`Hoegbom1974` for details.
1553
1492
  """
1554
1493
 
1555
- #: (only for backward compatibility) :class:`BeamformerBase` object
1556
- #: if set, provides :attr:`freq_data`, :attr:`steer`, :attr:`r_diag`
1557
- #: if not set, these have to be set explicitly.
1558
- beamformer = Property()
1559
-
1560
- # private storage of beamformer instance
1561
- _beamformer = Instance(BeamformerBase)
1562
-
1563
1494
  #: The floating-number-precision of the PSFs. Default is 64 bit.
1564
1495
  psf_precision = Enum('float64', 'float32', desc='precision of PSF.')
1565
1496
 
@@ -1582,28 +1513,6 @@ class BeamformerClean(BeamformerBase):
1582
1513
  def _get_digest(self):
1583
1514
  return digest(self)
1584
1515
 
1585
- def _get_beamformer(self):
1586
- return self._beamformer
1587
-
1588
- def _set_beamformer(self, beamformer):
1589
- msg = (
1590
- f"Deprecated use of 'beamformer' trait in class {self.__class__.__name__}. "
1591
- 'Please set :attr:`freq_data`, :attr:`steer`, :attr:`r_diag` directly. '
1592
- "Using the 'beamformer' trait will be removed in version 25.07."
1593
- )
1594
- warn(
1595
- msg,
1596
- DeprecationWarning,
1597
- stacklevel=2,
1598
- )
1599
- self._beamformer = beamformer
1600
-
1601
- @on_trait_change('_beamformer.digest')
1602
- def delegate_beamformer_traits(self):
1603
- self.freq_data = self.beamformer.freq_data
1604
- self.r_diag = self.beamformer.r_diag
1605
- self.steer = self.beamformer.steer
1606
-
1607
1516
  def _calc(self, ind):
1608
1517
  """Calculates the result for the frequencies defined by :attr:`freq_data`.
1609
1518
 
@@ -1666,7 +1575,7 @@ class BeamformerClean(BeamformerBase):
1666
1575
  self._fr[i] = 1
1667
1576
 
1668
1577
 
1669
- @deprecated_alias({'max_iter': 'n_iter'})
1578
+ @deprecated_alias({'max_iter': 'n_iter'}, removal_version='25.10')
1670
1579
  class BeamformerCMF(BeamformerBase):
1671
1580
  """Covariance Matrix Fitting algorithm.
1672
1581
 
@@ -1870,10 +1779,8 @@ class BeamformerCMF(BeamformerBase):
1870
1779
  factr=10000000.0,
1871
1780
  pgtol=1e-05,
1872
1781
  epsilon=1e-08,
1873
- iprint=-1,
1874
1782
  maxfun=15000,
1875
1783
  maxiter=self.n_iter,
1876
- disp=None,
1877
1784
  callback=None,
1878
1785
  maxls=20,
1879
1786
  )
@@ -1895,7 +1802,7 @@ class BeamformerCMF(BeamformerBase):
1895
1802
  self._fr[i] = 1
1896
1803
 
1897
1804
 
1898
- @deprecated_alias({'max_iter': 'n_iter'})
1805
+ @deprecated_alias({'max_iter': 'n_iter'}, removal_version='25.10')
1899
1806
  class BeamformerSODIX(BeamformerBase):
1900
1807
  """Source directivity modeling in the cross-spectral matrix (SODIX) algorithm.
1901
1808
 
@@ -2040,10 +1947,8 @@ class BeamformerSODIX(BeamformerBase):
2040
1947
  factr=100.0,
2041
1948
  pgtol=1e-12,
2042
1949
  epsilon=1e-08,
2043
- iprint=-1,
2044
1950
  maxfun=1500000,
2045
1951
  maxiter=self.n_iter,
2046
- disp=-1,
2047
1952
  callback=None,
2048
1953
  maxls=20,
2049
1954
  )
@@ -2054,7 +1959,7 @@ class BeamformerSODIX(BeamformerBase):
2054
1959
  self._fr[i] = 1
2055
1960
 
2056
1961
 
2057
- @deprecated_alias({'max_iter': 'n_iter'})
1962
+ @deprecated_alias({'max_iter': 'n_iter'}, removal_version='25.10')
2058
1963
  class BeamformerGIB(BeamformerEig): # BeamformerEig #BeamformerBase
2059
1964
  """Beamforming GIB methods with different normalizations.
2060
1965
 
acoular/fprocess.py CHANGED
@@ -11,11 +11,8 @@ Implements blockwise processing methods in the frequency domain.
11
11
  IRFFT
12
12
  AutoPowerSpectra
13
13
  CrossPowerSpectra
14
- FFTSpectra
15
14
  """
16
15
 
17
- from warnings import warn
18
-
19
16
  import numpy as np
20
17
  from scipy import fft
21
18
  from traits.api import Bool, CArray, Enum, Instance, Int, Property, Union, cached_property
@@ -29,7 +26,7 @@ from .process import SamplesBuffer
29
26
  from .spectra import BaseSpectra
30
27
 
31
28
 
32
- @deprecated_alias({'numfreqs': 'num_freqs', 'numsamples': 'num_samples'}, read_only=True)
29
+ @deprecated_alias({'numfreqs': 'num_freqs', 'numsamples': 'num_samples'}, read_only=True, removal_version='25.10')
33
30
  class RFFT(BaseSpectra, SpectraOut):
34
31
  """
35
32
  Compute the one-sided Fast Fourier Transform (FFT) for real-valued multichannel time data.
@@ -170,7 +167,7 @@ class RFFT(BaseSpectra, SpectraOut):
170
167
  yield fftdata[: j + 1]
171
168
 
172
169
 
173
- @deprecated_alias({'numsamples': 'num_samples'}, read_only=True)
170
+ @deprecated_alias({'numsamples': 'num_samples'}, read_only=True, removal_version='25.10')
174
171
  class IRFFT(TimeOut):
175
172
  """
176
173
  Perform the inverse Fast Fourier Transform (IFFT) for one-sided multi-channel spectra.
@@ -350,7 +347,7 @@ class AutoPowerSpectra(SpectraOut):
350
347
  yield ((temp * temp.conjugate()).real * scale).astype(self.precision)
351
348
 
352
349
 
353
- @deprecated_alias({'numchannels': 'num_channels'}, read_only=True)
350
+ @deprecated_alias({'numchannels': 'num_channels'}, read_only=True, removal_version='25.10')
354
351
  class CrossPowerSpectra(AutoPowerSpectra):
355
352
  """
356
353
  Compute the complex-valued auto- and cross-power spectra from frequency-domain data.
@@ -450,29 +447,3 @@ class CrossPowerSpectra(AutoPowerSpectra):
450
447
  csm_flat[i] = csm_lower[:, :nc].reshape(-1)
451
448
  csm_upper[...] = 0 # calcCSM adds cumulative
452
449
  yield csm_flat[: i + 1] * scale
453
-
454
-
455
- class FFTSpectra(RFFT):
456
- """
457
- Provide the one-sided Fast Fourier Transform (FFT) for multichannel time data.
458
-
459
- .. deprecated:: 24.10
460
- The :class:`~acoular.fprocess.FFTSpectra` class is deprecated and will be removed
461
- in Acoular version 25.07. Please use :class:`~acoular.fprocess.RFFT` instead.
462
-
463
- Alias for the :class:`~acoular.fprocess.RFFT` class, which computes the one-sided
464
- Fast Fourier Transform (FFT) for multichannel time data.
465
-
466
- Warnings
467
- --------
468
- This class remains temporarily available for backward compatibility but should not be used in
469
- new implementations.
470
- """
471
-
472
- def __init__(self, *args, **kwargs):
473
- super().__init__(*args, **kwargs)
474
- warn(
475
- 'Using FFTSpectra is deprecated and will be removed in Acoular version 25.07. Use class RFFT instead.',
476
- DeprecationWarning,
477
- stacklevel=2,
478
- )
acoular/grids.py CHANGED
@@ -28,6 +28,7 @@ Implement support for multidimensional grids and integration sectors.
28
28
  # imports from other packages
29
29
  import xml.dom.minidom
30
30
  from abc import abstractmethod
31
+ from pathlib import Path
31
32
 
32
33
  from numpy import (
33
34
  absolute,
@@ -301,7 +302,7 @@ class Polygon:
301
302
  return mindst
302
303
 
303
304
 
304
- @deprecated_alias({'gpos': 'pos'})
305
+ @deprecated_alias({'gpos': 'pos'}, removal_version='25.10')
305
306
  class Grid(ABCHasStrictTraits):
306
307
  """
307
308
  Abstract base class for grid geometries.
@@ -309,6 +310,16 @@ class Grid(ABCHasStrictTraits):
309
310
  This class defines a common interface for all grid geometries and provides tools to query grid
310
311
  properties and related data. It is intended to serve as a base class for specialized grid
311
312
  implementations and should not be instantiated directly as it lacks concrete functionality.
313
+
314
+ .. _units_note_grids:
315
+
316
+ Unit System
317
+ -----------
318
+ The source code is agnostic to the unit of length. The positions' coordinates are assumed to be
319
+ in meters. This is consistent with the standard :class:`~acoular.environments.Environment` class
320
+ which uses the speed of sound at 20°C at sea level under standard atmosphere pressure in m/s.
321
+ If the positions' coordinates are provided in a unit other than meter, it is advisable to change
322
+ the :attr:`~acoular.environments.Environment.c` attribute to match the given unit.
312
323
  """
313
324
 
314
325
  #: The total number of grid points. This property is automatically calculated based on other
@@ -321,6 +332,7 @@ class Grid(ABCHasStrictTraits):
321
332
 
322
333
  #: The grid positions represented as a (3, :attr:`size`) array of :class:`floats<float>`.
323
334
  #: (read-only)
335
+ #: All positions' coordinates are in meters by default (see :ref:`notes <units_note_grids>`).
324
336
  pos = Property(desc='x, y, z positions of grid points')
325
337
 
326
338
  #: A unique identifier for the grid, based on its properties. (read-only)
@@ -375,8 +387,77 @@ class Grid(ABCHasStrictTraits):
375
387
  # return indices of "True" entries
376
388
  return where(xyi)
377
389
 
390
+ def export_gpos(self, filename):
391
+ """
392
+ Export the grid positions to an XML file.
393
+
394
+ This method generates an XML file containing the positions of all grid points.
395
+ Each point is represented by a ``<pos>`` element with ``Name``, ``x``, ``y``, and ``z``
396
+ attributes. The generated XML is formatted to match the structure required for importing
397
+ into the :class:`ImportGrid` class.
398
+
399
+ Parameters
400
+ ----------
401
+ filename : :class:`str`
402
+ The path to the file to which the grid positions will be written. The file
403
+ extension must be ``.xml``.
404
+
405
+ Raises
406
+ ------
407
+ :obj:`OSError`
408
+ If the file cannot be written due to permissions issues or invalid file paths.
409
+
410
+ Notes
411
+ -----
412
+ - The file will be saved in UTF-8 encoding.
413
+ - The ``Name`` attribute for each point is set as ``"Point {i+1}"``, where ``i`` is the
414
+ index of the grid point.
415
+ - If subgrids are defined, they will be included as the ``subgrid`` attribute.
416
+
417
+ Examples
418
+ --------
419
+ Export a grid with 100 points to an XML file:
420
+
421
+ >>> import acoular as ac
422
+ >>> import numpy as np
423
+ >>> grid = ac.ImportGrid()
424
+ >>> # Create some grid points
425
+ >>> points = np.arange(9).reshape(3, 3)
426
+ >>> grid.pos = points
427
+ >>> grid.export_gpos('grid_points.xml') # doctest: +SKIP
428
+
429
+ The generated ``grid_points.xml`` file will look like this:
430
+
431
+ .. code-block:: xml
378
432
 
379
- @deprecated_alias({'gpos': 'pos'}, read_only=True)
433
+ <?xml version="1.1" encoding="utf-8"?><Grid name="grid_points">
434
+ <pos Name="Point 1" x="0" y="1" z="2"/>
435
+ <pos Name="Point 2" x="3" y="4" z="5"/>
436
+ <pos Name="Point 3" x="6" y="7" z="8"/>
437
+ </Grid>
438
+ """
439
+ filepath = Path(filename)
440
+ basename = filepath.stem
441
+ with filepath.open('w', encoding='utf-8') as f:
442
+ f.write(f'<?xml version="1.1" encoding="utf-8"?><Grid name="{basename}">\n')
443
+ for i in range(self.pos.shape[-1]):
444
+ has_subgrids = hasattr(self, 'subgrids') and len(self.subgrids) > i
445
+ subgrid_attr = f'subgrid="{self.subgrids[i]}"' if has_subgrids else ''
446
+ pos_str = ' '.join(
447
+ [
448
+ ' <pos',
449
+ f'Name="Point {i+1}"',
450
+ f'x="{self.pos[0, i]}"',
451
+ f'y="{self.pos[1, i]}"',
452
+ f'z="{self.pos[2, i]}"',
453
+ f'{subgrid_attr}/>\n',
454
+ ]
455
+ )
456
+ f.write(pos_str)
457
+ f.write('</Grid>')
458
+
459
+
460
+ @deprecated_alias({'gpos': 'pos'}, read_only=True, removal_version='25.10')
380
461
  class RectGrid(Grid):
381
462
  """
382
463
  Provides a 2D Cartesian grid for beamforming results.
@@ -409,6 +490,9 @@ class RectGrid(Grid):
409
490
  #: Number of grid points along y-axis. (read-only)
410
491
  nysteps = Property(desc='number of grid points along y-axis')
411
492
 
493
+ #: The grid's extension in :obj:`matplotlib.pyplot.imshow` compatible form. (read-only)
494
+ extent = Property(desc='grid extent as (x_min, x_max, y_min, y_max)')
495
+
412
496
  #: A unique identifier for the grid, based on its properties. (read-only)
413
497
  digest = Property(
414
498
  depends_on=['x_min', 'x_max', 'y_min', 'y_max', 'z', 'increment'],
@@ -450,6 +534,56 @@ class RectGrid(Grid):
450
534
  bpos.resize((3, self.size))
451
535
  return bpos
452
536
 
537
+ @property_depends_on(['x_min', 'x_max', 'y_min', 'y_max'])
538
+ def _get_extent(self):
539
+ # Return the grid's extension in :obj:`matplotlib.pyplot.imshow` compatible form.
540
+ #
541
+ # Returns
542
+ # -------
543
+ # :class:`tuple` of :class:`floats<float>`
544
+ # (:attr:`x_min`, :attr:`x_max`, :attr:`y_min`, :attr:`y_max`) representing the grid's
545
+ # extent.
546
+ #
547
+ # Notes
548
+ # -----
549
+ # This property is intended for use with the ``extent`` parameter of
550
+ # :obj:`matplotlib.pyplot.imshow`.
551
+ #
552
+ # Examples
553
+ # --------
554
+ # >>> from acoular import RectGrid
555
+ # >>> grid = RectGrid()
556
+ # >>> grid.y_min = -5
557
+ # >>> grid.y_max = 5
558
+ # >>> grid.extent
559
+ # (-1.0, 1.0, -5.0, 5.0)
560
+ return (self.x_min, self.x_max, self.y_min, self.y_max)
561
+
562
+ def extend(self):
563
+ """
564
+ Return the grid's extension in :obj:`matplotlib.pyplot.imshow` compatible form.
565
+
566
+ Returns
567
+ -------
568
+ :class:`tuple` of :class:`floats<float>`
569
+ (:attr:`x_min`, :attr:`x_max`, :attr:`y_min`, :attr:`y_max`) representing the grid's
570
+ extent.
571
+
572
+ Notes
573
+ -----
574
+ This method is deprecated. Use the :attr:`extent` property instead.
575
+ """
576
+ import warnings
577
+
578
+ msg = ' '.join(
579
+ [
580
+ "Deprecated use of 'extend' method (will be removed in version 26.04).",
581
+ "Please use the 'extent' trait instead.",
582
+ ]
583
+ )
584
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
585
+ return self.extent
586
+
453
587
  def index(self, x, y):
454
588
  """
455
589
  Find the indices of a grid point near a given coordinate.
@@ -539,34 +673,6 @@ class RectGrid(Grid):
539
673
  return array(xis), array(yis)
540
674
  # return arange(self.size)[inds]
541
675
 
542
- def extend(self):
543
- """
544
- Return the grid's extension in :obj:`matplotlib.pyplot.imshow` compatible form.
545
-
546
- Returns
547
- -------
548
- :class:`tuple` of :class:`floats<float>`
549
- (:attr:`x_min`, :attr:`x_max`, :attr:`y_min`, :attr:`y_max`) representing the grid's
550
- extent.
551
-
552
- Notes
553
- -----
554
- - ``pylab.imhow`` is the same as :obj:`matplotlib.pyplot.imshow`. It's only using a
555
- different namespace.
556
- - The return of the method is ment for the ``extent`` parameter of
557
- :obj:`matplotlib.pyplot.imshow`.
558
-
559
- Examples
560
- --------
561
- >>> from acoular import RectGrid
562
- >>> grid = RectGrid()
563
- >>> grid.y_min = -5
564
- >>> grid.y_max = 5
565
- >>> grid.extend()
566
- (-1.0, 1.0, -5.0, 5.0)
567
- """
568
- return (self.x_min, self.x_max, self.y_min, self.y_max)
569
-
570
676
 
571
677
  class RectGrid3D(RectGrid):
572
678
  """
@@ -575,10 +681,10 @@ class RectGrid3D(RectGrid):
575
681
  The grid has cubic or nearly cubic cells. It is defined by lower and upper x-, y- and z-limits.
576
682
  """
577
683
 
578
- #: The lower z-limit that defines the grid. Default is ``-1``.
684
+ #: The lower z-limit that defines the grid. Default is ``-1.0``.
579
685
  z_min = Float(-1.0, desc='minimum z-value')
580
686
 
581
- #: The upper z-limit that defines the grid. Default is ``1``.
687
+ #: The upper z-limit that defines the grid. Default is ``1.0``.
582
688
  z_max = Float(1.0, desc='maximum z-value')
583
689
 
584
690
  #: Number of grid points along x-axis. (read-only)
@@ -760,7 +866,7 @@ class RectGrid3D(RectGrid):
760
866
  return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1], s_[zi1 : zi2 + 1]
761
867
 
762
868
 
763
- @deprecated_alias({'from_file': 'file', 'gpos_file': 'pos'})
869
+ @deprecated_alias({'from_file': 'file', 'gpos_file': 'pos'}, removal_version='25.10')
764
870
  class ImportGrid(Grid):
765
871
  """
766
872
  Load a 3D grid from an XML file.
@@ -770,7 +876,7 @@ class ImportGrid(Grid):
770
876
  """
771
877
 
772
878
  #: Name of the .xml-file from which to read the data.
773
- file = File(filter=['*.xml'], exists=True, desc='name of the xml file to import')
879
+ file = Union(None, File(filter=['*.xml'], exists=True), desc='name of the xml file to import')
774
880
 
775
881
  _gpos = CArray(dtype=float, desc='x, y, z position of all Grid Points')
776
882
 
@@ -928,7 +1034,7 @@ class ImportGrid(Grid):
928
1034
  self.subgrids = array(names)
929
1035
 
930
1036
 
931
- @deprecated_alias({'gpos': 'pos', 'numpoints': 'num_points'}, read_only=['gpos'])
1037
+ @deprecated_alias({'gpos': 'pos', 'numpoints': 'num_points'}, read_only=['gpos'], removal_version='25.10')
932
1038
  class LineGrid(Grid):
933
1039
  """
934
1040
  Define a 3D grid for a line geometry.
@@ -976,8 +1082,9 @@ class LineGrid(Grid):
976
1082
  #: are set. (read-only)
977
1083
  size = Property(desc='overall number of grid points')
978
1084
 
979
- #: A (3, :attr:`size`) array containing the x, y, and z positions
980
- #: of the grid points. (read-only)
1085
+ #: A (3, :attr:`size`) array containing the x, y, and z positions of the grid points.
1086
+ #: (read-only)
1087
+ #: All positions' coordinates are in meters by default (see :ref:`notes <units_note_grids>`).
981
1088
  pos = Property(desc='x, y, z positions of grid points')
982
1089
 
983
1090
  #: A unique identifier for the grid, based on its properties. (read-only)
@@ -1008,7 +1115,7 @@ class LineGrid(Grid):
1008
1115
  return pos.T
1009
1116
 
1010
1117
 
1011
- @deprecated_alias({'gpos': 'pos'}, read_only=True)
1118
+ @deprecated_alias({'gpos': 'pos'}, read_only=True, removal_version='25.10')
1012
1119
  class MergeGrid(Grid):
1013
1120
  """
1014
1121
  Base class for merging multiple grid geometries.
acoular/h5cache.py CHANGED
@@ -2,7 +2,8 @@
2
2
  # Copyright (c) Acoular Development Team.
3
3
  # ------------------------------------------------------------------------------
4
4
 
5
- # imports from other packages
5
+ """Implements a cache for HDF5 files used in Acoular."""
6
+
6
7
  import gc
7
8
  from pathlib import Path
8
9
  from weakref import WeakValueDictionary
@@ -92,10 +93,11 @@ class HDF5Cache(HasStrictTraits):
92
93
  return # cachefile is not created in readonly mode
93
94
 
94
95
  if isinstance(obj.h5f, file_cls):
95
- if Path(obj.h5f.filename).resolve() == filename:
96
+ h5filename = Path(obj.h5f.filename).resolve()
97
+ if h5filename == filename:
96
98
  self.busy = False
97
99
  return
98
- self._decrease_file_reference_counter(obj.h5f.filename)
100
+ self._decrease_file_reference_counter(h5filename)
99
101
 
100
102
  if filename not in self.open_files: # or tables.file._open_files.filenames
101
103
  if config.global_caching == 'readonly':
acoular/h5files.py CHANGED
@@ -2,6 +2,8 @@
2
2
  # Copyright (c) Acoular Development Team.
3
3
  # ------------------------------------------------------------------------------
4
4
 
5
+ """Implements base classes for handling HDF5 files."""
6
+
5
7
  from .configuration import config
6
8
 
7
9
 
@@ -57,6 +59,8 @@ if config.have_tables:
57
59
  }
58
60
 
59
61
  class H5FileTables(H5FileBase, tables.File):
62
+ """Hdf5 File based on PyTables."""
63
+
60
64
  def create_extendable_array(self, nodename, shape, precision, group=None):
61
65
  if not group:
62
66
  group = self.root
@@ -106,6 +110,8 @@ if config.have_tables:
106
110
  return result
107
111
 
108
112
  class H5CacheFileTables(H5FileTables, H5CacheFileBase):
113
+ """Hdf5 Cache File based on PyTables."""
114
+
109
115
  compression_filter = tables.Filters(complevel=5, complib='blosc')
110
116
 
111
117
  def is_cached(self, nodename, group=None):
@@ -124,6 +130,8 @@ if config.have_h5py:
124
130
  import h5py
125
131
 
126
132
  class H5FileH5py(H5FileBase, h5py.File):
133
+ """Hdf5 File based on h5py."""
134
+
127
135
  def _get_in_file_path(self, nodename, group=None):
128
136
  if not group:
129
137
  return '/' + nodename
@@ -182,6 +190,8 @@ if config.have_h5py:
182
190
  return result
183
191
 
184
192
  class H5CacheFileH5py(H5CacheFileBase, H5FileH5py):
193
+ """Hdf5 Cache File based on h5py."""
194
+
185
195
  compression_filter = 'lzf'
186
196
  # compression_filter = 'blosc' # unavailable...
187
197