acoular 25.7__py3-none-any.whl → 25.10__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/aiaa/aiaa.py +7 -9
- acoular/base.py +6 -9
- acoular/calib.py +19 -18
- acoular/configuration.py +2 -2
- acoular/environments.py +102 -113
- acoular/fbeamform.py +296 -301
- acoular/fprocess.py +7 -4
- acoular/grids.py +98 -111
- acoular/h5cache.py +5 -1
- acoular/h5files.py +96 -9
- acoular/microphones.py +22 -27
- acoular/process.py +7 -11
- acoular/sdinput.py +0 -5
- acoular/signals.py +29 -27
- acoular/sources.py +189 -322
- acoular/spectra.py +33 -44
- acoular/tbeamform.py +217 -199
- acoular/tools/helpers.py +25 -33
- acoular/tools/metrics.py +5 -10
- acoular/tprocess.py +173 -209
- acoular/trajectory.py +5 -5
- acoular/version.py +2 -2
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/METADATA +6 -2
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/RECORD +27 -27
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/WHEEL +0 -0
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/licenses/AUTHORS.rst +0 -0
- {acoular-25.7.dist-info → acoular-25.10.dist-info}/licenses/LICENSE +0 -0
acoular/fprocess.py
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
"""
|
|
5
5
|
Implements blockwise processing methods in the frequency domain.
|
|
6
6
|
|
|
7
|
+
.. inheritance-diagram::
|
|
8
|
+
acoular.fprocess
|
|
9
|
+
:top-classes:
|
|
10
|
+
acoular.base.Generator,
|
|
11
|
+
acoular.spectra.BaseSpectra
|
|
12
|
+
:parts: 1
|
|
13
|
+
|
|
7
14
|
.. autosummary::
|
|
8
15
|
:toctree: generated/
|
|
9
16
|
|
|
@@ -19,14 +26,12 @@ from traits.api import Bool, CArray, Enum, Instance, Int, Property, Union, cache
|
|
|
19
26
|
|
|
20
27
|
# acoular imports
|
|
21
28
|
from .base import SamplesGenerator, SpectraGenerator, SpectraOut, TimeOut
|
|
22
|
-
from .deprecation import deprecated_alias
|
|
23
29
|
from .fastFuncs import calcCSM
|
|
24
30
|
from .internal import digest
|
|
25
31
|
from .process import SamplesBuffer
|
|
26
32
|
from .spectra import BaseSpectra
|
|
27
33
|
|
|
28
34
|
|
|
29
|
-
@deprecated_alias({'numfreqs': 'num_freqs', 'numsamples': 'num_samples'}, read_only=True, removal_version='25.10')
|
|
30
35
|
class RFFT(BaseSpectra, SpectraOut):
|
|
31
36
|
"""
|
|
32
37
|
Compute the one-sided Fast Fourier Transform (FFT) for real-valued multichannel time data.
|
|
@@ -167,7 +172,6 @@ class RFFT(BaseSpectra, SpectraOut):
|
|
|
167
172
|
yield fftdata[: j + 1]
|
|
168
173
|
|
|
169
174
|
|
|
170
|
-
@deprecated_alias({'numsamples': 'num_samples'}, read_only=True, removal_version='25.10')
|
|
171
175
|
class IRFFT(TimeOut):
|
|
172
176
|
"""
|
|
173
177
|
Perform the inverse Fast Fourier Transform (IFFT) for one-sided multi-channel spectra.
|
|
@@ -347,7 +351,6 @@ class AutoPowerSpectra(SpectraOut):
|
|
|
347
351
|
yield ((temp * temp.conjugate()).real * scale).astype(self.precision)
|
|
348
352
|
|
|
349
353
|
|
|
350
|
-
@deprecated_alias({'numchannels': 'num_channels'}, read_only=True, removal_version='25.10')
|
|
351
354
|
class CrossPowerSpectra(AutoPowerSpectra):
|
|
352
355
|
"""
|
|
353
356
|
Compute the complex-valued auto- and cross-power spectra from frequency-domain data.
|
acoular/grids.py
CHANGED
|
@@ -4,6 +4,24 @@
|
|
|
4
4
|
"""
|
|
5
5
|
Implement support for multidimensional grids and integration sectors.
|
|
6
6
|
|
|
7
|
+
.. inheritance-diagram::
|
|
8
|
+
acoular.grids.Grid
|
|
9
|
+
acoular.grids.RectGrid
|
|
10
|
+
acoular.grids.RectGrid3D
|
|
11
|
+
acoular.grids.ImportGrid
|
|
12
|
+
acoular.grids.LineGrid
|
|
13
|
+
acoular.grids.MergeGrid
|
|
14
|
+
:top-classes:
|
|
15
|
+
acoular.grids.Grid
|
|
16
|
+
:parts: 1
|
|
17
|
+
|
|
18
|
+
.. inheritance-diagram::
|
|
19
|
+
acoular.grids.Sector
|
|
20
|
+
:include-subclasses:
|
|
21
|
+
:top-classes:
|
|
22
|
+
acoular.grids.Sector
|
|
23
|
+
:parts: 1
|
|
24
|
+
|
|
7
25
|
.. autosummary::
|
|
8
26
|
:toctree: generated/
|
|
9
27
|
|
|
@@ -30,31 +48,8 @@ import xml.dom.minidom
|
|
|
30
48
|
from abc import abstractmethod
|
|
31
49
|
from pathlib import Path
|
|
32
50
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
append,
|
|
36
|
-
arange,
|
|
37
|
-
argmin,
|
|
38
|
-
array,
|
|
39
|
-
asarray,
|
|
40
|
-
concatenate,
|
|
41
|
-
copysign,
|
|
42
|
-
fabs,
|
|
43
|
-
inf,
|
|
44
|
-
isscalar,
|
|
45
|
-
ma,
|
|
46
|
-
mgrid,
|
|
47
|
-
newaxis,
|
|
48
|
-
ones,
|
|
49
|
-
ones_like,
|
|
50
|
-
s_,
|
|
51
|
-
sum, # noqa: A004
|
|
52
|
-
tile,
|
|
53
|
-
unique,
|
|
54
|
-
where,
|
|
55
|
-
zeros,
|
|
56
|
-
)
|
|
57
|
-
from scipy.linalg import norm
|
|
51
|
+
import numpy as np
|
|
52
|
+
import scipy.linalg as spla
|
|
58
53
|
|
|
59
54
|
# from matplotlib.path import Path
|
|
60
55
|
from scipy.spatial import Delaunay
|
|
@@ -73,13 +68,11 @@ from traits.api import (
|
|
|
73
68
|
Union,
|
|
74
69
|
cached_property,
|
|
75
70
|
observe,
|
|
76
|
-
on_trait_change,
|
|
77
71
|
property_depends_on,
|
|
78
72
|
)
|
|
79
73
|
from traits.trait_errors import TraitError
|
|
80
74
|
|
|
81
75
|
# acoular imports
|
|
82
|
-
from .deprecation import deprecated_alias
|
|
83
76
|
from .internal import digest, ldigest
|
|
84
77
|
|
|
85
78
|
|
|
@@ -136,11 +129,11 @@ def in_hull(p, hull, border=True, tol=0):
|
|
|
136
129
|
|
|
137
130
|
|
|
138
131
|
def _det(xvert, yvert):
|
|
139
|
-
xvert = asarray(xvert, dtype=float)
|
|
140
|
-
yvert = asarray(yvert, dtype=float)
|
|
141
|
-
x_prev = concatenate(([xvert[-1]], xvert[:-1]))
|
|
142
|
-
y_prev = concatenate(([yvert[-1]], yvert[:-1]))
|
|
143
|
-
return sum(yvert * x_prev - xvert * y_prev, axis=0)
|
|
132
|
+
xvert = np.asarray(xvert, dtype=float)
|
|
133
|
+
yvert = np.asarray(yvert, dtype=float)
|
|
134
|
+
x_prev = np.concatenate(([xvert[-1]], xvert[:-1]))
|
|
135
|
+
y_prev = np.concatenate(([yvert[-1]], yvert[:-1]))
|
|
136
|
+
return np.sum(yvert * x_prev - xvert * y_prev, axis=0)
|
|
144
137
|
|
|
145
138
|
|
|
146
139
|
class Polygon:
|
|
@@ -174,14 +167,14 @@ class Polygon:
|
|
|
174
167
|
if len(x) != len(y):
|
|
175
168
|
msg = 'x and y must be equally sized.'
|
|
176
169
|
raise IndexError(msg)
|
|
177
|
-
self.x = asarray(x, dtype=float)
|
|
178
|
-
self.y = asarray(y, dtype=float)
|
|
170
|
+
self.x = np.asarray(x, dtype=float)
|
|
171
|
+
self.y = np.asarray(y, dtype=float)
|
|
179
172
|
# Closes the polygon if were open
|
|
180
173
|
x1, y1 = x[0], y[0]
|
|
181
174
|
xn, yn = x[-1], y[-1]
|
|
182
175
|
if x1 != xn or y1 != yn:
|
|
183
|
-
self.x = concatenate((self.x, [x1]))
|
|
184
|
-
self.y = concatenate((self.y, [y1]))
|
|
176
|
+
self.x = np.concatenate((self.x, [x1]))
|
|
177
|
+
self.y = np.concatenate((self.y, [y1]))
|
|
185
178
|
# Anti-clockwise coordinates
|
|
186
179
|
if _det(self.x, self.y) < 0:
|
|
187
180
|
self.x = self.x[::-1]
|
|
@@ -217,12 +210,12 @@ class Polygon:
|
|
|
217
210
|
The method uses an improved algorithm based on Nordbeck and Rydstedt for determining
|
|
218
211
|
whether a point is inside a polygon :cite:`SLOAN198545`.
|
|
219
212
|
"""
|
|
220
|
-
xpoint = asarray(xpoint, dtype=float)
|
|
221
|
-
ypoint = asarray(ypoint, dtype=float)
|
|
213
|
+
xpoint = np.asarray(xpoint, dtype=float)
|
|
214
|
+
ypoint = np.asarray(ypoint, dtype=float)
|
|
222
215
|
# Scalar to array
|
|
223
216
|
if xpoint.shape == ():
|
|
224
|
-
xpoint = array([xpoint], dtype=float)
|
|
225
|
-
ypoint = array([ypoint], dtype=float)
|
|
217
|
+
xpoint = np.array([xpoint], dtype=float)
|
|
218
|
+
ypoint = np.array([ypoint], dtype=float)
|
|
226
219
|
scalar = True
|
|
227
220
|
else:
|
|
228
221
|
scalar = False
|
|
@@ -232,16 +225,16 @@ class Polygon:
|
|
|
232
225
|
raise IndexError(msg)
|
|
233
226
|
# If snear = True: Dist to nearest side < nearest vertex
|
|
234
227
|
# If snear = False: Dist to nearest vertex < nearest side
|
|
235
|
-
snear = ma.masked_all(xpoint.shape, dtype=bool)
|
|
228
|
+
snear = np.ma.masked_all(xpoint.shape, dtype=bool)
|
|
236
229
|
# Initialize arrays
|
|
237
|
-
mindst = ones_like(xpoint, dtype=float) * inf
|
|
238
|
-
j = ma.masked_all(xpoint.shape, dtype=int)
|
|
230
|
+
mindst = np.ones_like(xpoint, dtype=float) * np.inf
|
|
231
|
+
j = np.ma.masked_all(xpoint.shape, dtype=int)
|
|
239
232
|
x = self.x
|
|
240
233
|
y = self.y
|
|
241
234
|
n = len(x) - 1 # Number of sides/vertices defining the polygon
|
|
242
235
|
# Loop over each side defining polygon
|
|
243
236
|
for i in range(n):
|
|
244
|
-
d = ones_like(xpoint, dtype=float) * inf
|
|
237
|
+
d = np.ones_like(xpoint, dtype=float) * np.inf
|
|
245
238
|
# Start of side has coords (x1, y1)
|
|
246
239
|
# End of side has coords (x2, y2)
|
|
247
240
|
# Point has coords (xpoint, ypoint)
|
|
@@ -276,7 +269,7 @@ class Polygon:
|
|
|
276
269
|
snear[mask & tlt0] = False
|
|
277
270
|
# Point is closer to this side than to any other side or vertex
|
|
278
271
|
snear[mask & tle1] = True
|
|
279
|
-
if ma.count(snear) != snear.size:
|
|
272
|
+
if np.ma.count(snear) != snear.size:
|
|
280
273
|
msg = 'Error computing distances'
|
|
281
274
|
raise IndexError(msg)
|
|
282
275
|
mindst **= 0.5
|
|
@@ -287,22 +280,21 @@ class Polygon:
|
|
|
287
280
|
jo = j.copy()
|
|
288
281
|
jo[j == 0] -= 1
|
|
289
282
|
area = _det([x[j + 1], x[j], x[jo - 1]], [y[j + 1], y[j], y[jo - 1]])
|
|
290
|
-
mindst[~snear] = copysign(mindst, area)[~snear]
|
|
283
|
+
mindst[~snear] = np.copysign(mindst, area)[~snear]
|
|
291
284
|
# Point is closer to its nearest side than to its nearest vertex, check
|
|
292
285
|
# if point is to left or right of this side.
|
|
293
286
|
# If point is to left of side it is inside polygon, else point is
|
|
294
287
|
# outside polygon.
|
|
295
288
|
area = _det([x[j], x[j + 1], xpoint], [y[j], y[j + 1], ypoint])
|
|
296
|
-
mindst[snear] = copysign(mindst, area)[snear]
|
|
289
|
+
mindst[snear] = np.copysign(mindst, area)[snear]
|
|
297
290
|
# Point is on side of polygon
|
|
298
|
-
mindst[fabs(mindst) < smalld] = 0
|
|
291
|
+
mindst[np.fabs(mindst) < smalld] = 0
|
|
299
292
|
# If input values were scalar then the output should be too
|
|
300
293
|
if scalar:
|
|
301
294
|
mindst = float(mindst)
|
|
302
295
|
return mindst
|
|
303
296
|
|
|
304
297
|
|
|
305
|
-
@deprecated_alias({'gpos': 'pos'}, removal_version='25.10')
|
|
306
298
|
class Grid(ABCHasStrictTraits):
|
|
307
299
|
"""
|
|
308
300
|
Abstract base class for grid geometries.
|
|
@@ -312,14 +304,13 @@ class Grid(ABCHasStrictTraits):
|
|
|
312
304
|
implementations and should not be instantiated directly as it lacks concrete functionality.
|
|
313
305
|
|
|
314
306
|
.. _units_note_grids:
|
|
307
|
+
.. admonition:: Unit of length
|
|
315
308
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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.
|
|
309
|
+
The source code is agnostic to the unit of length. The positions' coordinates are assumed to
|
|
310
|
+
be in meters. This is consistent with the standard :class:`~acoular.environments.Environment`
|
|
311
|
+
class which uses the speed of sound at 20°C at sea level under standard atmosphere pressure in
|
|
312
|
+
m/s. If the positions' coordinates are provided in a unit other than meter, it is advisable to
|
|
313
|
+
change the :attr:`~acoular.environments.Environment.c` attribute to match the given unit.
|
|
323
314
|
"""
|
|
324
315
|
|
|
325
316
|
#: The total number of grid points. This property is automatically calculated based on other
|
|
@@ -332,7 +323,7 @@ class Grid(ABCHasStrictTraits):
|
|
|
332
323
|
|
|
333
324
|
#: The grid positions represented as a (3, :attr:`size`) array of :class:`floats<float>`.
|
|
334
325
|
#: (read-only)
|
|
335
|
-
#: All positions' coordinates are in meters by default (
|
|
326
|
+
#: All positions' coordinates are in meters by default (:ref:`see here <units_note_grids>`).
|
|
336
327
|
pos = Property(desc='x, y, z positions of grid points')
|
|
337
328
|
|
|
338
329
|
#: A unique identifier for the grid, based on its properties. (read-only)
|
|
@@ -385,7 +376,7 @@ class Grid(ABCHasStrictTraits):
|
|
|
385
376
|
# construct grid-shaped array with "True" entries where sector is
|
|
386
377
|
xyi = sector.contains(xpos).reshape(self.shape)
|
|
387
378
|
# return indices of "True" entries
|
|
388
|
-
return where(xyi)
|
|
379
|
+
return np.where(xyi)
|
|
389
380
|
|
|
390
381
|
def export_gpos(self, filename):
|
|
391
382
|
"""
|
|
@@ -457,7 +448,6 @@ class Grid(ABCHasStrictTraits):
|
|
|
457
448
|
f.write('</Grid>')
|
|
458
449
|
|
|
459
450
|
|
|
460
|
-
@deprecated_alias({'gpos': 'pos'}, read_only=True, removal_version='25.10')
|
|
461
451
|
class RectGrid(Grid):
|
|
462
452
|
"""
|
|
463
453
|
Provides a 2D Cartesian grid for beamforming results.
|
|
@@ -526,7 +516,7 @@ class RectGrid(Grid):
|
|
|
526
516
|
|
|
527
517
|
@property_depends_on(['x_min', 'x_max', 'y_min', 'y_max', 'increment'])
|
|
528
518
|
def _get_pos(self):
|
|
529
|
-
bpos = mgrid[
|
|
519
|
+
bpos = np.mgrid[
|
|
530
520
|
self.x_min : self.x_max : self.nxsteps * 1j,
|
|
531
521
|
self.y_min : self.y_max : self.nysteps * 1j,
|
|
532
522
|
self.z : self.z + 0.1,
|
|
@@ -642,36 +632,36 @@ class RectGrid(Grid):
|
|
|
642
632
|
dr2 = (xpos[0, :] - r[0]) ** 2 + (xpos[1, :] - r[1]) ** 2
|
|
643
633
|
# array with true/false entries
|
|
644
634
|
inds = dr2 <= r[2] ** 2
|
|
645
|
-
for
|
|
646
|
-
xi, yi = self.index(xpos[0,
|
|
635
|
+
for n_p in np.arange(self.size)[inds]: # n_p -- points in x2-circle
|
|
636
|
+
xi, yi = self.index(xpos[0, n_p], xpos[1, n_p])
|
|
647
637
|
xis += [xi]
|
|
648
638
|
yis += [yi]
|
|
649
639
|
if not (xis and yis): # if no points in circle, take nearest one
|
|
650
640
|
return self.index(r[0], r[1])
|
|
651
|
-
return array(xis), array(yis)
|
|
641
|
+
return np.array(xis), np.array(yis)
|
|
652
642
|
if len(r) == 4: # rectangular subdomain - old functionality
|
|
653
643
|
xi1, yi1 = self.index(min(r[0], r[2]), min(r[1], r[3]))
|
|
654
644
|
xi2, yi2 = self.index(max(r[0], r[2]), max(r[1], r[3]))
|
|
655
|
-
return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1]
|
|
645
|
+
return np.s_[xi1 : xi2 + 1], np.s_[yi1 : yi2 + 1]
|
|
656
646
|
xpos = self.pos
|
|
657
647
|
xis = []
|
|
658
648
|
yis = []
|
|
659
649
|
# replaced matplotlib Path by numpy
|
|
660
|
-
# p = Path(array(r).reshape(-1,2))
|
|
650
|
+
# p = Path(np.array(r).reshape(-1,2))
|
|
661
651
|
# inds = p.contains_points()
|
|
662
|
-
# inds = in_poly(xpos[:2,:].T,array(r).reshape(-1,2))
|
|
663
|
-
poly = Polygon(array(r).reshape(-1, 2)[:, 0], array(r).reshape(-1, 2)[:, 1])
|
|
652
|
+
# inds = in_poly(xpos[:2,:].T,np.array(r).reshape(-1,2))
|
|
653
|
+
poly = Polygon(np.array(r).reshape(-1, 2)[:, 0], np.array(r).reshape(-1, 2)[:, 1])
|
|
664
654
|
dists = poly.is_inside(xpos[0, :], xpos[1, :])
|
|
665
655
|
inds = dists >= 0
|
|
666
|
-
for
|
|
667
|
-
xi, yi = self.index(xpos[0,
|
|
656
|
+
for n_p in np.arange(self.size)[inds]: # n_p -- points in x2-circle
|
|
657
|
+
xi, yi = self.index(xpos[0, n_p], xpos[1, n_p])
|
|
668
658
|
xis += [xi]
|
|
669
659
|
yis += [yi]
|
|
670
660
|
if not (xis and yis): # if no points inside, take nearest to center
|
|
671
|
-
center = array(r).reshape(-1, 2).mean(0)
|
|
661
|
+
center = np.array(r).reshape(-1, 2).mean(0)
|
|
672
662
|
return self.index(center[0], center[1])
|
|
673
|
-
return array(xis), array(yis)
|
|
674
|
-
# return arange(self.size)[inds]
|
|
663
|
+
return np.array(xis), np.array(yis)
|
|
664
|
+
# return np.arange(self.size)[inds]
|
|
675
665
|
|
|
676
666
|
|
|
677
667
|
class RectGrid3D(RectGrid):
|
|
@@ -708,13 +698,13 @@ class RectGrid3D(RectGrid):
|
|
|
708
698
|
return self._increment
|
|
709
699
|
|
|
710
700
|
def _set_increment(self, increment):
|
|
711
|
-
if isscalar(increment):
|
|
701
|
+
if np.isscalar(increment):
|
|
712
702
|
try:
|
|
713
|
-
self._increment =
|
|
703
|
+
self._increment = np.abs(float(increment))
|
|
714
704
|
except ValueError as ve:
|
|
715
705
|
raise TraitError(args=self, name='increment', info='Float or CArray(3,)', value=increment) from ve
|
|
716
706
|
elif len(increment) == 3:
|
|
717
|
-
self._increment = array(increment, dtype=float)
|
|
707
|
+
self._increment = np.array(increment, dtype=float)
|
|
718
708
|
else:
|
|
719
709
|
raise (TraitError(args=self, name='increment', info='Float or CArray(3,)', value=increment))
|
|
720
710
|
|
|
@@ -733,28 +723,28 @@ class RectGrid3D(RectGrid):
|
|
|
733
723
|
|
|
734
724
|
@property_depends_on(['x_min', 'x_max', '_increment'])
|
|
735
725
|
def _get_nxsteps(self):
|
|
736
|
-
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[0])
|
|
726
|
+
i = abs(self.increment) if np.isscalar(self.increment) else abs(self.increment[0])
|
|
737
727
|
if i != 0:
|
|
738
728
|
return int(round((abs(self.x_max - self.x_min) + i) / i))
|
|
739
729
|
return 1
|
|
740
730
|
|
|
741
731
|
@property_depends_on(['y_min', 'y_max', '_increment'])
|
|
742
732
|
def _get_nysteps(self):
|
|
743
|
-
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[1])
|
|
733
|
+
i = abs(self.increment) if np.isscalar(self.increment) else abs(self.increment[1])
|
|
744
734
|
if i != 0:
|
|
745
735
|
return int(round((abs(self.y_max - self.y_min) + i) / i))
|
|
746
736
|
return 1
|
|
747
737
|
|
|
748
738
|
@property_depends_on(['z_min', 'z_max', '_increment'])
|
|
749
739
|
def _get_nzsteps(self):
|
|
750
|
-
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[2])
|
|
740
|
+
i = abs(self.increment) if np.isscalar(self.increment) else abs(self.increment[2])
|
|
751
741
|
if i != 0:
|
|
752
742
|
return int(round((abs(self.z_max - self.z_min) + i) / i))
|
|
753
743
|
return 1
|
|
754
744
|
|
|
755
745
|
@property_depends_on('digest')
|
|
756
746
|
def _get_pos(self):
|
|
757
|
-
bpos = mgrid[
|
|
747
|
+
bpos = np.mgrid[
|
|
758
748
|
self.x_min : self.x_max : self.nxsteps * 1j,
|
|
759
749
|
self.y_min : self.y_max : self.nysteps * 1j,
|
|
760
750
|
self.z_min : self.z_max : self.nzsteps * 1j,
|
|
@@ -810,7 +800,7 @@ class RectGrid3D(RectGrid):
|
|
|
810
800
|
if z < self.z_min or z > self.z_max:
|
|
811
801
|
msg = f'z-value out of range {z:f} ({self.z_min:f}, {self.z_max:f})'
|
|
812
802
|
raise ValueError(msg)
|
|
813
|
-
if isscalar(self.increment):
|
|
803
|
+
if np.isscalar(self.increment):
|
|
814
804
|
incx = incy = incz = self.increment
|
|
815
805
|
else:
|
|
816
806
|
incx, incy, incz = self.increment
|
|
@@ -863,10 +853,9 @@ class RectGrid3D(RectGrid):
|
|
|
863
853
|
"""
|
|
864
854
|
xi1, yi1, zi1 = self.index(min(x1, x2), min(y1, y2), min(z1, z2))
|
|
865
855
|
xi2, yi2, zi2 = self.index(max(x1, x2), max(y1, y2), max(z1, z2))
|
|
866
|
-
return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1], s_[zi1 : zi2 + 1]
|
|
856
|
+
return np.s_[xi1 : xi2 + 1], np.s_[yi1 : yi2 + 1], np.s_[zi1 : zi2 + 1]
|
|
867
857
|
|
|
868
858
|
|
|
869
|
-
@deprecated_alias({'from_file': 'file', 'gpos_file': 'pos'}, removal_version='25.10')
|
|
870
859
|
class ImportGrid(Grid):
|
|
871
860
|
"""
|
|
872
861
|
Load a 3D grid from an XML file.
|
|
@@ -906,8 +895,8 @@ class ImportGrid(Grid):
|
|
|
906
895
|
def _set_pos(self, pos):
|
|
907
896
|
self._gpos = pos
|
|
908
897
|
|
|
909
|
-
@
|
|
910
|
-
def
|
|
898
|
+
@observe('file')
|
|
899
|
+
def _import_pos(self, event): # noqa ARG002
|
|
911
900
|
"""
|
|
912
901
|
Import the grid point locations and subgrid names from an XML file.
|
|
913
902
|
|
|
@@ -924,14 +913,14 @@ class ImportGrid(Grid):
|
|
|
924
913
|
|
|
925
914
|
>>> import numpy as np
|
|
926
915
|
>>>
|
|
927
|
-
>>> # Grid 1: ten points
|
|
916
|
+
>>> # Grid 1: ten points arranged in a circle in the x-y plane at z=0
|
|
928
917
|
>>> args = 2 * np.pi * np.arange(10) / 10
|
|
929
918
|
>>> x1 = np.cos(args)
|
|
930
919
|
>>> y1 = np.sin(args)
|
|
931
920
|
>>> z1 = np.zeros_like(x1)
|
|
932
921
|
>>> grid1 = np.vstack([x1, y1, z1]).T
|
|
933
922
|
>>>
|
|
934
|
-
>>> # Grid 2: nine points
|
|
923
|
+
>>> # Grid 2: nine points arranged in a mesh grid in the x-y plane at z=1
|
|
935
924
|
>>> a = np.linspace(-1, 1, 3)
|
|
936
925
|
>>> x2, y2 = np.meshgrid(a, a)
|
|
937
926
|
>>> z2 = np.ones_like(x2)
|
|
@@ -1030,11 +1019,10 @@ class ImportGrid(Grid):
|
|
|
1030
1019
|
for el in doc.getElementsByTagName('pos'):
|
|
1031
1020
|
names.append(el.getAttribute('subgrid'))
|
|
1032
1021
|
xyz.append([float(el.getAttribute(a)) for a in 'xyz'])
|
|
1033
|
-
self._gpos = array(xyz, 'd').swapaxes(0, 1)
|
|
1034
|
-
self.subgrids = array(names)
|
|
1022
|
+
self._gpos = np.array(xyz, 'd').swapaxes(0, 1)
|
|
1023
|
+
self.subgrids = np.array(names)
|
|
1035
1024
|
|
|
1036
1025
|
|
|
1037
|
-
@deprecated_alias({'gpos': 'pos', 'numpoints': 'num_points'}, read_only=['gpos'], removal_version='25.10')
|
|
1038
1026
|
class LineGrid(Grid):
|
|
1039
1027
|
"""
|
|
1040
1028
|
Define a 3D grid for a line geometry.
|
|
@@ -1084,7 +1072,7 @@ class LineGrid(Grid):
|
|
|
1084
1072
|
|
|
1085
1073
|
#: A (3, :attr:`size`) array containing the x, y, and z positions of the grid points.
|
|
1086
1074
|
#: (read-only)
|
|
1087
|
-
#: All positions' coordinates are in meters by default (
|
|
1075
|
+
#: All positions' coordinates are in meters by default (:ref:`see here <units_note_grids>`).
|
|
1088
1076
|
pos = Property(desc='x, y, z positions of grid points')
|
|
1089
1077
|
|
|
1090
1078
|
#: A unique identifier for the grid, based on its properties. (read-only)
|
|
@@ -1107,15 +1095,14 @@ class LineGrid(Grid):
|
|
|
1107
1095
|
@property_depends_on(['num_points', 'length', 'direction', 'loc'])
|
|
1108
1096
|
def _get_pos(self):
|
|
1109
1097
|
dist = self.length / (self.num_points - 1)
|
|
1110
|
-
loc = array(self.loc, dtype=float).reshape((3, 1))
|
|
1111
|
-
direc_n = array(self.direction) / norm(self.direction)
|
|
1112
|
-
pos = zeros((self.num_points, 3))
|
|
1098
|
+
loc = np.array(self.loc, dtype=float).reshape((3, 1))
|
|
1099
|
+
direc_n = np.array(self.direction) / spla.norm(self.direction)
|
|
1100
|
+
pos = np.zeros((self.num_points, 3))
|
|
1113
1101
|
for s in range(self.num_points):
|
|
1114
1102
|
pos[s] = loc.T + direc_n * dist * s
|
|
1115
1103
|
return pos.T
|
|
1116
1104
|
|
|
1117
1105
|
|
|
1118
|
-
@deprecated_alias({'gpos': 'pos'}, read_only=True, removal_version='25.10')
|
|
1119
1106
|
class MergeGrid(Grid):
|
|
1120
1107
|
"""
|
|
1121
1108
|
Base class for merging multiple grid geometries.
|
|
@@ -1177,17 +1164,17 @@ class MergeGrid(Grid):
|
|
|
1177
1164
|
|
|
1178
1165
|
@property_depends_on(['digest'])
|
|
1179
1166
|
def _get_subgrids(self):
|
|
1180
|
-
subgrids = zeros((1, 0), dtype=str)
|
|
1167
|
+
subgrids = np.zeros((1, 0), dtype=str)
|
|
1181
1168
|
for grid in self.grids:
|
|
1182
|
-
subgrids = append(subgrids, tile(grid.__class__.__name__ + grid.digest, grid.size))
|
|
1183
|
-
return subgrids[:, newaxis].T
|
|
1169
|
+
subgrids = np.append(subgrids, np.tile(grid.__class__.__name__ + grid.digest, grid.size))
|
|
1170
|
+
return subgrids[:, np.newaxis].T
|
|
1184
1171
|
|
|
1185
1172
|
@property_depends_on(['digest'])
|
|
1186
1173
|
def _get_pos(self):
|
|
1187
|
-
bpos = zeros((3, 0))
|
|
1174
|
+
bpos = np.zeros((3, 0))
|
|
1188
1175
|
for grid in self.grids:
|
|
1189
|
-
bpos = append(bpos, grid.pos, axis=1)
|
|
1190
|
-
return unique(bpos, axis=1)
|
|
1176
|
+
bpos = np.append(bpos, grid.pos, axis=1)
|
|
1177
|
+
return np.unique(bpos, axis=1)
|
|
1191
1178
|
|
|
1192
1179
|
|
|
1193
1180
|
class Sector(ABCHasStrictTraits):
|
|
@@ -1241,7 +1228,7 @@ class Sector(ABCHasStrictTraits):
|
|
|
1241
1228
|
>>> sector.contains(positions)
|
|
1242
1229
|
array([ True, True])
|
|
1243
1230
|
"""
|
|
1244
|
-
return ones(pos.shape[1], dtype=bool)
|
|
1231
|
+
return np.ones(pos.shape[1], dtype=bool)
|
|
1245
1232
|
|
|
1246
1233
|
|
|
1247
1234
|
class SingleSector(Sector):
|
|
@@ -1354,7 +1341,7 @@ class RectSector(SingleSector):
|
|
|
1354
1341
|
x = (xmin + xmax) / 2.0
|
|
1355
1342
|
y = (ymin + ymax) / 2.0
|
|
1356
1343
|
dr2 = (pos[0, :] - x) ** 2 + (pos[1, :] - y) ** 2
|
|
1357
|
-
inds[argmin(dr2)] = True
|
|
1344
|
+
inds[np.argmin(dr2)] = True
|
|
1358
1345
|
|
|
1359
1346
|
return inds.astype(bool)
|
|
1360
1347
|
|
|
@@ -1442,7 +1429,7 @@ class RectSector3D(RectSector):
|
|
|
1442
1429
|
x = (xmin + xmax) / 2.0
|
|
1443
1430
|
y = (ymin + ymax) / 2.0
|
|
1444
1431
|
dr2 = (pos[0, :] - x) ** 2 + (pos[1, :] - y) ** 2
|
|
1445
|
-
inds[argmin(dr2)] = True
|
|
1432
|
+
inds[np.argmin(dr2)] = True
|
|
1446
1433
|
|
|
1447
1434
|
return inds.astype(bool)
|
|
1448
1435
|
|
|
@@ -1510,7 +1497,7 @@ class CircSector(SingleSector):
|
|
|
1510
1497
|
|
|
1511
1498
|
# if there's no point inside
|
|
1512
1499
|
if ~inds.any() and self.default_nearest:
|
|
1513
|
-
inds[argmin(dr2)] = True
|
|
1500
|
+
inds[np.argmin(dr2)] = True
|
|
1514
1501
|
|
|
1515
1502
|
return inds
|
|
1516
1503
|
|
|
@@ -1567,14 +1554,14 @@ class PolySector(SingleSector):
|
|
|
1567
1554
|
>>> sec.contains(grid.pos)
|
|
1568
1555
|
array([False, False, False, False, True, True, False, True, True])
|
|
1569
1556
|
"""
|
|
1570
|
-
poly = Polygon(array(self.edges).reshape(-1, 2)[:, 0], array(self.edges).reshape(-1, 2)[:, 1])
|
|
1557
|
+
poly = Polygon(np.array(self.edges).reshape(-1, 2)[:, 0], np.array(self.edges).reshape(-1, 2)[:, 1])
|
|
1571
1558
|
dists = poly.is_inside(pos[0, :], pos[1, :])
|
|
1572
1559
|
inds = dists >= -self.abs_tol if self.include_border else dists > 0
|
|
1573
1560
|
|
|
1574
1561
|
# if none inside, take nearest
|
|
1575
1562
|
if ~inds.any() and self.default_nearest:
|
|
1576
|
-
dr2 = array(self.edges).reshape(-1, 2).mean(0)
|
|
1577
|
-
inds[argmin(dr2)] = True
|
|
1563
|
+
dr2 = np.array(self.edges).reshape(-1, 2).mean(0)
|
|
1564
|
+
inds[np.argmin(dr2)] = True
|
|
1578
1565
|
|
|
1579
1566
|
return inds
|
|
1580
1567
|
|
|
@@ -1627,12 +1614,12 @@ class ConvexSector(SingleSector):
|
|
|
1627
1614
|
>>> sec.contains(grid.pos)
|
|
1628
1615
|
array([False, False, False, False, True, True, False, True, True])
|
|
1629
1616
|
"""
|
|
1630
|
-
inds = in_hull(pos[:2, :].T, array(self.edges).reshape(-1, 2), border=self.include_border, tol=self.abs_tol)
|
|
1617
|
+
inds = in_hull(pos[:2, :].T, np.array(self.edges).reshape(-1, 2), border=self.include_border, tol=self.abs_tol)
|
|
1631
1618
|
|
|
1632
1619
|
# if none inside, take nearest
|
|
1633
1620
|
if ~inds.any() and self.default_nearest:
|
|
1634
|
-
dr2 = array(self.edges).reshape(-1, 2).mean(0) # Use the centroid of the polygon as the "center"
|
|
1635
|
-
inds[argmin(dr2)] = True
|
|
1621
|
+
dr2 = np.array(self.edges).reshape(-1, 2).mean(0) # Use the centroid of the polygon as the "center"
|
|
1622
|
+
inds[np.argmin(dr2)] = True
|
|
1636
1623
|
|
|
1637
1624
|
return inds
|
|
1638
1625
|
|
|
@@ -1687,7 +1674,7 @@ class MultiSector(Sector):
|
|
|
1687
1674
|
array([False, False, False, False, True, True, False, True, True])
|
|
1688
1675
|
"""
|
|
1689
1676
|
# initialize with only "False" entries
|
|
1690
|
-
inds = zeros(pos.shape[1], dtype=bool)
|
|
1677
|
+
inds = np.zeros(pos.shape[1], dtype=bool)
|
|
1691
1678
|
|
|
1692
1679
|
# add points contained in each sector
|
|
1693
1680
|
for sec in self.sectors:
|
acoular/h5cache.py
CHANGED
|
@@ -32,23 +32,27 @@ class HDF5Cache(HasStrictTraits):
|
|
|
32
32
|
pass
|
|
33
33
|
|
|
34
34
|
def close_cachefile(self, cachefile):
|
|
35
|
+
"""Close a cache file and remove it from the reference counter."""
|
|
35
36
|
self.open_file_reference.pop(Path(cachefile.filename))
|
|
36
37
|
cachefile.close()
|
|
37
38
|
|
|
38
39
|
def get_open_cachefiles(self):
|
|
40
|
+
"""Get an iterator over all open cache files."""
|
|
39
41
|
try:
|
|
40
42
|
return self.open_files.itervalues()
|
|
41
43
|
except AttributeError:
|
|
42
44
|
return iter(self.open_files.values())
|
|
43
45
|
|
|
44
46
|
def close_unreferenced_cachefiles(self):
|
|
47
|
+
"""Close cache files that are no longer referenced by any objects."""
|
|
45
48
|
for cachefile in self.get_open_cachefiles():
|
|
46
49
|
if not self.is_reference_existent(cachefile):
|
|
47
50
|
self.close_cachefile(cachefile)
|
|
48
51
|
|
|
49
52
|
def is_reference_existent(self, file):
|
|
53
|
+
"""Check if a file object still has active references."""
|
|
50
54
|
exist_flag = False
|
|
51
|
-
# inspect all
|
|
55
|
+
# inspect all referrers to the file object
|
|
52
56
|
gc.collect() # clear garbage before collecting referrers
|
|
53
57
|
for ref in gc.get_referrers(file):
|
|
54
58
|
# does the file object have a referrer that has a 'h5f'
|