acoular 24.7__py3-none-any.whl → 25.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acoular/__init__.py +21 -9
- acoular/aiaa/__init__.py +12 -0
- acoular/{tools → aiaa}/aiaa.py +26 -31
- acoular/base.py +332 -0
- acoular/calib.py +129 -34
- acoular/configuration.py +13 -11
- acoular/demo/__init__.py +1 -0
- acoular/demo/acoular_demo.py +30 -17
- acoular/deprecation.py +85 -0
- acoular/environments.py +38 -24
- acoular/fastFuncs.py +90 -84
- acoular/fbeamform.py +342 -387
- acoular/fprocess.py +376 -0
- acoular/grids.py +122 -150
- acoular/h5cache.py +29 -40
- acoular/h5files.py +2 -6
- acoular/microphones.py +50 -59
- acoular/process.py +771 -0
- acoular/sdinput.py +35 -21
- acoular/signals.py +120 -113
- acoular/sources.py +208 -234
- acoular/spectra.py +59 -254
- acoular/tbeamform.py +280 -280
- acoular/tfastfuncs.py +21 -21
- acoular/tools/__init__.py +3 -7
- acoular/tools/helpers.py +218 -4
- acoular/tools/metrics.py +5 -5
- acoular/tools/utils.py +116 -0
- acoular/tprocess.py +416 -741
- acoular/traitsviews.py +15 -13
- acoular/trajectory.py +7 -10
- acoular/version.py +2 -2
- {acoular-24.7.dist-info → acoular-25.1.dist-info}/METADATA +63 -21
- acoular-25.1.dist-info/RECORD +56 -0
- {acoular-24.7.dist-info → acoular-25.1.dist-info}/WHEEL +1 -1
- acoular-24.7.dist-info/RECORD +0 -50
- {acoular-24.7.dist-info → acoular-25.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {acoular-24.7.dist-info → acoular-25.1.dist-info}/licenses/LICENSE +0 -0
acoular/grids.py
CHANGED
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
26
|
# imports from other packages
|
|
27
|
-
|
|
27
|
+
import xml.dom.minidom
|
|
28
|
+
from abc import abstractmethod
|
|
28
29
|
|
|
29
30
|
from numpy import (
|
|
30
31
|
absolute,
|
|
@@ -32,7 +33,7 @@ from numpy import (
|
|
|
32
33
|
arange,
|
|
33
34
|
argmin,
|
|
34
35
|
array,
|
|
35
|
-
|
|
36
|
+
asarray,
|
|
36
37
|
concatenate,
|
|
37
38
|
copysign,
|
|
38
39
|
fabs,
|
|
@@ -44,35 +45,39 @@ from numpy import (
|
|
|
44
45
|
ones,
|
|
45
46
|
ones_like,
|
|
46
47
|
s_,
|
|
47
|
-
sum,
|
|
48
|
+
sum, # noqa: A004
|
|
48
49
|
tile,
|
|
49
50
|
unique,
|
|
50
51
|
where,
|
|
51
52
|
zeros,
|
|
52
53
|
)
|
|
53
|
-
from
|
|
54
|
+
from scipy.linalg import norm
|
|
54
55
|
|
|
55
56
|
# from matplotlib.path import Path
|
|
56
57
|
from scipy.spatial import Delaunay
|
|
57
58
|
from traits.api import (
|
|
58
|
-
|
|
59
|
+
ABCHasStrictTraits,
|
|
59
60
|
Bool,
|
|
60
61
|
CArray,
|
|
61
62
|
File,
|
|
62
63
|
Float,
|
|
63
|
-
HasPrivateTraits,
|
|
64
64
|
Instance,
|
|
65
65
|
Int,
|
|
66
66
|
List,
|
|
67
67
|
Property,
|
|
68
|
+
Str,
|
|
68
69
|
Tuple,
|
|
70
|
+
Union,
|
|
69
71
|
cached_property,
|
|
72
|
+
observe,
|
|
70
73
|
on_trait_change,
|
|
71
74
|
property_depends_on,
|
|
72
75
|
)
|
|
73
76
|
from traits.trait_errors import TraitError
|
|
74
77
|
|
|
75
|
-
|
|
78
|
+
# acoular imports
|
|
79
|
+
from .deprecation import deprecated_alias
|
|
80
|
+
from .internal import digest, ldigest
|
|
76
81
|
|
|
77
82
|
|
|
78
83
|
def in_hull(p, hull, border=True, tol=0):
|
|
@@ -110,8 +115,8 @@ def _det(xvert, yvert):
|
|
|
110
115
|
all points are collinear.
|
|
111
116
|
|
|
112
117
|
"""
|
|
113
|
-
xvert =
|
|
114
|
-
yvert =
|
|
118
|
+
xvert = asarray(xvert, dtype=float)
|
|
119
|
+
yvert = asarray(yvert, dtype=float)
|
|
115
120
|
x_prev = concatenate(([xvert[-1]], xvert[:-1]))
|
|
116
121
|
y_prev = concatenate(([yvert[-1]], yvert[:-1]))
|
|
117
122
|
return sum(yvert * x_prev - xvert * y_prev, axis=0)
|
|
@@ -128,8 +133,8 @@ class Polygon:
|
|
|
128
133
|
if len(x) != len(y):
|
|
129
134
|
msg = 'x and y must be equally sized.'
|
|
130
135
|
raise IndexError(msg)
|
|
131
|
-
self.x =
|
|
132
|
-
self.y =
|
|
136
|
+
self.x = asarray(x, dtype=float)
|
|
137
|
+
self.y = asarray(y, dtype=float)
|
|
133
138
|
# Closes the polygon if were open
|
|
134
139
|
x1, y1 = x[0], y[0]
|
|
135
140
|
xn, yn = x[-1], y[-1]
|
|
@@ -166,8 +171,8 @@ class Polygon:
|
|
|
166
171
|
Software, Vol 7, No. 1, pp 45-47.
|
|
167
172
|
|
|
168
173
|
"""
|
|
169
|
-
xpoint =
|
|
170
|
-
ypoint =
|
|
174
|
+
xpoint = asarray(xpoint, dtype=float)
|
|
175
|
+
ypoint = asarray(ypoint, dtype=float)
|
|
171
176
|
# Scalar to array
|
|
172
177
|
if xpoint.shape == ():
|
|
173
178
|
xpoint = array([xpoint], dtype=float)
|
|
@@ -251,12 +256,13 @@ class Polygon:
|
|
|
251
256
|
return mindst
|
|
252
257
|
|
|
253
258
|
|
|
254
|
-
|
|
259
|
+
@deprecated_alias({'gpos': 'pos'})
|
|
260
|
+
class Grid(ABCHasStrictTraits):
|
|
255
261
|
"""Virtual base class for grid geometries.
|
|
256
262
|
|
|
257
263
|
Defines the common interface for all grid classes and
|
|
258
264
|
provides facilities to query grid properties and related data. This class
|
|
259
|
-
may be used as a base for specialized grid
|
|
265
|
+
may be used as a base for specialized grid implementations. It should not
|
|
260
266
|
be used directly as it contains no real functionality.
|
|
261
267
|
"""
|
|
262
268
|
|
|
@@ -270,40 +276,32 @@ class Grid(HasPrivateTraits):
|
|
|
270
276
|
|
|
271
277
|
#: Grid positions as (3, :attr:`size`) array of floats, without invalid
|
|
272
278
|
#: microphones; readonly.
|
|
273
|
-
|
|
279
|
+
pos = Property(desc='x, y, z positions of grid points')
|
|
274
280
|
|
|
275
281
|
# internal identifier
|
|
276
282
|
digest = Property
|
|
277
283
|
|
|
284
|
+
@abstractmethod
|
|
278
285
|
def _get_digest(self):
|
|
279
|
-
|
|
286
|
+
"""Returns the digest of the grid object."""
|
|
280
287
|
|
|
281
288
|
# 'digest' is a placeholder for other properties in derived classes,
|
|
282
289
|
# necessary to trigger the depends on mechanism
|
|
283
|
-
@property_depends_on('digest')
|
|
290
|
+
@property_depends_on(['digest'])
|
|
291
|
+
@abstractmethod
|
|
284
292
|
def _get_size(self):
|
|
285
|
-
|
|
293
|
+
"""Returns the number of grid points."""
|
|
286
294
|
|
|
287
295
|
# 'digest' is a placeholder for other properties in derived classes
|
|
288
|
-
@property_depends_on('digest')
|
|
296
|
+
@property_depends_on(['digest'])
|
|
297
|
+
@abstractmethod
|
|
289
298
|
def _get_shape(self):
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
@property_depends_on('digest')
|
|
293
|
-
def _get_gpos(self):
|
|
294
|
-
return array([[0.0], [0.0], [0.0]])
|
|
295
|
-
|
|
296
|
-
def pos(self):
|
|
297
|
-
"""Calculates grid co-ordinates.
|
|
298
|
-
Deprecated; use :attr:`gpos` attribute instead.
|
|
299
|
-
|
|
300
|
-
Returns
|
|
301
|
-
-------
|
|
302
|
-
array of floats of shape (3, :attr:`size`)
|
|
303
|
-
The grid point x, y, z-coordinates in one array.
|
|
299
|
+
"""Returns the shape of the grid as a Tuple."""
|
|
304
300
|
|
|
305
|
-
|
|
306
|
-
|
|
301
|
+
@property_depends_on(['digest'])
|
|
302
|
+
@abstractmethod
|
|
303
|
+
def _get_pos(self):
|
|
304
|
+
"""Returns the grid positions as (3, size) array of floats."""
|
|
307
305
|
|
|
308
306
|
def subdomain(self, sector):
|
|
309
307
|
"""Queries the indices for a subdomain in the grid.
|
|
@@ -322,13 +320,14 @@ class Grid(HasPrivateTraits):
|
|
|
322
320
|
an array with the same shape as the grid.
|
|
323
321
|
|
|
324
322
|
"""
|
|
325
|
-
xpos = self.
|
|
323
|
+
xpos = self.pos
|
|
326
324
|
# construct grid-shaped array with "True" entries where sector is
|
|
327
325
|
xyi = sector.contains(xpos).reshape(self.shape)
|
|
328
326
|
# return indices of "True" entries
|
|
329
327
|
return where(xyi)
|
|
330
328
|
|
|
331
329
|
|
|
330
|
+
@deprecated_alias({'gpos': 'pos'}, read_only=True)
|
|
332
331
|
class RectGrid(Grid):
|
|
333
332
|
"""Provides a cartesian 2D grid for the beamforming results.
|
|
334
333
|
|
|
@@ -366,22 +365,22 @@ class RectGrid(Grid):
|
|
|
366
365
|
depends_on=['x_min', 'x_max', 'y_min', 'y_max', 'z', 'increment'],
|
|
367
366
|
)
|
|
368
367
|
|
|
369
|
-
@property_depends_on('nxsteps, nysteps')
|
|
368
|
+
@property_depends_on(['nxsteps', 'nysteps'])
|
|
370
369
|
def _get_size(self):
|
|
371
370
|
return self.nxsteps * self.nysteps
|
|
372
371
|
|
|
373
|
-
@property_depends_on('nxsteps, nysteps')
|
|
372
|
+
@property_depends_on(['nxsteps', 'nysteps'])
|
|
374
373
|
def _get_shape(self):
|
|
375
374
|
return (self.nxsteps, self.nysteps)
|
|
376
375
|
|
|
377
|
-
@property_depends_on('x_min, x_max, increment')
|
|
376
|
+
@property_depends_on(['x_min', 'x_max', 'increment'])
|
|
378
377
|
def _get_nxsteps(self):
|
|
379
378
|
i = abs(self.increment)
|
|
380
379
|
if i != 0:
|
|
381
380
|
return int(round((abs(self.x_max - self.x_min) + i) / i))
|
|
382
381
|
return 1
|
|
383
382
|
|
|
384
|
-
@property_depends_on('y_min, y_max, increment')
|
|
383
|
+
@property_depends_on(['y_min', 'y_max', 'increment'])
|
|
385
384
|
def _get_nysteps(self):
|
|
386
385
|
i = abs(self.increment)
|
|
387
386
|
if i != 0:
|
|
@@ -392,8 +391,8 @@ class RectGrid(Grid):
|
|
|
392
391
|
def _get_digest(self):
|
|
393
392
|
return digest(self)
|
|
394
393
|
|
|
395
|
-
@property_depends_on('x_min, x_max, y_min, y_max, increment')
|
|
396
|
-
def
|
|
394
|
+
@property_depends_on(['x_min', 'x_max', 'y_min', 'y_max', 'increment'])
|
|
395
|
+
def _get_pos(self):
|
|
397
396
|
"""Calculates grid co-ordinates.
|
|
398
397
|
|
|
399
398
|
Returns
|
|
@@ -450,7 +449,7 @@ class RectGrid(Grid):
|
|
|
450
449
|
x1, y1, x2, y2, ... : float
|
|
451
450
|
If three parameters are given, then a circular sector is assumed
|
|
452
451
|
that is given by its center (x1, y1) and the radius x2.
|
|
453
|
-
If four
|
|
452
|
+
If four parameters are given, then a rectangular sector is
|
|
454
453
|
assumed that is given by two corners (x1, y1) and (x2, y2).
|
|
455
454
|
If more parameters are given, the subdomain is assumed to have
|
|
456
455
|
polygonial shape with corners at (x_n, y_n).
|
|
@@ -463,7 +462,7 @@ class RectGrid(Grid):
|
|
|
463
462
|
|
|
464
463
|
"""
|
|
465
464
|
if len(r) == 3: # only 3 values given -> use x,y,radius method
|
|
466
|
-
xpos = self.
|
|
465
|
+
xpos = self.pos
|
|
467
466
|
xis = []
|
|
468
467
|
yis = []
|
|
469
468
|
dr2 = (xpos[0, :] - r[0]) ** 2 + (xpos[1, :] - r[1]) ** 2
|
|
@@ -480,7 +479,7 @@ class RectGrid(Grid):
|
|
|
480
479
|
xi1, yi1 = self.index(min(r[0], r[2]), min(r[1], r[3]))
|
|
481
480
|
xi2, yi2 = self.index(max(r[0], r[2]), max(r[1], r[3]))
|
|
482
481
|
return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1]
|
|
483
|
-
xpos = self.
|
|
482
|
+
xpos = self.pos
|
|
484
483
|
xis = []
|
|
485
484
|
yis = []
|
|
486
485
|
# replaced matplotlib Path by numpy
|
|
@@ -535,7 +534,7 @@ class RectGrid3D(RectGrid):
|
|
|
535
534
|
nzsteps = Property(desc='number of grid points along x-axis')
|
|
536
535
|
|
|
537
536
|
# Private trait for increment handling
|
|
538
|
-
_increment =
|
|
537
|
+
_increment = Union(Float(), CArray(shape=(3,), dtype=float), default_value=0.1, desc='step size')
|
|
539
538
|
|
|
540
539
|
#: The cell side length for the grid. This can either be a scalar (same
|
|
541
540
|
#: increments in all 3 dimensions) or a (3,) array of floats with
|
|
@@ -557,57 +556,42 @@ class RectGrid3D(RectGrid):
|
|
|
557
556
|
else:
|
|
558
557
|
raise (TraitError(args=self, name='increment', info='Float or CArray(3,)', value=increment))
|
|
559
558
|
|
|
560
|
-
# Respective increments in x,y, and z-direction (in m).
|
|
561
|
-
# Deprecated: Use :attr:`~RectGrid.increment` for this functionality
|
|
562
|
-
increment3D = Property(desc='3D step sizes') # noqa N815
|
|
563
|
-
|
|
564
|
-
def _get_increment3D(self): # noqa N802
|
|
565
|
-
if isscalar(self._increment):
|
|
566
|
-
return array([self._increment, self._increment, self._increment])
|
|
567
|
-
return self._increment
|
|
568
|
-
|
|
569
|
-
def _set_increment3D(self, inc): # noqa N802
|
|
570
|
-
if not isscalar(inc) and len(inc) == 3:
|
|
571
|
-
self._increment = array(inc, dtype=float)
|
|
572
|
-
else:
|
|
573
|
-
raise (TraitError(args=self, name='increment3D', info='CArray(3,)', value=inc))
|
|
574
|
-
|
|
575
559
|
# internal identifier
|
|
576
560
|
digest = Property(
|
|
577
561
|
depends_on=['x_min', 'x_max', 'y_min', 'y_max', 'z_min', 'z_max', '_increment'],
|
|
578
562
|
)
|
|
579
563
|
|
|
580
|
-
@property_depends_on('nxsteps, nysteps, nzsteps')
|
|
564
|
+
@property_depends_on(['nxsteps', 'nysteps', 'nzsteps'])
|
|
581
565
|
def _get_size(self):
|
|
582
566
|
return self.nxsteps * self.nysteps * self.nzsteps
|
|
583
567
|
|
|
584
|
-
@property_depends_on('nxsteps, nysteps, nzsteps')
|
|
568
|
+
@property_depends_on(['nxsteps', 'nysteps', 'nzsteps'])
|
|
585
569
|
def _get_shape(self):
|
|
586
570
|
return (self.nxsteps, self.nysteps, self.nzsteps)
|
|
587
571
|
|
|
588
|
-
@property_depends_on('x_min, x_max, _increment')
|
|
572
|
+
@property_depends_on(['x_min', 'x_max', '_increment'])
|
|
589
573
|
def _get_nxsteps(self):
|
|
590
|
-
i = abs(self.
|
|
574
|
+
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[0])
|
|
591
575
|
if i != 0:
|
|
592
576
|
return int(round((abs(self.x_max - self.x_min) + i) / i))
|
|
593
577
|
return 1
|
|
594
578
|
|
|
595
|
-
@property_depends_on('y_min, y_max, _increment')
|
|
579
|
+
@property_depends_on(['y_min', 'y_max', '_increment'])
|
|
596
580
|
def _get_nysteps(self):
|
|
597
|
-
i = abs(self.
|
|
581
|
+
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[1])
|
|
598
582
|
if i != 0:
|
|
599
583
|
return int(round((abs(self.y_max - self.y_min) + i) / i))
|
|
600
584
|
return 1
|
|
601
585
|
|
|
602
|
-
@property_depends_on('z_min, z_max, _increment')
|
|
586
|
+
@property_depends_on(['z_min', 'z_max', '_increment'])
|
|
603
587
|
def _get_nzsteps(self):
|
|
604
|
-
i = abs(self.
|
|
588
|
+
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[2])
|
|
605
589
|
if i != 0:
|
|
606
590
|
return int(round((abs(self.z_max - self.z_min) + i) / i))
|
|
607
591
|
return 1
|
|
608
592
|
|
|
609
593
|
@property_depends_on('digest')
|
|
610
|
-
def
|
|
594
|
+
def _get_pos(self):
|
|
611
595
|
"""Calculates grid co-ordinates.
|
|
612
596
|
|
|
613
597
|
Returns
|
|
@@ -655,9 +639,13 @@ class RectGrid3D(RectGrid):
|
|
|
655
639
|
if z < self.z_min or z > self.z_max:
|
|
656
640
|
msg = f'z-value out of range {z:f} ({self.z_min:f}, {self.z_max:f})'
|
|
657
641
|
raise ValueError(msg)
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
642
|
+
if isscalar(self.increment):
|
|
643
|
+
incx = incy = incz = self.increment
|
|
644
|
+
else:
|
|
645
|
+
incx, incy, incz = self.increment
|
|
646
|
+
xi = int(round((x - self.x_min) / incx))
|
|
647
|
+
yi = int(round((y - self.y_min) / incy))
|
|
648
|
+
zi = int(round((z - self.z_min) / incz))
|
|
661
649
|
return xi, yi, zi
|
|
662
650
|
|
|
663
651
|
def indices(self, x1, y1, z1, x2, y2, z2):
|
|
@@ -684,25 +672,19 @@ class RectGrid3D(RectGrid):
|
|
|
684
672
|
return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1], s_[zi1 : zi2 + 1]
|
|
685
673
|
|
|
686
674
|
|
|
675
|
+
@deprecated_alias({'from_file': 'file', 'gpos_file': 'pos'})
|
|
687
676
|
class ImportGrid(Grid):
|
|
688
677
|
"""Loads a 3D grid from xml file."""
|
|
689
678
|
|
|
690
|
-
#: Name of the .xml-file from
|
|
691
|
-
|
|
679
|
+
#: Name of the .xml-file from which to read the data.
|
|
680
|
+
file = File(filter=['*.xml'], exists=True, desc='name of the xml file to import')
|
|
692
681
|
|
|
693
|
-
|
|
682
|
+
_gpos = CArray(dtype=float, desc='x, y, z position of all Grid Points')
|
|
694
683
|
|
|
695
|
-
|
|
696
|
-
basename = Property(depends_on='from_file', desc='basename of xml file')
|
|
684
|
+
subgrids = CArray(desc='names of subgrids for each point')
|
|
697
685
|
|
|
698
686
|
# internal identifier
|
|
699
|
-
digest = Property(
|
|
700
|
-
depends_on=['from_file'],
|
|
701
|
-
)
|
|
702
|
-
|
|
703
|
-
@cached_property
|
|
704
|
-
def _get_basename(self):
|
|
705
|
-
return path.splitext(path.basename(self.from_file))[0]
|
|
687
|
+
digest = Property(depends_on=['_gpos'])
|
|
706
688
|
|
|
707
689
|
@cached_property
|
|
708
690
|
def _get_digest(self):
|
|
@@ -710,42 +692,36 @@ class ImportGrid(Grid):
|
|
|
710
692
|
|
|
711
693
|
# 'digest' is a placeholder for other properties in derived classes,
|
|
712
694
|
# necessary to trigger the depends on mechanism
|
|
713
|
-
@property_depends_on('
|
|
695
|
+
@property_depends_on(['_gpos'])
|
|
714
696
|
def _get_size(self):
|
|
715
|
-
return self.
|
|
697
|
+
return self.pos.shape[-1]
|
|
716
698
|
|
|
717
699
|
# 'digest' is a placeholder for other properties in derived classes
|
|
718
|
-
@property_depends_on('
|
|
700
|
+
@property_depends_on(['_gpos'])
|
|
719
701
|
def _get_shape(self):
|
|
720
|
-
return (self.
|
|
702
|
+
return (self.pos.shape[-1],)
|
|
721
703
|
|
|
722
|
-
@property_depends_on('
|
|
723
|
-
def
|
|
724
|
-
return self.
|
|
704
|
+
@property_depends_on(['_gpos'])
|
|
705
|
+
def _get_pos(self):
|
|
706
|
+
return self._gpos
|
|
725
707
|
|
|
726
|
-
|
|
708
|
+
def _set_pos(self, pos):
|
|
709
|
+
self._gpos = pos
|
|
727
710
|
|
|
728
|
-
@on_trait_change('
|
|
711
|
+
@on_trait_change('file')
|
|
729
712
|
def import_gpos(self):
|
|
730
|
-
"""Import the the grid point locations from .xml file.
|
|
731
|
-
|
|
732
|
-
"""
|
|
733
|
-
if not path.isfile(self.from_file):
|
|
734
|
-
# no file there
|
|
735
|
-
self.gpos_file = array([], 'd')
|
|
736
|
-
return
|
|
737
|
-
import xml.dom.minidom
|
|
738
|
-
|
|
739
|
-
doc = xml.dom.minidom.parse(self.from_file)
|
|
713
|
+
"""Import the the grid point locations from .xml file when :attr:`file` changes."""
|
|
714
|
+
doc = xml.dom.minidom.parse(self.file)
|
|
740
715
|
names = []
|
|
741
716
|
xyz = []
|
|
742
717
|
for el in doc.getElementsByTagName('pos'):
|
|
743
718
|
names.append(el.getAttribute('subgrid'))
|
|
744
719
|
xyz.append([float(el.getAttribute(a)) for a in 'xyz'])
|
|
745
|
-
self.
|
|
720
|
+
self._gpos = array(xyz, 'd').swapaxes(0, 1)
|
|
746
721
|
self.subgrids = array(names)
|
|
747
722
|
|
|
748
723
|
|
|
724
|
+
@deprecated_alias({'gpos': 'pos', 'numpoints': 'num_points'}, read_only=['gpos'])
|
|
749
725
|
class LineGrid(Grid):
|
|
750
726
|
"""Class for Line grid geometries."""
|
|
751
727
|
|
|
@@ -759,7 +735,7 @@ class LineGrid(Grid):
|
|
|
759
735
|
length = Float(1, desc='length of the line source')
|
|
760
736
|
|
|
761
737
|
#:number of grid points.
|
|
762
|
-
|
|
738
|
+
num_points = Int(1, desc='length of the line source')
|
|
763
739
|
|
|
764
740
|
#: Overall number of grid points. Readonly; is set automatically when
|
|
765
741
|
#: other grid defining properties are set
|
|
@@ -767,10 +743,10 @@ class LineGrid(Grid):
|
|
|
767
743
|
|
|
768
744
|
#: Grid positions as (3, :attr:`size`) array of floats, without invalid
|
|
769
745
|
#: microphones; readonly.
|
|
770
|
-
|
|
746
|
+
pos = Property(desc='x, y, z positions of grid points')
|
|
771
747
|
|
|
772
748
|
digest = Property(
|
|
773
|
-
depends_on=['loc', 'direction', 'length', '
|
|
749
|
+
depends_on=['loc', 'direction', 'length', 'num_points', 'size'],
|
|
774
750
|
)
|
|
775
751
|
|
|
776
752
|
@cached_property
|
|
@@ -779,26 +755,27 @@ class LineGrid(Grid):
|
|
|
779
755
|
|
|
780
756
|
# 'digest' is a placeholder for other properties in derived classes,
|
|
781
757
|
# necessary to trigger the depends on mechanism
|
|
782
|
-
@property_depends_on('
|
|
758
|
+
@property_depends_on(['num_points'])
|
|
783
759
|
def _get_size(self):
|
|
784
|
-
return self.
|
|
760
|
+
return self.pos.shape[-1]
|
|
785
761
|
|
|
786
762
|
# 'digest' is a placeholder for other properties in derived classes
|
|
787
|
-
@property_depends_on('
|
|
763
|
+
@property_depends_on(['num_points'])
|
|
788
764
|
def _get_shape(self):
|
|
789
|
-
return self.
|
|
765
|
+
return self.pos.shape[-1]
|
|
790
766
|
|
|
791
|
-
@property_depends_on('
|
|
792
|
-
def
|
|
793
|
-
dist = self.length / (self.
|
|
767
|
+
@property_depends_on(['num_points', 'length', 'direction', 'loc'])
|
|
768
|
+
def _get_pos(self):
|
|
769
|
+
dist = self.length / (self.num_points - 1)
|
|
794
770
|
loc = array(self.loc, dtype=float).reshape((3, 1))
|
|
795
|
-
direc_n = self.direction / norm(self.direction)
|
|
796
|
-
pos = zeros((self.
|
|
797
|
-
for s in range(self.
|
|
771
|
+
direc_n = array(self.direction) / norm(self.direction)
|
|
772
|
+
pos = zeros((self.num_points, 3))
|
|
773
|
+
for s in range(self.num_points):
|
|
798
774
|
pos[s] = loc.T + direc_n * dist * s
|
|
799
775
|
return pos.T
|
|
800
776
|
|
|
801
777
|
|
|
778
|
+
@deprecated_alias({'gpos': 'pos'}, read_only=True)
|
|
802
779
|
class MergeGrid(Grid):
|
|
803
780
|
"""Base class for merging different grid geometries."""
|
|
804
781
|
|
|
@@ -807,7 +784,7 @@ class MergeGrid(Grid):
|
|
|
807
784
|
#: other grid defining properties are set
|
|
808
785
|
grids = List(desc='list of grids')
|
|
809
786
|
|
|
810
|
-
grid_digest =
|
|
787
|
+
grid_digest = Str(desc='digest of the merged grids')
|
|
811
788
|
|
|
812
789
|
subgrids = Property(desc='names of subgrids for each point')
|
|
813
790
|
|
|
@@ -820,46 +797,41 @@ class MergeGrid(Grid):
|
|
|
820
797
|
def _get_digest(self):
|
|
821
798
|
return digest(self)
|
|
822
799
|
|
|
823
|
-
@
|
|
824
|
-
def
|
|
825
|
-
|
|
826
|
-
for grid in self.grids:
|
|
827
|
-
griddigest.append(grid.digest)
|
|
828
|
-
return griddigest
|
|
800
|
+
@observe('grids.items.digest')
|
|
801
|
+
def _set_sourcesdigest(self, event): # noqa ARG002
|
|
802
|
+
self.grid_digest = ldigest(self.grids)
|
|
829
803
|
|
|
830
804
|
# 'digest' is a placeholder for other properties in derived classes,
|
|
831
805
|
# necessary to trigger the depends on mechanism
|
|
832
|
-
@property_depends_on('digest')
|
|
806
|
+
@property_depends_on(['digest'])
|
|
833
807
|
def _get_size(self):
|
|
834
|
-
return self.
|
|
808
|
+
return self.pos.shape[-1]
|
|
835
809
|
|
|
836
810
|
# 'digest' is a placeholder for other properties in derived classes
|
|
837
|
-
@property_depends_on('digest')
|
|
811
|
+
@property_depends_on(['digest'])
|
|
838
812
|
def _get_shape(self):
|
|
839
|
-
return self.
|
|
813
|
+
return self.pos.shape[-1]
|
|
840
814
|
|
|
841
|
-
@property_depends_on('digest')
|
|
815
|
+
@property_depends_on(['digest'])
|
|
842
816
|
def _get_subgrids(self):
|
|
843
817
|
subgrids = zeros((1, 0), dtype=str)
|
|
844
818
|
for grid in self.grids:
|
|
845
819
|
subgrids = append(subgrids, tile(grid.__class__.__name__ + grid.digest, grid.size))
|
|
846
820
|
return subgrids[:, newaxis].T
|
|
847
821
|
|
|
848
|
-
@property_depends_on('digest')
|
|
849
|
-
def
|
|
822
|
+
@property_depends_on(['digest'])
|
|
823
|
+
def _get_pos(self):
|
|
850
824
|
bpos = zeros((3, 0))
|
|
851
|
-
# subgrids = zeros((1,0))
|
|
852
825
|
for grid in self.grids:
|
|
853
|
-
bpos = append(bpos, grid.
|
|
854
|
-
# subgrids = append(subgrids,str(grid))
|
|
826
|
+
bpos = append(bpos, grid.pos, axis=1)
|
|
855
827
|
return unique(bpos, axis=1)
|
|
856
828
|
|
|
857
829
|
|
|
858
|
-
class Sector(
|
|
830
|
+
class Sector(ABCHasStrictTraits):
|
|
859
831
|
"""Base class for all sector types.
|
|
860
832
|
|
|
861
833
|
Defines the common interface for all tbdsector classes. This class
|
|
862
|
-
may be used as a base for diverse sector
|
|
834
|
+
may be used as a base for diverse sector implementations. If used
|
|
863
835
|
directly, it implements a sector encompassing the whole grid.
|
|
864
836
|
"""
|
|
865
837
|
|
|
@@ -888,7 +860,7 @@ class SingleSector(Sector):
|
|
|
888
860
|
"""Base class for single sector types.
|
|
889
861
|
|
|
890
862
|
Defines the common interface for all single sector classes. This class
|
|
891
|
-
may be used as a base for diverse single sector
|
|
863
|
+
may be used as a base for diverse single sector implementations. If used
|
|
892
864
|
directly, it implements a sector encompassing the whole grid.
|
|
893
865
|
"""
|
|
894
866
|
|
|
@@ -898,14 +870,15 @@ class SingleSector(Sector):
|
|
|
898
870
|
#: Absolute tolerance for sector border
|
|
899
871
|
abs_tol = Float(1e-12, desc='absolute tolerance for sector border')
|
|
900
872
|
|
|
901
|
-
#: Boolean flag, if 'True' (default), the nearest grid point is returned if
|
|
873
|
+
#: Boolean flag, if 'True' (default), the nearest grid point is returned if None is inside the
|
|
874
|
+
#: sector.
|
|
902
875
|
default_nearest = Bool(True, desc='return nearest grid point to center of none inside sector')
|
|
903
876
|
|
|
904
877
|
|
|
905
878
|
class RectSector(SingleSector):
|
|
906
879
|
"""Class for defining a rectangular sector.
|
|
907
880
|
|
|
908
|
-
Can be used for 2D Grids for
|
|
881
|
+
Can be used for 2D Grids for defining a rectangular sector or
|
|
909
882
|
for 3D grids for a rectangular cylinder sector parallel to the z-axis.
|
|
910
883
|
"""
|
|
911
884
|
|
|
@@ -976,7 +949,7 @@ class RectSector(SingleSector):
|
|
|
976
949
|
class RectSector3D(RectSector):
|
|
977
950
|
"""Class for defining a cuboid sector.
|
|
978
951
|
|
|
979
|
-
Can be used for 3D Grids for
|
|
952
|
+
Can be used for 3D Grids for defining a cuboid sector.
|
|
980
953
|
"""
|
|
981
954
|
|
|
982
955
|
#: The lower z position of the cuboid
|
|
@@ -1046,7 +1019,7 @@ class RectSector3D(RectSector):
|
|
|
1046
1019
|
class CircSector(SingleSector):
|
|
1047
1020
|
"""Class for defining a circular sector.
|
|
1048
1021
|
|
|
1049
|
-
Can be used for 2D Grids for
|
|
1022
|
+
Can be used for 2D Grids for defining a circular sector or
|
|
1050
1023
|
for 3D grids for a cylindrical sector parallel to the z-axis.
|
|
1051
1024
|
"""
|
|
1052
1025
|
|
|
@@ -1082,7 +1055,7 @@ class CircSector(SingleSector):
|
|
|
1082
1055
|
# which points are in the circle?
|
|
1083
1056
|
inds = dr2 - self.r**2 < self.abs_tol if self.include_border else dr2 - self.r**2 < -self.abs_tol
|
|
1084
1057
|
|
|
1085
|
-
# if there's no
|
|
1058
|
+
# if there's no point inside
|
|
1086
1059
|
if ~inds.any() and self.default_nearest:
|
|
1087
1060
|
inds[argmin(dr2)] = True
|
|
1088
1061
|
|
|
@@ -1092,17 +1065,16 @@ class CircSector(SingleSector):
|
|
|
1092
1065
|
class PolySector(SingleSector):
|
|
1093
1066
|
"""Class for defining a polygon sector.
|
|
1094
1067
|
|
|
1095
|
-
Can be used for 2D Grids for
|
|
1068
|
+
Can be used for 2D Grids for defining a polygon sector.
|
|
1096
1069
|
"""
|
|
1097
1070
|
|
|
1098
1071
|
# x1, y1, x2, y2, ... xn, yn :
|
|
1099
1072
|
edges = List(Float)
|
|
1100
1073
|
|
|
1101
1074
|
def contains(self, pos):
|
|
1102
|
-
"""Queries whether the coordinates in a given array lie within the
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
is returned if :attr:`~Sector.default_nearest` is True.
|
|
1075
|
+
"""Queries whether the coordinates in a given array lie within the polygon sector. If no
|
|
1076
|
+
coordinate is inside, the nearest one to the rectangle center is returned if
|
|
1077
|
+
:attr:`~Sector.default_nearest` is True.
|
|
1106
1078
|
|
|
1107
1079
|
Parameters
|
|
1108
1080
|
----------
|
|
@@ -1132,7 +1104,7 @@ class PolySector(SingleSector):
|
|
|
1132
1104
|
class ConvexSector(SingleSector):
|
|
1133
1105
|
"""Class for defining a convex hull sector.
|
|
1134
1106
|
|
|
1135
|
-
Can be used for 2D Grids for
|
|
1107
|
+
Can be used for 2D Grids for defining a convex hull sector.
|
|
1136
1108
|
"""
|
|
1137
1109
|
|
|
1138
1110
|
# x1, y1, x2, y2, ... xn, yn :
|