acoular 24.3__py3-none-any.whl → 24.5__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 +118 -50
- acoular/calib.py +29 -38
- acoular/configuration.py +116 -73
- acoular/demo/__init__.py +10 -4
- acoular/demo/acoular_demo.py +78 -53
- acoular/environments.py +265 -262
- acoular/fastFuncs.py +361 -191
- acoular/fbeamform.py +1460 -1404
- acoular/grids.py +501 -545
- acoular/h5cache.py +50 -59
- acoular/h5files.py +154 -137
- acoular/internal.py +10 -11
- acoular/microphones.py +57 -53
- acoular/sdinput.py +47 -52
- acoular/signals.py +167 -179
- acoular/sources.py +818 -693
- acoular/spectra.py +349 -359
- acoular/tbeamform.py +414 -413
- acoular/tfastfuncs.py +178 -101
- acoular/tools/__init__.py +25 -0
- acoular/tools/aiaa.py +186 -0
- acoular/tools/helpers.py +189 -0
- acoular/tools/metrics.py +165 -0
- acoular/tprocess.py +1201 -1143
- acoular/traitsviews.py +513 -501
- acoular/trajectory.py +50 -52
- acoular/version.py +5 -6
- acoular/xml/minidsp_uma-16.xml +20 -0
- acoular/xml/{minidsp_uma16.xml → minidsp_uma-16_mirrored.xml} +3 -0
- {acoular-24.3.dist-info → acoular-24.5.dist-info}/METADATA +45 -46
- acoular-24.5.dist-info/RECORD +50 -0
- {acoular-24.3.dist-info → acoular-24.5.dist-info}/WHEEL +1 -1
- acoular-24.5.dist-info/licenses/LICENSE +28 -0
- acoular/fileimport.py +0 -380
- acoular/nidaqimport.py +0 -273
- acoular/tests/reference_data/BeamformerBase.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse1.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse2.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse3.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseFalse4.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue1.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue2.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue3.npy +0 -0
- acoular/tests/reference_data/BeamformerBaseTrue4.npy +0 -0
- acoular/tests/reference_data/BeamformerCMFLassoLarsBIC.npy +0 -0
- acoular/tests/reference_data/BeamformerCMFNNLS.npy +0 -0
- acoular/tests/reference_data/BeamformerCapon.npy +0 -0
- acoular/tests/reference_data/BeamformerClean.npy +0 -0
- acoular/tests/reference_data/BeamformerCleansc.npy +0 -0
- acoular/tests/reference_data/BeamformerCleant.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantSq.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantSqTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerCleantTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerDamas.npy +0 -0
- acoular/tests/reference_data/BeamformerDamasPlus.npy +0 -0
- acoular/tests/reference_data/BeamformerEig.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse1.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse2.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse3.npy +0 -0
- acoular/tests/reference_data/BeamformerEigFalse4.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue1.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue2.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue3.npy +0 -0
- acoular/tests/reference_data/BeamformerEigTrue4.npy +0 -0
- acoular/tests/reference_data/BeamformerFunctional.npy +0 -0
- acoular/tests/reference_data/BeamformerGIB.npy +0 -0
- acoular/tests/reference_data/BeamformerGridlessOrth.npy +0 -0
- acoular/tests/reference_data/BeamformerMusic.npy +0 -0
- acoular/tests/reference_data/BeamformerOrth.npy +0 -0
- acoular/tests/reference_data/BeamformerSODIX.npy +0 -0
- acoular/tests/reference_data/BeamformerTime.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeSq.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeSqTraj.npy +0 -0
- acoular/tests/reference_data/BeamformerTimeTraj.npy +0 -0
- acoular/tests/reference_data/Environment.npy +0 -0
- acoular/tests/reference_data/Example1_numerical_values_testsum.h5 +0 -0
- acoular/tests/reference_data/FiltFiltOctave__.npy +0 -0
- acoular/tests/reference_data/FiltFiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_A_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_C_.npy +0 -0
- acoular/tests/reference_data/FiltFreqWeight_weight_Z_.npy +0 -0
- acoular/tests/reference_data/FiltOctave__.npy +0 -0
- acoular/tests/reference_data/FiltOctave_band_100_0_fraction_Thirdoctave_.npy +0 -0
- acoular/tests/reference_data/Filter__.npy +0 -0
- acoular/tests/reference_data/GeneralFlowEnvironment.npy +0 -0
- acoular/tests/reference_data/OctaveFilterBank__.npy +0 -0
- acoular/tests/reference_data/OpenJet.npy +0 -0
- acoular/tests/reference_data/PointSource.npy +0 -0
- acoular/tests/reference_data/PowerSpectra_csm.npy +0 -0
- acoular/tests/reference_data/PowerSpectra_ev.npy +0 -0
- acoular/tests/reference_data/RotatingFlow.npy +0 -0
- acoular/tests/reference_data/SlotJet.npy +0 -0
- acoular/tests/reference_data/TimeAverage__.npy +0 -0
- acoular/tests/reference_data/TimeCumAverage__.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_F_.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_I_.npy +0 -0
- acoular/tests/reference_data/TimeExpAverage_weight_S_.npy +0 -0
- acoular/tests/reference_data/TimeInOut__.npy +0 -0
- acoular/tests/reference_data/TimePower__.npy +0 -0
- acoular/tests/reference_data/TimeReverse__.npy +0 -0
- acoular/tests/reference_data/UniformFlowEnvironment.npy +0 -0
- acoular/tests/reference_data/beamformer_traj_time_data.h5 +0 -0
- acoular/tests/run_tests.sh +0 -18
- acoular/tests/run_tests_osx.sh +0 -16
- acoular/tests/test.npy +0 -0
- acoular/tests/test_beamformer_results.py +0 -213
- acoular/tests/test_classes.py +0 -60
- acoular/tests/test_digest.py +0 -125
- acoular/tests/test_environments.py +0 -73
- acoular/tests/test_example1.py +0 -124
- acoular/tests/test_grid.py +0 -92
- acoular/tests/test_integrate.py +0 -102
- acoular/tests/test_signals.py +0 -60
- acoular/tests/test_sources.py +0 -65
- acoular/tests/test_spectra.py +0 -38
- acoular/tests/test_timecache.py +0 -35
- acoular/tests/test_tprocess.py +0 -90
- acoular/tests/test_traj_beamformer_results.py +0 -164
- acoular/tests/unsupported/SpeedComparison/OvernightTestcasesBeamformer_nMics32_nGridPoints100_nFreqs4_nTrials10.png +0 -0
- acoular/tests/unsupported/SpeedComparison/cythonBeamformer.pyx +0 -237
- acoular/tests/unsupported/SpeedComparison/mainForCython.py +0 -103
- acoular/tests/unsupported/SpeedComparison/mainForParallelJit.py +0 -143
- acoular/tests/unsupported/SpeedComparison/setupCythonOpenMP.py +0 -63
- acoular/tests/unsupported/SpeedComparison/sharedFunctions.py +0 -153
- acoular/tests/unsupported/SpeedComparison/timeOverNMics_AllImportantMethods.png +0 -0
- acoular/tests/unsupported/SpeedComparison/timeOverNMics_faverage.png +0 -0
- acoular/tests/unsupported/SpeedComparison/vglOptimierungFAverage.py +0 -204
- acoular/tests/unsupported/SpeedComparison/vglOptimierungGaussSeidel.py +0 -182
- acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAMFULL_INVERSE.py +0 -764
- acoular/tests/unsupported/SpeedComparison/vglOptimierungR_BEAM_OS.py +0 -231
- acoular/tests/unsupported/SpeedComparison/whatsFastestWayFor_absASquared.py +0 -48
- acoular/tests/unsupported/functionalBeamformer.py +0 -123
- acoular/tests/unsupported/precisionTest.py +0 -153
- acoular/tests/unsupported/validationOfBeamformerFuncsPOSTAcoularIntegration.py +0 -254
- acoular/tests/unsupported/validationOfBeamformerFuncsPREeAcoularIntegration.py +0 -531
- acoular/tools.py +0 -422
- acoular-24.3.dist-info/RECORD +0 -148
- acoular-24.3.dist-info/licenses/LICENSE +0 -29
- {acoular-24.3.dist-info → acoular-24.5.dist-info}/licenses/AUTHORS.rst +0 -0
acoular/grids.py
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
#
|
|
2
|
-
#pylint: disable-msg=E0611, E1101, C0103, R0901, R0902, R0903, R0904, W0232
|
|
3
|
-
#------------------------------------------------------------------------------
|
|
1
|
+
# ------------------------------------------------------------------------------
|
|
4
2
|
# Copyright (c) Acoular Development Team.
|
|
5
|
-
|
|
6
|
-
"""Implements support for two- and threedimensional grids
|
|
3
|
+
# ------------------------------------------------------------------------------
|
|
4
|
+
"""Implements support for two- and threedimensional grids.
|
|
7
5
|
|
|
8
6
|
.. autosummary::
|
|
9
7
|
:toctree: generated/
|
|
@@ -26,39 +24,74 @@
|
|
|
26
24
|
"""
|
|
27
25
|
|
|
28
26
|
# imports from other packages
|
|
29
|
-
from
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
from os import path
|
|
28
|
+
|
|
29
|
+
from numpy import (
|
|
30
|
+
absolute,
|
|
31
|
+
append,
|
|
32
|
+
arange,
|
|
33
|
+
argmin,
|
|
34
|
+
array,
|
|
35
|
+
asfarray,
|
|
36
|
+
concatenate,
|
|
37
|
+
copysign,
|
|
38
|
+
fabs,
|
|
39
|
+
inf,
|
|
40
|
+
isscalar,
|
|
41
|
+
ma,
|
|
42
|
+
mgrid,
|
|
43
|
+
newaxis,
|
|
44
|
+
ones,
|
|
45
|
+
ones_like,
|
|
46
|
+
s_,
|
|
47
|
+
sum,
|
|
48
|
+
tile,
|
|
49
|
+
unique,
|
|
50
|
+
where,
|
|
51
|
+
zeros,
|
|
52
|
+
)
|
|
32
53
|
from numpy.linalg import norm
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
CArray, Tuple, Int
|
|
36
|
-
from traits.trait_errors import TraitError
|
|
37
|
-
#from matplotlib.path import Path
|
|
54
|
+
|
|
55
|
+
# from matplotlib.path import Path
|
|
38
56
|
from scipy.spatial import Delaunay
|
|
39
|
-
from
|
|
57
|
+
from traits.api import (
|
|
58
|
+
Any,
|
|
59
|
+
Bool,
|
|
60
|
+
CArray,
|
|
61
|
+
File,
|
|
62
|
+
Float,
|
|
63
|
+
HasPrivateTraits,
|
|
64
|
+
Instance,
|
|
65
|
+
Int,
|
|
66
|
+
List,
|
|
67
|
+
Property,
|
|
68
|
+
Tuple,
|
|
69
|
+
cached_property,
|
|
70
|
+
on_trait_change,
|
|
71
|
+
property_depends_on,
|
|
72
|
+
)
|
|
73
|
+
from traits.trait_errors import TraitError
|
|
74
|
+
|
|
40
75
|
from .internal import digest
|
|
41
76
|
|
|
42
77
|
|
|
43
|
-
def in_hull(p, hull, border=
|
|
44
|
-
"""
|
|
45
|
-
test if points in `p` are in `hull`
|
|
78
|
+
def in_hull(p, hull, border=True, tol=0):
|
|
79
|
+
"""Test if points in `p` are in `hull`
|
|
46
80
|
`p` should be a `NxK` coordinates of `N` points in `K` dimensions
|
|
47
|
-
`hull` is either a scipy.spatial.Delaunay object or the `MxK` array of the
|
|
81
|
+
`hull` is either a scipy.spatial.Delaunay object or the `MxK` array of the
|
|
48
82
|
coordinates of `M` points in `K`dimensions for which Delaunay triangulation
|
|
49
|
-
will be computed
|
|
83
|
+
will be computed.
|
|
50
84
|
"""
|
|
51
|
-
if not isinstance(hull,Delaunay):
|
|
85
|
+
if not isinstance(hull, Delaunay):
|
|
52
86
|
hull = Delaunay(hull)
|
|
53
|
-
|
|
87
|
+
|
|
54
88
|
if border:
|
|
55
|
-
return hull.find_simplex(p,tol
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
89
|
+
return hull.find_simplex(p, tol=tol) >= 0
|
|
90
|
+
return hull.find_simplex(p, tol=tol) > 0
|
|
91
|
+
|
|
59
92
|
|
|
60
93
|
def _det(xvert, yvert):
|
|
61
|
-
|
|
94
|
+
"""Compute twice the area of the triangle defined by points with using
|
|
62
95
|
determinant formula.
|
|
63
96
|
|
|
64
97
|
Input parameters:
|
|
@@ -69,14 +102,14 @@ def _det(xvert, yvert):
|
|
|
69
102
|
Output parameters:
|
|
70
103
|
Twice the area of the triangle defined by the points.
|
|
71
104
|
|
|
72
|
-
Notes
|
|
73
|
-
|
|
105
|
+
Notes
|
|
106
|
+
-----
|
|
74
107
|
_det is positive if points define polygon in anticlockwise order.
|
|
75
108
|
_det is negative if points define polygon in clockwise order.
|
|
76
109
|
_det is zero if at least two of the points are concident or if
|
|
77
110
|
all points are collinear.
|
|
78
111
|
|
|
79
|
-
|
|
112
|
+
"""
|
|
80
113
|
xvert = asfarray(xvert)
|
|
81
114
|
yvert = asfarray(yvert)
|
|
82
115
|
x_prev = concatenate(([xvert[-1]], xvert[:-1]))
|
|
@@ -85,15 +118,16 @@ def _det(xvert, yvert):
|
|
|
85
118
|
|
|
86
119
|
|
|
87
120
|
class Polygon:
|
|
88
|
-
|
|
121
|
+
"""Polygon object.
|
|
89
122
|
Input parameters:
|
|
90
123
|
x -- A sequence of nodal x-coords.
|
|
91
124
|
y -- A sequence of nodal y-coords.
|
|
92
|
-
|
|
125
|
+
"""
|
|
93
126
|
|
|
94
127
|
def __init__(self, x, y):
|
|
95
128
|
if len(x) != len(y):
|
|
96
|
-
|
|
129
|
+
msg = 'x and y must be equally sized.'
|
|
130
|
+
raise IndexError(msg)
|
|
97
131
|
self.x = asfarray(x)
|
|
98
132
|
self.y = asfarray(y)
|
|
99
133
|
# Closes the polygon if were open
|
|
@@ -108,7 +142,7 @@ class Polygon:
|
|
|
108
142
|
self.y = self.y[::-1]
|
|
109
143
|
|
|
110
144
|
def is_inside(self, xpoint, ypoint, smalld=1e-12):
|
|
111
|
-
|
|
145
|
+
"""Check if point is inside a general polygon.
|
|
112
146
|
|
|
113
147
|
Input parameters:
|
|
114
148
|
xpoint -- The x-coord of the point to be tested.
|
|
@@ -125,16 +159,17 @@ class Polygon:
|
|
|
125
159
|
If mindst = 0 then point in on a side of the polygon.
|
|
126
160
|
If mindst > 0 then point is inside the polygon.
|
|
127
161
|
|
|
128
|
-
Notes
|
|
162
|
+
Notes
|
|
163
|
+
-----
|
|
129
164
|
An improved version of the algorithm of Nordbeck and Rydstedt.
|
|
130
165
|
REF: SLOAN, S.W. (1985): A point-in-polygon program. Adv. Eng.
|
|
131
166
|
Software, Vol 7, No. 1, pp 45-47.
|
|
132
167
|
|
|
133
|
-
|
|
168
|
+
"""
|
|
134
169
|
xpoint = asfarray(xpoint)
|
|
135
170
|
ypoint = asfarray(ypoint)
|
|
136
171
|
# Scalar to array
|
|
137
|
-
if xpoint.shape
|
|
172
|
+
if xpoint.shape == ():
|
|
138
173
|
xpoint = array([xpoint], dtype=float)
|
|
139
174
|
ypoint = array([ypoint], dtype=float)
|
|
140
175
|
scalar = True
|
|
@@ -142,7 +177,8 @@ class Polygon:
|
|
|
142
177
|
scalar = False
|
|
143
178
|
# Check consistency
|
|
144
179
|
if xpoint.shape != ypoint.shape:
|
|
145
|
-
|
|
180
|
+
msg = 'x and y has different shapes'
|
|
181
|
+
raise IndexError(msg)
|
|
146
182
|
# If snear = True: Dist to nearest side < nearest vertex
|
|
147
183
|
# If snear = False: Dist to nearest vertex < nearest side
|
|
148
184
|
snear = ma.masked_all(xpoint.shape, dtype=bool)
|
|
@@ -172,12 +208,11 @@ class Polygon:
|
|
|
172
208
|
# t = 1 at (x2, y2)
|
|
173
209
|
# Find where normal passing through (xpoint, ypoint) intersects
|
|
174
210
|
# infinite line
|
|
175
|
-
t = -(x1p * x21 + y1p * y21) / (x21
|
|
211
|
+
t = -(x1p * x21 + y1p * y21) / (x21**2 + y21**2)
|
|
176
212
|
tlt0 = t < 0
|
|
177
|
-
tle1 = (
|
|
213
|
+
tle1 = (t >= 0) & (t <= 1)
|
|
178
214
|
# Normal intersects side
|
|
179
|
-
d[tle1] = (
|
|
180
|
-
(y1p[tle1] + t[tle1] * y21) ** 2)
|
|
215
|
+
d[tle1] = (x1p[tle1] + t[tle1] * x21) ** 2 + (y1p[tle1] + t[tle1] * y21) ** 2
|
|
181
216
|
# Normal does not intersects side
|
|
182
217
|
# Point is closest to vertex (x1, y1)
|
|
183
218
|
# Compute square of distance to this vertex
|
|
@@ -191,7 +226,8 @@ class Polygon:
|
|
|
191
226
|
# Point is closer to this side than to any other side or vertex
|
|
192
227
|
snear[mask & tle1] = True
|
|
193
228
|
if ma.count(snear) != snear.size:
|
|
194
|
-
|
|
229
|
+
msg = 'Error computing distances'
|
|
230
|
+
raise IndexError(msg)
|
|
195
231
|
mindst **= 0.5
|
|
196
232
|
# Point is closer to its nearest vertex than its nearest side, check if
|
|
197
233
|
# nearest vertex is concave.
|
|
@@ -215,10 +251,9 @@ class Polygon:
|
|
|
215
251
|
return mindst
|
|
216
252
|
|
|
217
253
|
|
|
218
|
-
class Grid(
|
|
219
|
-
"""
|
|
220
|
-
|
|
221
|
-
|
|
254
|
+
class Grid(HasPrivateTraits):
|
|
255
|
+
"""Virtual base class for grid geometries.
|
|
256
|
+
|
|
222
257
|
Defines the common interface for all grid classes and
|
|
223
258
|
provides facilities to query grid properties and related data. This class
|
|
224
259
|
may be used as a base for specialized grid implementaions. It should not
|
|
@@ -227,55 +262,54 @@ class Grid( HasPrivateTraits ):
|
|
|
227
262
|
|
|
228
263
|
#: Overall number of grid points. Readonly; is set automatically when
|
|
229
264
|
#: other grid defining properties are set
|
|
230
|
-
size = Property(desc=
|
|
265
|
+
size = Property(desc='overall number of grid points')
|
|
231
266
|
|
|
232
267
|
#: Shape of grid. Readonly, gives the shape as tuple, useful for cartesian
|
|
233
268
|
#: grids
|
|
234
|
-
shape = Property(desc=
|
|
269
|
+
shape = Property(desc='grid shape as tuple')
|
|
235
270
|
|
|
236
271
|
#: Grid positions as (3, :attr:`size`) array of floats, without invalid
|
|
237
272
|
#: microphones; readonly.
|
|
238
|
-
gpos = Property(desc=
|
|
273
|
+
gpos = Property(desc='x, y, z positions of grid points')
|
|
239
274
|
|
|
240
275
|
# internal identifier
|
|
241
276
|
digest = Property
|
|
242
277
|
|
|
243
|
-
def _get_digest(
|
|
278
|
+
def _get_digest(self):
|
|
244
279
|
return ''
|
|
245
280
|
|
|
246
281
|
# 'digest' is a placeholder for other properties in derived classes,
|
|
247
282
|
# necessary to trigger the depends on mechanism
|
|
248
283
|
@property_depends_on('digest')
|
|
249
|
-
def _get_size
|
|
284
|
+
def _get_size(self):
|
|
250
285
|
return 1
|
|
251
286
|
|
|
252
287
|
# 'digest' is a placeholder for other properties in derived classes
|
|
253
288
|
@property_depends_on('digest')
|
|
254
|
-
def _get_shape
|
|
289
|
+
def _get_shape(self):
|
|
255
290
|
return (1, 1)
|
|
256
291
|
|
|
257
292
|
@property_depends_on('digest')
|
|
258
|
-
def _get_gpos(
|
|
259
|
-
return array([[0.], [0.], [0.]])
|
|
260
|
-
|
|
261
|
-
def pos
|
|
262
|
-
"""
|
|
263
|
-
Calculates grid co-ordinates.
|
|
293
|
+
def _get_gpos(self):
|
|
294
|
+
return array([[0.0], [0.0], [0.0]])
|
|
295
|
+
|
|
296
|
+
def pos(self):
|
|
297
|
+
"""Calculates grid co-ordinates.
|
|
264
298
|
Deprecated; use :attr:`gpos` attribute instead.
|
|
265
|
-
|
|
299
|
+
|
|
266
300
|
Returns
|
|
267
301
|
-------
|
|
268
302
|
array of floats of shape (3, :attr:`size`)
|
|
269
303
|
The grid point x, y, z-coordinates in one array.
|
|
304
|
+
|
|
270
305
|
"""
|
|
271
|
-
return self.gpos# array([[0.], [0.], [0.]])
|
|
272
|
-
|
|
273
|
-
def subdomain
|
|
274
|
-
"""
|
|
275
|
-
|
|
276
|
-
|
|
306
|
+
return self.gpos # array([[0.], [0.], [0.]])
|
|
307
|
+
|
|
308
|
+
def subdomain(self, sector):
|
|
309
|
+
"""Queries the indices for a subdomain in the grid.
|
|
310
|
+
|
|
277
311
|
Allows arbitrary subdomains of type :class:`Sector`
|
|
278
|
-
|
|
312
|
+
|
|
279
313
|
Parameters
|
|
280
314
|
----------
|
|
281
315
|
sector : :class:`Sector`
|
|
@@ -284,10 +318,10 @@ class Grid( HasPrivateTraits ):
|
|
|
284
318
|
Returns
|
|
285
319
|
-------
|
|
286
320
|
2-tuple of arrays of integers or of numpy slice objects
|
|
287
|
-
The indices that can be used to mask/select the grid subdomain from
|
|
288
|
-
an array with the same shape as the grid.
|
|
321
|
+
The indices that can be used to mask/select the grid subdomain from
|
|
322
|
+
an array with the same shape as the grid.
|
|
323
|
+
|
|
289
324
|
"""
|
|
290
|
-
|
|
291
325
|
xpos = self.gpos
|
|
292
326
|
# construct grid-shaped array with "True" entries where sector is
|
|
293
327
|
xyi = sector.contains(xpos).reshape(self.shape)
|
|
@@ -295,101 +329,93 @@ class Grid( HasPrivateTraits ):
|
|
|
295
329
|
return where(xyi)
|
|
296
330
|
|
|
297
331
|
|
|
298
|
-
class RectGrid(
|
|
299
|
-
"""
|
|
300
|
-
|
|
301
|
-
|
|
332
|
+
class RectGrid(Grid):
|
|
333
|
+
"""Provides a cartesian 2D grid for the beamforming results.
|
|
334
|
+
|
|
302
335
|
The grid has square or nearly square cells and is on a plane perpendicular
|
|
303
|
-
to the z-axis. It is defined by lower and upper x- and y-limits and the
|
|
336
|
+
to the z-axis. It is defined by lower and upper x- and y-limits and the
|
|
304
337
|
z co-ordinate.
|
|
305
338
|
"""
|
|
306
|
-
|
|
339
|
+
|
|
307
340
|
#: The lower x-limit that defines the grid, defaults to -1.
|
|
308
|
-
x_min = Float(-1.0,
|
|
309
|
-
desc="minimum x-value")
|
|
341
|
+
x_min = Float(-1.0, desc='minimum x-value')
|
|
310
342
|
|
|
311
343
|
#: The upper x-limit that defines the grid, defaults to 1.
|
|
312
|
-
x_max = Float(1.0,
|
|
313
|
-
desc="maximum x-value")
|
|
344
|
+
x_max = Float(1.0, desc='maximum x-value')
|
|
314
345
|
|
|
315
346
|
#: The lower y-limit that defines the grid, defaults to -1.
|
|
316
|
-
y_min = Float(-1.0,
|
|
317
|
-
desc="minimum y-value")
|
|
347
|
+
y_min = Float(-1.0, desc='minimum y-value')
|
|
318
348
|
|
|
319
349
|
#: The upper y-limit that defines the grid, defaults to 1.
|
|
320
|
-
y_max = Float(1.0,
|
|
321
|
-
desc="maximum y-value")
|
|
350
|
+
y_max = Float(1.0, desc='maximum y-value')
|
|
322
351
|
|
|
323
352
|
#: The z co-ordinate that defines the grid, defaults to 1.
|
|
324
|
-
z = Float(1.0,
|
|
325
|
-
desc="position on z-axis")
|
|
353
|
+
z = Float(1.0, desc='position on z-axis')
|
|
326
354
|
|
|
327
355
|
#: The cell side length for the grid, defaults to 0.1.
|
|
328
|
-
increment = Float(0.1,
|
|
329
|
-
desc="step size")
|
|
356
|
+
increment = Float(0.1, desc='step size')
|
|
330
357
|
|
|
331
358
|
#: Number of grid points along x-axis, readonly.
|
|
332
|
-
nxsteps = Property(
|
|
333
|
-
desc="number of grid points along x-axis")
|
|
359
|
+
nxsteps = Property(desc='number of grid points along x-axis')
|
|
334
360
|
|
|
335
361
|
#: Number of grid points along y-axis, readonly.
|
|
336
|
-
nysteps = Property(
|
|
337
|
-
desc="number of grid points along y-axis")
|
|
362
|
+
nysteps = Property(desc='number of grid points along y-axis')
|
|
338
363
|
|
|
339
364
|
# internal identifier
|
|
340
365
|
digest = Property(
|
|
341
|
-
depends_on
|
|
342
|
-
|
|
366
|
+
depends_on=['x_min', 'x_max', 'y_min', 'y_max', 'z', 'increment'],
|
|
367
|
+
)
|
|
343
368
|
|
|
344
369
|
@property_depends_on('nxsteps, nysteps')
|
|
345
|
-
def _get_size
|
|
346
|
-
return self.nxsteps*self.nysteps
|
|
370
|
+
def _get_size(self):
|
|
371
|
+
return self.nxsteps * self.nysteps
|
|
347
372
|
|
|
348
373
|
@property_depends_on('nxsteps, nysteps')
|
|
349
|
-
def _get_shape
|
|
374
|
+
def _get_shape(self):
|
|
350
375
|
return (self.nxsteps, self.nysteps)
|
|
351
376
|
|
|
352
377
|
@property_depends_on('x_min, x_max, increment')
|
|
353
|
-
def _get_nxsteps
|
|
378
|
+
def _get_nxsteps(self):
|
|
354
379
|
i = abs(self.increment)
|
|
355
380
|
if i != 0:
|
|
356
|
-
return int(round((abs(self.x_max-self.x_min)+i)/i))
|
|
381
|
+
return int(round((abs(self.x_max - self.x_min) + i) / i))
|
|
357
382
|
return 1
|
|
358
383
|
|
|
359
384
|
@property_depends_on('y_min, y_max, increment')
|
|
360
|
-
def _get_nysteps
|
|
385
|
+
def _get_nysteps(self):
|
|
361
386
|
i = abs(self.increment)
|
|
362
387
|
if i != 0:
|
|
363
|
-
return int(round((abs(self.y_max-self.y_min)+i)/i))
|
|
388
|
+
return int(round((abs(self.y_max - self.y_min) + i) / i))
|
|
364
389
|
return 1
|
|
365
390
|
|
|
366
391
|
@cached_property
|
|
367
|
-
def _get_digest(
|
|
368
|
-
return digest(
|
|
392
|
+
def _get_digest(self):
|
|
393
|
+
return digest(self)
|
|
369
394
|
|
|
370
395
|
@property_depends_on('x_min, x_max, y_min, y_max, increment')
|
|
371
|
-
def _get_gpos
|
|
372
|
-
"""
|
|
373
|
-
|
|
374
|
-
|
|
396
|
+
def _get_gpos(self):
|
|
397
|
+
"""Calculates grid co-ordinates.
|
|
398
|
+
|
|
375
399
|
Returns
|
|
376
400
|
-------
|
|
377
401
|
array of floats of shape (3, :attr:`~Grid.size`)
|
|
378
402
|
The grid point x, y, z-coordinates in one array.
|
|
403
|
+
|
|
379
404
|
"""
|
|
380
|
-
bpos = mgrid[
|
|
381
|
-
|
|
382
|
-
|
|
405
|
+
bpos = mgrid[
|
|
406
|
+
self.x_min : self.x_max : self.nxsteps * 1j,
|
|
407
|
+
self.y_min : self.y_max : self.nysteps * 1j,
|
|
408
|
+
self.z : self.z + 0.1,
|
|
409
|
+
]
|
|
383
410
|
bpos.resize((3, self.size))
|
|
384
411
|
return bpos
|
|
385
412
|
|
|
386
|
-
def index
|
|
387
|
-
"""
|
|
388
|
-
Queries the indices for a grid point near a certain co-ordinate.
|
|
413
|
+
def index(self, x, y):
|
|
414
|
+
"""Queries the indices for a grid point near a certain co-ordinate.
|
|
389
415
|
|
|
390
416
|
This can be used to query results or co-ordinates at/near a certain
|
|
391
417
|
co-ordinate.
|
|
392
|
-
|
|
418
|
+
|
|
393
419
|
Parameters
|
|
394
420
|
----------
|
|
395
421
|
x, y : float
|
|
@@ -399,235 +425,215 @@ class RectGrid( Grid ):
|
|
|
399
425
|
-------
|
|
400
426
|
2-tuple of integers
|
|
401
427
|
The indices that give the grid point nearest to the given x, y
|
|
402
|
-
co-ordinates from an array with the same shape as the grid.
|
|
428
|
+
co-ordinates from an array with the same shape as the grid.
|
|
429
|
+
|
|
403
430
|
"""
|
|
404
431
|
if x < self.x_min or x > self.x_max:
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
432
|
+
msg = 'x-value out of range'
|
|
433
|
+
raise ValueError(msg)
|
|
434
|
+
if y < self.y_min or y > self.y_max:
|
|
435
|
+
msg = 'y-value out of range'
|
|
436
|
+
raise ValueError(msg)
|
|
437
|
+
xi = int((x - self.x_min) / self.increment + 0.5)
|
|
438
|
+
yi = int((y - self.y_min) / self.increment + 0.5)
|
|
410
439
|
return xi, yi
|
|
411
440
|
|
|
412
|
-
def indices
|
|
413
|
-
"""
|
|
414
|
-
|
|
415
|
-
|
|
441
|
+
def indices(self, *r):
|
|
442
|
+
"""Queries the indices for a subdomain in the grid.
|
|
443
|
+
|
|
416
444
|
Allows either rectangular, circular or polygonial subdomains.
|
|
417
|
-
This can be used to mask or to query results from a certain
|
|
445
|
+
This can be used to mask or to query results from a certain
|
|
418
446
|
sector or subdomain.
|
|
419
|
-
|
|
447
|
+
|
|
420
448
|
Parameters
|
|
421
449
|
----------
|
|
422
450
|
x1, y1, x2, y2, ... : float
|
|
423
451
|
If three parameters are given, then a circular sector is assumed
|
|
424
452
|
that is given by its center (x1, y1) and the radius x2.
|
|
425
453
|
If four paramters are given, then a rectangular sector is
|
|
426
|
-
assumed that is given by two corners (x1, y1) and (x2, y2).
|
|
454
|
+
assumed that is given by two corners (x1, y1) and (x2, y2).
|
|
427
455
|
If more parameters are given, the subdomain is assumed to have
|
|
428
456
|
polygonial shape with corners at (x_n, y_n).
|
|
429
457
|
|
|
430
458
|
Returns
|
|
431
459
|
-------
|
|
432
460
|
2-tuple of arrays of integers or of numpy slice objects
|
|
433
|
-
The indices that can be used to mask/select the grid subdomain from
|
|
434
|
-
an array with the same shape as the grid.
|
|
461
|
+
The indices that can be used to mask/select the grid subdomain from
|
|
462
|
+
an array with the same shape as the grid.
|
|
463
|
+
|
|
435
464
|
"""
|
|
436
|
-
|
|
437
|
-
if len(r) == 3: # only 3 values given -> use x,y,radius method
|
|
465
|
+
if len(r) == 3: # only 3 values given -> use x,y,radius method
|
|
438
466
|
xpos = self.gpos
|
|
439
467
|
xis = []
|
|
440
468
|
yis = []
|
|
441
|
-
dr2 = (xpos[0, :]-r[0])**2 + (xpos[1, :]-r[1])**2
|
|
469
|
+
dr2 = (xpos[0, :] - r[0]) ** 2 + (xpos[1, :] - r[1]) ** 2
|
|
442
470
|
# array with true/false entries
|
|
443
|
-
inds = dr2 <= r[2]**2
|
|
444
|
-
for np in arange(self.size)[inds]:
|
|
471
|
+
inds = dr2 <= r[2] ** 2
|
|
472
|
+
for np in arange(self.size)[inds]: # np -- points in x2-circle
|
|
445
473
|
xi, yi = self.index(xpos[0, np], xpos[1, np])
|
|
446
474
|
xis += [xi]
|
|
447
475
|
yis += [yi]
|
|
448
|
-
if not (xis and yis):
|
|
476
|
+
if not (xis and yis): # if no points in circle, take nearest one
|
|
449
477
|
return self.index(r[0], r[1])
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
elif len(r) == 4: # rectangular subdomain - old functionality
|
|
478
|
+
return array(xis), array(yis)
|
|
479
|
+
if len(r) == 4: # rectangular subdomain - old functionality
|
|
453
480
|
xi1, yi1 = self.index(min(r[0], r[2]), min(r[1], r[3]))
|
|
454
481
|
xi2, yi2 = self.index(max(r[0], r[2]), max(r[1], r[3]))
|
|
455
|
-
return s_[xi1:xi2+1], s_[yi1:yi2+1]
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
def extend (self) :
|
|
479
|
-
"""
|
|
480
|
-
The extension of the grid in pylab.imshow compatible form.
|
|
482
|
+
return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1]
|
|
483
|
+
xpos = self.gpos
|
|
484
|
+
xis = []
|
|
485
|
+
yis = []
|
|
486
|
+
# replaced matplotlib Path by numpy
|
|
487
|
+
# p = Path(array(r).reshape(-1,2))
|
|
488
|
+
# inds = p.contains_points()
|
|
489
|
+
# inds = in_poly(xpos[:2,:].T,array(r).reshape(-1,2))
|
|
490
|
+
poly = Polygon(array(r).reshape(-1, 2)[:, 0], array(r).reshape(-1, 2)[:, 1])
|
|
491
|
+
dists = poly.is_inside(xpos[0, :], xpos[1, :])
|
|
492
|
+
inds = dists >= 0
|
|
493
|
+
for np in arange(self.size)[inds]: # np -- points in x2-circle
|
|
494
|
+
xi, yi = self.index(xpos[0, np], xpos[1, np])
|
|
495
|
+
xis += [xi]
|
|
496
|
+
yis += [yi]
|
|
497
|
+
if not (xis and yis): # if no points inside, take nearest to center
|
|
498
|
+
center = array(r).reshape(-1, 2).mean(0)
|
|
499
|
+
return self.index(center[0], center[1])
|
|
500
|
+
return array(xis), array(yis)
|
|
501
|
+
# return arange(self.size)[inds]
|
|
502
|
+
|
|
503
|
+
def extend(self):
|
|
504
|
+
"""The extension of the grid in pylab.imshow compatible form.
|
|
481
505
|
|
|
482
506
|
Returns
|
|
483
507
|
-------
|
|
484
508
|
4-tuple of floats
|
|
485
509
|
The extent of the grid as a tuple of x_min, x_max, y_min, y_max)
|
|
510
|
+
|
|
486
511
|
"""
|
|
487
512
|
return (self.x_min, self.x_max, self.y_min, self.y_max)
|
|
488
513
|
|
|
489
514
|
|
|
490
|
-
class RectGrid3D(
|
|
491
|
-
"""
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
The grid has cubic or nearly cubic cells. It is defined by lower and upper
|
|
515
|
+
class RectGrid3D(RectGrid):
|
|
516
|
+
"""Provides a cartesian 3D grid for the beamforming results.
|
|
517
|
+
|
|
518
|
+
The grid has cubic or nearly cubic cells. It is defined by lower and upper
|
|
495
519
|
x-, y- and z-limits.
|
|
496
520
|
"""
|
|
497
521
|
|
|
498
522
|
#: The lower z-limit that defines the grid, defaults to -1.
|
|
499
|
-
z_min = Float(-1.0,
|
|
500
|
-
desc="minimum z-value")
|
|
523
|
+
z_min = Float(-1.0, desc='minimum z-value')
|
|
501
524
|
|
|
502
525
|
#: The upper z-limit that defines the grid, defaults to 1.
|
|
503
|
-
z_max = Float(1.0,
|
|
504
|
-
desc="maximum z-value")
|
|
526
|
+
z_max = Float(1.0, desc='maximum z-value')
|
|
505
527
|
|
|
506
528
|
#: Number of grid points along x-axis, readonly.
|
|
507
|
-
nxsteps = Property(
|
|
508
|
-
desc="number of grid points along x-axis")
|
|
529
|
+
nxsteps = Property(desc='number of grid points along x-axis')
|
|
509
530
|
|
|
510
531
|
#: Number of grid points along y-axis, readonly.
|
|
511
|
-
nysteps = Property(
|
|
512
|
-
desc="number of grid points along y-axis")
|
|
532
|
+
nysteps = Property(desc='number of grid points along y-axis')
|
|
513
533
|
|
|
514
534
|
#: Number of grid points along x-axis, readonly.
|
|
515
|
-
nzsteps = Property(
|
|
516
|
-
desc="number of grid points along x-axis")
|
|
535
|
+
nzsteps = Property(desc='number of grid points along x-axis')
|
|
517
536
|
|
|
518
|
-
|
|
519
537
|
# Private trait for increment handling
|
|
520
538
|
_increment = Any(0.1)
|
|
521
|
-
|
|
522
|
-
#: The cell side length for the grid. This can either be a scalar (same
|
|
523
|
-
#: increments in all 3 dimensions) or a (3,) array of floats with
|
|
524
|
-
#: respective increments in x,y, and z-direction (in m).
|
|
539
|
+
|
|
540
|
+
#: The cell side length for the grid. This can either be a scalar (same
|
|
541
|
+
#: increments in all 3 dimensions) or a (3,) array of floats with
|
|
542
|
+
#: respective increments in x,y, and z-direction (in m).
|
|
525
543
|
#: Defaults to 0.1.
|
|
526
|
-
increment = Property(desc=
|
|
527
|
-
|
|
544
|
+
increment = Property(desc='step size')
|
|
545
|
+
|
|
528
546
|
def _get_increment(self):
|
|
529
547
|
return self._increment
|
|
530
|
-
|
|
548
|
+
|
|
531
549
|
def _set_increment(self, increment):
|
|
532
550
|
if isscalar(increment):
|
|
533
551
|
try:
|
|
534
552
|
self._increment = absolute(float(increment))
|
|
535
553
|
except:
|
|
536
|
-
raise TraitError(args=self,
|
|
537
|
-
name='increment',
|
|
538
|
-
info='Float or CArray(3,)',
|
|
539
|
-
value=increment)
|
|
554
|
+
raise TraitError(args=self, name='increment', info='Float or CArray(3,)', value=increment)
|
|
540
555
|
elif len(increment) == 3:
|
|
541
|
-
self._increment = array(increment,dtype=float)
|
|
556
|
+
self._increment = array(increment, dtype=float)
|
|
542
557
|
else:
|
|
543
|
-
raise(TraitError(args=self,
|
|
544
|
-
|
|
545
|
-
info='Float or CArray(3,)',
|
|
546
|
-
value=increment))
|
|
547
|
-
|
|
558
|
+
raise (TraitError(args=self, name='increment', info='Float or CArray(3,)', value=increment))
|
|
559
|
+
|
|
548
560
|
# Respective increments in x,y, and z-direction (in m).
|
|
549
561
|
# Deprecated: Use :attr:`~RectGrid.increment` for this functionality
|
|
550
|
-
increment3D = Property(desc=
|
|
551
|
-
|
|
562
|
+
increment3D = Property(desc='3D step sizes')
|
|
563
|
+
|
|
552
564
|
def _get_increment3D(self):
|
|
553
565
|
if isscalar(self._increment):
|
|
554
|
-
return array([self._increment,self._increment,self._increment])
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
566
|
+
return array([self._increment, self._increment, self._increment])
|
|
567
|
+
return self._increment
|
|
568
|
+
|
|
558
569
|
def _set_increment3D(self, inc):
|
|
559
570
|
if not isscalar(inc) and len(inc) == 3:
|
|
560
|
-
self._increment = array(inc,dtype=float)
|
|
571
|
+
self._increment = array(inc, dtype=float)
|
|
561
572
|
else:
|
|
562
|
-
raise(TraitError(args=self,
|
|
563
|
-
|
|
564
|
-
info='CArray(3,)',
|
|
565
|
-
value=inc))
|
|
566
|
-
|
|
573
|
+
raise (TraitError(args=self, name='increment3D', info='CArray(3,)', value=inc))
|
|
574
|
+
|
|
567
575
|
# internal identifier
|
|
568
576
|
digest = Property(
|
|
569
|
-
depends_on
|
|
570
|
-
|
|
571
|
-
)
|
|
577
|
+
depends_on=['x_min', 'x_max', 'y_min', 'y_max', 'z_min', 'z_max', '_increment'],
|
|
578
|
+
)
|
|
572
579
|
|
|
573
580
|
@property_depends_on('nxsteps, nysteps, nzsteps')
|
|
574
|
-
def _get_size
|
|
575
|
-
return self.nxsteps*self.nysteps*self.nzsteps
|
|
581
|
+
def _get_size(self):
|
|
582
|
+
return self.nxsteps * self.nysteps * self.nzsteps
|
|
576
583
|
|
|
577
584
|
@property_depends_on('nxsteps, nysteps, nzsteps')
|
|
578
|
-
def _get_shape
|
|
585
|
+
def _get_shape(self):
|
|
579
586
|
return (self.nxsteps, self.nysteps, self.nzsteps)
|
|
580
|
-
|
|
587
|
+
|
|
581
588
|
@property_depends_on('x_min, x_max, _increment')
|
|
582
|
-
def _get_nxsteps
|
|
589
|
+
def _get_nxsteps(self):
|
|
583
590
|
i = abs(self.increment3D[0])
|
|
584
591
|
if i != 0:
|
|
585
|
-
return int(round((abs(self.x_max-self.x_min)+i)/i))
|
|
592
|
+
return int(round((abs(self.x_max - self.x_min) + i) / i))
|
|
586
593
|
return 1
|
|
587
594
|
|
|
588
595
|
@property_depends_on('y_min, y_max, _increment')
|
|
589
|
-
def _get_nysteps
|
|
596
|
+
def _get_nysteps(self):
|
|
590
597
|
i = abs(self.increment3D[1])
|
|
591
598
|
if i != 0:
|
|
592
|
-
return int(round((abs(self.y_max-self.y_min)+i)/i))
|
|
599
|
+
return int(round((abs(self.y_max - self.y_min) + i) / i))
|
|
593
600
|
return 1
|
|
594
|
-
|
|
601
|
+
|
|
595
602
|
@property_depends_on('z_min, z_max, _increment')
|
|
596
|
-
def _get_nzsteps
|
|
603
|
+
def _get_nzsteps(self):
|
|
597
604
|
i = abs(self.increment3D[2])
|
|
598
605
|
if i != 0:
|
|
599
|
-
return int(round((abs(self.z_max-self.z_min)+i)/i))
|
|
606
|
+
return int(round((abs(self.z_max - self.z_min) + i) / i))
|
|
600
607
|
return 1
|
|
601
608
|
|
|
602
609
|
@property_depends_on('digest')
|
|
603
|
-
def _get_gpos
|
|
604
|
-
"""
|
|
605
|
-
|
|
606
|
-
|
|
610
|
+
def _get_gpos(self):
|
|
611
|
+
"""Calculates grid co-ordinates.
|
|
612
|
+
|
|
607
613
|
Returns
|
|
608
614
|
-------
|
|
609
615
|
array of floats of shape (3, :attr:`~Grid.size`)
|
|
610
616
|
The grid point x, y, z-coordinates in one array.
|
|
617
|
+
|
|
611
618
|
"""
|
|
612
|
-
bpos = mgrid[
|
|
613
|
-
|
|
614
|
-
|
|
619
|
+
bpos = mgrid[
|
|
620
|
+
self.x_min : self.x_max : self.nxsteps * 1j,
|
|
621
|
+
self.y_min : self.y_max : self.nysteps * 1j,
|
|
622
|
+
self.z_min : self.z_max : self.nzsteps * 1j,
|
|
623
|
+
]
|
|
615
624
|
bpos.resize((3, self.size))
|
|
616
625
|
return bpos
|
|
617
626
|
|
|
618
627
|
@cached_property
|
|
619
|
-
def _get_digest(
|
|
620
|
-
return digest(
|
|
621
|
-
|
|
622
|
-
|
|
628
|
+
def _get_digest(self):
|
|
629
|
+
return digest(self)
|
|
623
630
|
|
|
624
|
-
def index
|
|
625
|
-
"""
|
|
626
|
-
Queries the indices for a grid point near a certain co-ordinate.
|
|
631
|
+
def index(self, x, y, z):
|
|
632
|
+
"""Queries the indices for a grid point near a certain co-ordinate.
|
|
627
633
|
|
|
628
634
|
This can be used to query results or co-ordinates at/near a certain
|
|
629
635
|
co-ordinate.
|
|
630
|
-
|
|
636
|
+
|
|
631
637
|
Parameters
|
|
632
638
|
----------
|
|
633
639
|
x, y, z : float
|
|
@@ -637,104 +643,91 @@ class RectGrid3D( RectGrid):
|
|
|
637
643
|
-------
|
|
638
644
|
3-tuple of integers
|
|
639
645
|
The indices that give the grid point nearest to the given x, y, z
|
|
640
|
-
co-ordinates from an array with the same shape as the grid.
|
|
646
|
+
co-ordinates from an array with the same shape as the grid.
|
|
647
|
+
|
|
641
648
|
"""
|
|
642
649
|
if x < self.x_min or x > self.x_max:
|
|
643
|
-
|
|
644
|
-
|
|
650
|
+
msg = f'x-value out of range {x:f} ({self.x_min:f}, {self.x_max:f})'
|
|
651
|
+
raise ValueError(msg)
|
|
645
652
|
if y < self.y_min or y > self.y_max:
|
|
646
|
-
|
|
647
|
-
|
|
653
|
+
msg = f'y-value out of range {y:f} ({self.y_min:f}, {self.y_max:f})'
|
|
654
|
+
raise ValueError(msg)
|
|
648
655
|
if z < self.z_min or z > self.z_max:
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
xi = int(round((x-self.x_min)/self.increment3D[0]))
|
|
652
|
-
yi = int(round((y-self.y_min)/self.increment3D[1]))
|
|
653
|
-
zi = int(round((z-self.z_min)/self.increment3D[2]))
|
|
656
|
+
msg = f'z-value out of range {z:f} ({self.z_min:f}, {self.z_max:f})'
|
|
657
|
+
raise ValueError(msg)
|
|
658
|
+
xi = int(round((x - self.x_min) / self.increment3D[0]))
|
|
659
|
+
yi = int(round((y - self.y_min) / self.increment3D[1]))
|
|
660
|
+
zi = int(round((z - self.z_min) / self.increment3D[2]))
|
|
654
661
|
return xi, yi, zi
|
|
655
662
|
|
|
656
|
-
def indices
|
|
657
|
-
"""
|
|
658
|
-
|
|
659
|
-
|
|
663
|
+
def indices(self, x1, y1, z1, x2, y2, z2):
|
|
664
|
+
"""Queries the indices for a subdomain in the grid.
|
|
665
|
+
|
|
660
666
|
Allows box-shaped subdomains. This can be used to
|
|
661
667
|
mask or to query results from a certain sector or subdomain.
|
|
662
|
-
|
|
668
|
+
|
|
663
669
|
Parameters
|
|
664
670
|
----------
|
|
665
671
|
x1, y1, z1, x2, y2, z2 : float
|
|
666
672
|
A box-shaped sector is assumed that is given by two corners
|
|
667
|
-
(x1,y1,z1) and (x2,y2,z2).
|
|
673
|
+
(x1,y1,z1) and (x2,y2,z2).
|
|
668
674
|
|
|
669
675
|
Returns
|
|
670
676
|
-------
|
|
671
677
|
3-tuple of numpy slice objects
|
|
672
|
-
The indices that can be used to mask/select the grid subdomain from
|
|
673
|
-
an array with the same shape as the grid.
|
|
678
|
+
The indices that can be used to mask/select the grid subdomain from
|
|
679
|
+
an array with the same shape as the grid.
|
|
680
|
+
|
|
674
681
|
"""
|
|
675
682
|
xi1, yi1, zi1 = self.index(min(x1, x2), min(y1, y2), min(z1, z2))
|
|
676
683
|
xi2, yi2, zi2 = self.index(max(x1, x2), max(y1, y2), max(z1, z2))
|
|
677
|
-
return s_[xi1:xi2+1], s_[yi1:yi2+1], s_[zi1:zi2+1]
|
|
684
|
+
return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1], s_[zi1 : zi2 + 1]
|
|
678
685
|
|
|
679
686
|
|
|
680
|
-
class ImportGrid(
|
|
681
|
-
"""
|
|
682
|
-
Loads a 3D grid from xml file.
|
|
683
|
-
"""
|
|
687
|
+
class ImportGrid(Grid):
|
|
688
|
+
"""Loads a 3D grid from xml file."""
|
|
684
689
|
|
|
685
|
-
# internal identifier
|
|
686
|
-
digest = Property
|
|
687
|
-
|
|
688
690
|
#: Name of the .xml-file from wich to read the data.
|
|
689
|
-
from_file = File(filter=['*.xml'],
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
gpos_file = CArray(dtype=float,
|
|
694
|
-
desc="x, y, z position of all Grid Points")
|
|
695
|
-
|
|
691
|
+
from_file = File(filter=['*.xml'], desc='name of the xml file to import')
|
|
692
|
+
|
|
693
|
+
gpos_file = CArray(dtype=float, desc='x, y, z position of all Grid Points')
|
|
696
694
|
|
|
697
695
|
#: Basename of the .xml-file, without the extension; is set automatically / readonly.
|
|
698
|
-
basename = Property(
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
# internal identifier
|
|
696
|
+
basename = Property(depends_on='from_file', desc='basename of xml file')
|
|
697
|
+
|
|
698
|
+
# internal identifier
|
|
702
699
|
digest = Property(
|
|
703
|
-
depends_on
|
|
704
|
-
|
|
705
|
-
|
|
700
|
+
depends_on=['from_file'],
|
|
701
|
+
)
|
|
702
|
+
|
|
706
703
|
@cached_property
|
|
707
|
-
def _get_basename(
|
|
704
|
+
def _get_basename(self):
|
|
708
705
|
return path.splitext(path.basename(self.from_file))[0]
|
|
709
706
|
|
|
710
707
|
@cached_property
|
|
711
|
-
def _get_digest(
|
|
712
|
-
return digest(
|
|
708
|
+
def _get_digest(self):
|
|
709
|
+
return digest(self)
|
|
713
710
|
|
|
714
711
|
# 'digest' is a placeholder for other properties in derived classes,
|
|
715
712
|
# necessary to trigger the depends on mechanism
|
|
716
713
|
@property_depends_on('basename')
|
|
717
|
-
def _get_size
|
|
714
|
+
def _get_size(self):
|
|
718
715
|
return self.gpos.shape[-1]
|
|
719
716
|
|
|
720
717
|
# 'digest' is a placeholder for other properties in derived classes
|
|
721
718
|
@property_depends_on('basename')
|
|
722
|
-
def _get_shape
|
|
719
|
+
def _get_shape(self):
|
|
723
720
|
return (self.gpos.shape[-1],)
|
|
724
721
|
|
|
725
722
|
@property_depends_on('basename')
|
|
726
|
-
def _get_gpos(
|
|
723
|
+
def _get_gpos(self):
|
|
727
724
|
return self.gpos_file
|
|
728
725
|
|
|
726
|
+
subgrids = CArray(desc='names of subgrids for each point')
|
|
729
727
|
|
|
730
|
-
subgrids = CArray(
|
|
731
|
-
desc="names of subgrids for each point")
|
|
732
|
-
|
|
733
|
-
|
|
734
728
|
@on_trait_change('basename')
|
|
735
|
-
def import_gpos(
|
|
736
|
-
"""
|
|
737
|
-
Import the the grid point locations from .xml file.
|
|
729
|
+
def import_gpos(self):
|
|
730
|
+
"""Import the the grid point locations from .xml file.
|
|
738
731
|
Called when :attr:`basename` changes.
|
|
739
732
|
"""
|
|
740
733
|
if not path.isfile(self.from_file):
|
|
@@ -742,98 +735,93 @@ class ImportGrid( Grid ):
|
|
|
742
735
|
self.gpos_file = array([], 'd')
|
|
743
736
|
return
|
|
744
737
|
import xml.dom.minidom
|
|
738
|
+
|
|
745
739
|
doc = xml.dom.minidom.parse(self.from_file)
|
|
746
740
|
names = []
|
|
747
741
|
xyz = []
|
|
748
742
|
for el in doc.getElementsByTagName('pos'):
|
|
749
743
|
names.append(el.getAttribute('subgrid'))
|
|
750
|
-
xyz.append(
|
|
744
|
+
xyz.append([float(el.getAttribute(a)) for a in 'xyz'])
|
|
751
745
|
self.gpos_file = array(xyz, 'd').swapaxes(0, 1)
|
|
752
746
|
self.subgrids = array(names)
|
|
753
747
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
Class for Line grid geometries.
|
|
757
|
-
|
|
758
|
-
"""
|
|
759
|
-
|
|
748
|
+
|
|
749
|
+
class LineGrid(Grid):
|
|
750
|
+
"""Class for Line grid geometries."""
|
|
751
|
+
|
|
760
752
|
#: Staring point of the Grid
|
|
761
753
|
loc = Tuple((0.0, 0.0, 0.0))
|
|
762
754
|
|
|
763
755
|
#: Vector to define the orientation of the line source
|
|
764
|
-
direction = Tuple((1.0, 0.0, 0.0),
|
|
765
|
-
|
|
766
|
-
|
|
756
|
+
direction = Tuple((1.0, 0.0, 0.0), desc='Line orientation ')
|
|
757
|
+
|
|
767
758
|
#: Vector to define the length of the line source in meter
|
|
768
|
-
length = Float(1,desc=
|
|
769
|
-
|
|
759
|
+
length = Float(1, desc='length of the line source')
|
|
760
|
+
|
|
770
761
|
#:number of grid points.
|
|
771
|
-
numpoints = Int(1,desc=
|
|
772
|
-
|
|
762
|
+
numpoints = Int(1, desc='length of the line source')
|
|
763
|
+
|
|
773
764
|
#: Overall number of grid points. Readonly; is set automatically when
|
|
774
765
|
#: other grid defining properties are set
|
|
775
|
-
size = Property(desc=
|
|
766
|
+
size = Property(desc='overall number of grid points')
|
|
776
767
|
|
|
777
768
|
#: Grid positions as (3, :attr:`size`) array of floats, without invalid
|
|
778
769
|
#: microphones; readonly.
|
|
779
|
-
gpos = Property(desc=
|
|
770
|
+
gpos = Property(desc='x, y, z positions of grid points')
|
|
780
771
|
|
|
781
772
|
digest = Property(
|
|
782
|
-
|
|
773
|
+
depends_on=['loc', 'direction', 'length', 'numpoints', 'size'],
|
|
783
774
|
)
|
|
784
775
|
|
|
785
776
|
@cached_property
|
|
786
|
-
def _get_digest(
|
|
787
|
-
return digest(
|
|
777
|
+
def _get_digest(self):
|
|
778
|
+
return digest(self)
|
|
788
779
|
|
|
789
780
|
# 'digest' is a placeholder for other properties in derived classes,
|
|
790
781
|
# necessary to trigger the depends on mechanism
|
|
791
782
|
@property_depends_on('numpoints')
|
|
792
|
-
def _get_size
|
|
783
|
+
def _get_size(self):
|
|
793
784
|
return self.gpos.shape[-1]
|
|
794
785
|
|
|
795
786
|
# 'digest' is a placeholder for other properties in derived classes
|
|
796
787
|
@property_depends_on('numpoints')
|
|
797
|
-
def _get_shape
|
|
788
|
+
def _get_shape(self):
|
|
798
789
|
return self.gpos.shape[-1]
|
|
799
790
|
|
|
800
791
|
@property_depends_on('numpoints,length,direction,loc')
|
|
801
|
-
def _get_gpos(
|
|
792
|
+
def _get_gpos(self):
|
|
802
793
|
dist = self.length / (self.numpoints - 1)
|
|
803
|
-
loc = array(self.loc, dtype
|
|
804
|
-
direc_n = self.direction/norm(self.direction)
|
|
805
|
-
pos = zeros((self.numpoints,3))
|
|
794
|
+
loc = array(self.loc, dtype=float).reshape((3, 1))
|
|
795
|
+
direc_n = self.direction / norm(self.direction)
|
|
796
|
+
pos = zeros((self.numpoints, 3))
|
|
806
797
|
for s in range(self.numpoints):
|
|
807
|
-
pos[s] =
|
|
798
|
+
pos[s] = loc.T + direc_n * dist * s
|
|
808
799
|
return pos.T
|
|
809
800
|
|
|
810
801
|
|
|
811
|
-
class MergeGrid(
|
|
812
|
-
"""
|
|
813
|
-
Base class for merging different grid geometries.
|
|
814
|
-
|
|
815
|
-
"""
|
|
802
|
+
class MergeGrid(Grid):
|
|
803
|
+
"""Base class for merging different grid geometries."""
|
|
816
804
|
|
|
817
805
|
#: List of Grids to be merged
|
|
818
806
|
#: each grid gets a new subdomain in the new grid
|
|
819
807
|
#: other grid defining properties are set
|
|
820
|
-
grids = List(desc=
|
|
821
|
-
|
|
822
|
-
grid_digest = Property(desc=
|
|
808
|
+
grids = List(desc='list of grids')
|
|
809
|
+
|
|
810
|
+
grid_digest = Property(desc='digest of the merged grids')
|
|
811
|
+
|
|
812
|
+
subgrids = Property(desc='names of subgrids for each point')
|
|
823
813
|
|
|
824
|
-
subgrids = Property(desc="names of subgrids for each point")
|
|
825
|
-
|
|
826
814
|
# internal identifier
|
|
827
815
|
digest = Property(
|
|
828
|
-
|
|
816
|
+
depends_on=['grids', 'grid_digest'],
|
|
829
817
|
)
|
|
830
818
|
|
|
831
819
|
@cached_property
|
|
832
|
-
def _get_digest(
|
|
833
|
-
return digest(
|
|
834
|
-
|
|
820
|
+
def _get_digest(self):
|
|
821
|
+
return digest(self)
|
|
822
|
+
|
|
835
823
|
@cached_property
|
|
836
|
-
def _get_grid_digest(
|
|
824
|
+
def _get_grid_digest(self):
|
|
837
825
|
griddigest = []
|
|
838
826
|
for grid in self.grids:
|
|
839
827
|
griddigest.append(grid.digest)
|
|
@@ -842,409 +830,377 @@ class MergeGrid( Grid ):
|
|
|
842
830
|
# 'digest' is a placeholder for other properties in derived classes,
|
|
843
831
|
# necessary to trigger the depends on mechanism
|
|
844
832
|
@property_depends_on('digest')
|
|
845
|
-
def _get_size
|
|
833
|
+
def _get_size(self):
|
|
846
834
|
return self.gpos.shape[-1]
|
|
847
835
|
|
|
848
836
|
# 'digest' is a placeholder for other properties in derived classes
|
|
849
837
|
@property_depends_on('digest')
|
|
850
|
-
def _get_shape
|
|
838
|
+
def _get_shape(self):
|
|
851
839
|
return self.gpos.shape[-1]
|
|
852
|
-
|
|
840
|
+
|
|
853
841
|
@property_depends_on('digest')
|
|
854
|
-
def _get_subgrids(
|
|
855
|
-
subgrids = zeros((1,0),dtype=str)
|
|
842
|
+
def _get_subgrids(self):
|
|
843
|
+
subgrids = zeros((1, 0), dtype=str)
|
|
856
844
|
for grid in self.grids:
|
|
857
|
-
subgrids = append(subgrids,tile(grid.__class__.__name__+grid.digest,grid.size))
|
|
858
|
-
return subgrids[:,newaxis].T
|
|
859
|
-
|
|
845
|
+
subgrids = append(subgrids, tile(grid.__class__.__name__ + grid.digest, grid.size))
|
|
846
|
+
return subgrids[:, newaxis].T
|
|
847
|
+
|
|
860
848
|
@property_depends_on('digest')
|
|
861
|
-
def _get_gpos(
|
|
862
|
-
bpos = zeros((3,0))
|
|
863
|
-
#subgrids = zeros((1,0))
|
|
849
|
+
def _get_gpos(self):
|
|
850
|
+
bpos = zeros((3, 0))
|
|
851
|
+
# subgrids = zeros((1,0))
|
|
864
852
|
for grid in self.grids:
|
|
865
|
-
bpos = append(bpos,grid.gpos, axis
|
|
866
|
-
#subgrids = append(subgrids,str(grid))
|
|
867
|
-
|
|
868
|
-
|
|
853
|
+
bpos = append(bpos, grid.gpos, axis=1)
|
|
854
|
+
# subgrids = append(subgrids,str(grid))
|
|
855
|
+
return unique(bpos, axis=1)
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
class Sector(HasPrivateTraits):
|
|
859
|
+
"""Base class for all sector types.
|
|
869
860
|
|
|
870
|
-
class Sector( HasPrivateTraits ):
|
|
871
|
-
"""
|
|
872
|
-
Base class for all sector types.
|
|
873
|
-
|
|
874
861
|
Defines the common interface for all tbdsector classes. This class
|
|
875
862
|
may be used as a base for diverse sector implementaions. If used
|
|
876
863
|
directly, it implements a sector encompassing the whole grid.
|
|
877
864
|
"""
|
|
878
|
-
|
|
879
|
-
def contains
|
|
880
|
-
"""
|
|
881
|
-
|
|
882
|
-
defined sector.
|
|
865
|
+
|
|
866
|
+
def contains(self, pos):
|
|
867
|
+
"""Queries whether the coordinates in a given array lie within the
|
|
868
|
+
defined sector.
|
|
883
869
|
For this sector type, any position is valid.
|
|
884
|
-
|
|
870
|
+
|
|
885
871
|
Parameters
|
|
886
872
|
----------
|
|
887
873
|
pos : array of floats
|
|
888
874
|
Array with the shape 3x[number of gridpoints] containing the
|
|
889
875
|
grid positions
|
|
890
|
-
|
|
876
|
+
|
|
891
877
|
Returns
|
|
892
878
|
-------
|
|
893
879
|
array of bools with as many entries as columns in pos
|
|
894
880
|
Array indicating which of the given positions lie within the
|
|
895
|
-
given sector
|
|
881
|
+
given sector
|
|
882
|
+
|
|
896
883
|
"""
|
|
897
884
|
return ones(pos.shape[1], dtype=bool)
|
|
898
885
|
|
|
899
886
|
|
|
900
|
-
class SingleSector(
|
|
901
|
-
"""
|
|
902
|
-
|
|
903
|
-
|
|
887
|
+
class SingleSector(Sector):
|
|
888
|
+
"""Base class for single sector types.
|
|
889
|
+
|
|
904
890
|
Defines the common interface for all single sector classes. This class
|
|
905
891
|
may be used as a base for diverse single sector implementaions. If used
|
|
906
892
|
directly, it implements a sector encompassing the whole grid.
|
|
907
893
|
"""
|
|
908
|
-
|
|
894
|
+
|
|
909
895
|
#: Boolean flag, if 'True' (default), grid points lying on the sector border are included.
|
|
910
|
-
include_border = Bool(True,
|
|
911
|
-
|
|
912
|
-
|
|
896
|
+
include_border = Bool(True, desc='include points on the border')
|
|
897
|
+
|
|
913
898
|
#: Absolute tolerance for sector border
|
|
914
|
-
abs_tol = Float(1e-12,
|
|
915
|
-
desc="absolute tolerance for sector border")
|
|
899
|
+
abs_tol = Float(1e-12, desc='absolute tolerance for sector border')
|
|
916
900
|
|
|
917
901
|
#: Boolean flag, if 'True' (default), the nearest grid point is returned if none is inside the sector.
|
|
918
|
-
default_nearest = Bool(True,
|
|
919
|
-
desc="return nearest grid point to center of none inside sector")
|
|
902
|
+
default_nearest = Bool(True, desc='return nearest grid point to center of none inside sector')
|
|
920
903
|
|
|
921
904
|
|
|
905
|
+
class RectSector(SingleSector):
|
|
906
|
+
"""Class for defining a rectangular sector.
|
|
922
907
|
|
|
923
|
-
class RectSector( SingleSector ):
|
|
924
|
-
"""
|
|
925
|
-
Class for defining a rectangular sector.
|
|
926
|
-
|
|
927
908
|
Can be used for 2D Grids for definining a rectangular sector or
|
|
928
909
|
for 3D grids for a rectangular cylinder sector parallel to the z-axis.
|
|
929
910
|
"""
|
|
930
|
-
|
|
911
|
+
|
|
931
912
|
#: The lower x position of the rectangle
|
|
932
|
-
x_min = Float(-1.0,
|
|
933
|
-
desc="minimum x position of the rectangle")
|
|
913
|
+
x_min = Float(-1.0, desc='minimum x position of the rectangle')
|
|
934
914
|
|
|
935
915
|
#: The upper x position of the rectangle
|
|
936
|
-
x_max = Float(1.0,
|
|
937
|
-
desc="maximum x position of the rectangle")
|
|
916
|
+
x_max = Float(1.0, desc='maximum x position of the rectangle')
|
|
938
917
|
|
|
939
918
|
#: The lower y position of the rectangle
|
|
940
|
-
y_min = Float(-1.0,
|
|
941
|
-
|
|
942
|
-
|
|
919
|
+
y_min = Float(-1.0, desc='minimum y position of the rectangle')
|
|
920
|
+
|
|
943
921
|
#: The upper y position of the rectangle
|
|
944
|
-
y_max = Float(1.0,
|
|
945
|
-
desc="maximum y position of the rectangle")
|
|
922
|
+
y_max = Float(1.0, desc='maximum y position of the rectangle')
|
|
946
923
|
|
|
947
|
-
def contains
|
|
948
|
-
"""
|
|
949
|
-
|
|
950
|
-
rectangular sector.
|
|
924
|
+
def contains(self, pos):
|
|
925
|
+
"""Queries whether the coordinates in a given array lie within the
|
|
926
|
+
rectangular sector.
|
|
951
927
|
If no coordinate is inside, the nearest one to the rectangle center
|
|
952
928
|
is returned if :attr:`~Sector.default_nearest` is True.
|
|
953
|
-
|
|
929
|
+
|
|
954
930
|
Parameters
|
|
955
931
|
----------
|
|
956
932
|
pos : array of floats
|
|
957
933
|
Array with the shape 3x[number of gridpoints] containing the
|
|
958
934
|
grid positions
|
|
959
|
-
|
|
935
|
+
|
|
960
936
|
Returns
|
|
961
937
|
-------
|
|
962
938
|
array of bools with as many entries as columns in pos
|
|
963
939
|
Array indicating which of the given positions lie within the
|
|
964
|
-
given sector
|
|
940
|
+
given sector
|
|
941
|
+
|
|
965
942
|
"""
|
|
966
943
|
# make sure xmin is minimum etc
|
|
967
|
-
xmin = min(self.x_min,self.x_max)
|
|
968
|
-
xmax = max(self.x_min,self.x_max)
|
|
969
|
-
ymin = min(self.y_min,self.y_max)
|
|
970
|
-
ymax = max(self.y_min,self.y_max)
|
|
971
|
-
|
|
944
|
+
xmin = min(self.x_min, self.x_max)
|
|
945
|
+
xmax = max(self.x_min, self.x_max)
|
|
946
|
+
ymin = min(self.y_min, self.y_max)
|
|
947
|
+
ymax = max(self.y_min, self.y_max)
|
|
948
|
+
|
|
972
949
|
abs_tol = self.abs_tol
|
|
973
950
|
# get pos indices inside rectangle (* == and)
|
|
974
951
|
if self.include_border:
|
|
975
|
-
inds = (
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
952
|
+
inds = (
|
|
953
|
+
(pos[0, :] - xmin > -abs_tol)
|
|
954
|
+
* (pos[0, :] - xmax < abs_tol)
|
|
955
|
+
* (pos[1, :] - ymin > -abs_tol)
|
|
956
|
+
* (pos[1, :] - ymax < abs_tol)
|
|
957
|
+
)
|
|
979
958
|
else:
|
|
980
|
-
inds = (
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
959
|
+
inds = (
|
|
960
|
+
(pos[0, :] - xmin > abs_tol)
|
|
961
|
+
* (pos[0, :] - xmax < -abs_tol)
|
|
962
|
+
* (pos[1, :] - ymin > abs_tol)
|
|
963
|
+
* (pos[1, :] - ymax < -abs_tol)
|
|
964
|
+
)
|
|
965
|
+
|
|
986
966
|
# if none inside, take nearest
|
|
987
967
|
if ~inds.any() and self.default_nearest:
|
|
988
968
|
x = (xmin + xmax) / 2.0
|
|
989
969
|
y = (ymin + ymax) / 2.0
|
|
990
|
-
dr2 = (pos[0, :] - x)**2 + (pos[1, :] - y)**2
|
|
970
|
+
dr2 = (pos[0, :] - x) ** 2 + (pos[1, :] - y) ** 2
|
|
991
971
|
inds[argmin(dr2)] = True
|
|
992
|
-
|
|
972
|
+
|
|
993
973
|
return inds.astype(bool)
|
|
994
974
|
|
|
995
975
|
|
|
996
|
-
class RectSector3D(
|
|
997
|
-
"""
|
|
998
|
-
|
|
999
|
-
|
|
976
|
+
class RectSector3D(RectSector):
|
|
977
|
+
"""Class for defining a cuboid sector.
|
|
978
|
+
|
|
1000
979
|
Can be used for 3D Grids for definining a cuboid sector.
|
|
1001
980
|
"""
|
|
1002
|
-
|
|
981
|
+
|
|
1003
982
|
#: The lower z position of the cuboid
|
|
1004
|
-
z_min = Float(-1.0,
|
|
1005
|
-
desc="minimum z position of the cuboid")
|
|
983
|
+
z_min = Float(-1.0, desc='minimum z position of the cuboid')
|
|
1006
984
|
|
|
1007
985
|
#: The upper z position of the cuboid
|
|
1008
|
-
z_max = Float(1.0,
|
|
1009
|
-
desc="maximum z position of the cuboid")
|
|
986
|
+
z_max = Float(1.0, desc='maximum z position of the cuboid')
|
|
1010
987
|
|
|
1011
|
-
def contains
|
|
1012
|
-
"""
|
|
1013
|
-
|
|
1014
|
-
rectangular sector.
|
|
988
|
+
def contains(self, pos):
|
|
989
|
+
"""Queries whether the coordinates in a given array lie within the
|
|
990
|
+
rectangular sector.
|
|
1015
991
|
If no coordinate is inside, the nearest one to the rectangle center
|
|
1016
992
|
is returned if :attr:`~Sector.default_nearest` is True.
|
|
1017
|
-
|
|
993
|
+
|
|
1018
994
|
Parameters
|
|
1019
995
|
----------
|
|
1020
996
|
pos : array of floats
|
|
1021
997
|
Array with the shape 3x[number of gridpoints] containing the
|
|
1022
998
|
grid positions
|
|
1023
|
-
|
|
999
|
+
|
|
1024
1000
|
Returns
|
|
1025
1001
|
-------
|
|
1026
1002
|
array of bools with as many entries as columns in pos
|
|
1027
1003
|
Array indicating which of the given positions lie within the
|
|
1028
|
-
given sector
|
|
1004
|
+
given sector
|
|
1005
|
+
|
|
1029
1006
|
"""
|
|
1030
1007
|
# make sure xmin is minimum etc
|
|
1031
|
-
xmin = min(self.x_min,self.x_max)
|
|
1032
|
-
xmax = max(self.x_min,self.x_max)
|
|
1033
|
-
ymin = min(self.y_min,self.y_max)
|
|
1034
|
-
ymax = max(self.y_min,self.y_max)
|
|
1035
|
-
zmin = min(self.z_min,self.z_max)
|
|
1036
|
-
zmax = max(self.z_min,self.z_max)
|
|
1037
|
-
|
|
1008
|
+
xmin = min(self.x_min, self.x_max)
|
|
1009
|
+
xmax = max(self.x_min, self.x_max)
|
|
1010
|
+
ymin = min(self.y_min, self.y_max)
|
|
1011
|
+
ymax = max(self.y_min, self.y_max)
|
|
1012
|
+
zmin = min(self.z_min, self.z_max)
|
|
1013
|
+
zmax = max(self.z_min, self.z_max)
|
|
1014
|
+
|
|
1038
1015
|
abs_tol = self.abs_tol
|
|
1039
1016
|
# get pos indices inside rectangle (* == and)
|
|
1040
1017
|
if self.include_border:
|
|
1041
|
-
inds = (
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1018
|
+
inds = (
|
|
1019
|
+
(pos[0, :] - xmin > -abs_tol)
|
|
1020
|
+
* (pos[0, :] - xmax < abs_tol)
|
|
1021
|
+
* (pos[1, :] - ymin > -abs_tol)
|
|
1022
|
+
* (pos[1, :] - ymax < abs_tol)
|
|
1023
|
+
* (pos[2, :] - zmin > -abs_tol)
|
|
1024
|
+
* (pos[2, :] - zmax < abs_tol)
|
|
1025
|
+
)
|
|
1047
1026
|
else:
|
|
1048
|
-
inds = (
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1027
|
+
inds = (
|
|
1028
|
+
(pos[0, :] - xmin > abs_tol)
|
|
1029
|
+
* (pos[0, :] - xmax < -abs_tol)
|
|
1030
|
+
* (pos[1, :] - ymin > abs_tol)
|
|
1031
|
+
* (pos[1, :] - ymax < -abs_tol)
|
|
1032
|
+
* (pos[2, :] - zmin > abs_tol)
|
|
1033
|
+
* (pos[2, :] - zmax < -abs_tol)
|
|
1034
|
+
)
|
|
1035
|
+
|
|
1055
1036
|
# if none inside, take nearest
|
|
1056
1037
|
if ~inds.any() and self.default_nearest:
|
|
1057
1038
|
x = (xmin + xmax) / 2.0
|
|
1058
1039
|
y = (ymin + ymax) / 2.0
|
|
1059
|
-
dr2 = (pos[0, :] - x)**2 + (pos[1, :] - y)**2
|
|
1040
|
+
dr2 = (pos[0, :] - x) ** 2 + (pos[1, :] - y) ** 2
|
|
1060
1041
|
inds[argmin(dr2)] = True
|
|
1061
|
-
|
|
1042
|
+
|
|
1062
1043
|
return inds.astype(bool)
|
|
1063
1044
|
|
|
1064
1045
|
|
|
1065
|
-
class CircSector(
|
|
1066
|
-
"""
|
|
1067
|
-
|
|
1068
|
-
|
|
1046
|
+
class CircSector(SingleSector):
|
|
1047
|
+
"""Class for defining a circular sector.
|
|
1048
|
+
|
|
1069
1049
|
Can be used for 2D Grids for definining a circular sector or
|
|
1070
1050
|
for 3D grids for a cylindrical sector parallel to the z-axis.
|
|
1071
1051
|
"""
|
|
1072
|
-
|
|
1052
|
+
|
|
1073
1053
|
#: x position of the circle center
|
|
1074
|
-
x = Float(0.0,
|
|
1075
|
-
desc="x position of the circle center")
|
|
1054
|
+
x = Float(0.0, desc='x position of the circle center')
|
|
1076
1055
|
|
|
1077
1056
|
#: y position of the circle center
|
|
1078
|
-
y = Float(0.0,
|
|
1079
|
-
|
|
1080
|
-
|
|
1057
|
+
y = Float(0.0, desc='y position of the circle center')
|
|
1058
|
+
|
|
1081
1059
|
#: radius of the circle
|
|
1082
|
-
r = Float(1.0,
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
"""
|
|
1088
|
-
Queries whether the coordinates in a given array lie within the
|
|
1089
|
-
circular sector.
|
|
1060
|
+
r = Float(1.0, desc='radius of the circle')
|
|
1061
|
+
|
|
1062
|
+
def contains(self, pos):
|
|
1063
|
+
"""Queries whether the coordinates in a given array lie within the
|
|
1064
|
+
circular sector.
|
|
1090
1065
|
If no coordinate is inside, the nearest one outside is returned
|
|
1091
1066
|
if :attr:`~Sector.default_nearest` is True.
|
|
1092
|
-
|
|
1067
|
+
|
|
1093
1068
|
Parameters
|
|
1094
1069
|
----------
|
|
1095
1070
|
pos : array of floats
|
|
1096
1071
|
Array with the shape 3x[number of gridpoints] containing the
|
|
1097
1072
|
grid positions
|
|
1098
|
-
|
|
1073
|
+
|
|
1099
1074
|
Returns
|
|
1100
1075
|
-------
|
|
1101
1076
|
array of bools with as many entries as columns in pos
|
|
1102
1077
|
Array indicating which of the given positions lie within the
|
|
1103
|
-
given sector
|
|
1078
|
+
given sector
|
|
1079
|
+
|
|
1104
1080
|
"""
|
|
1105
|
-
dr2 = (pos[0, :]-self.x)**2 + (pos[1, :]-self.y)**2
|
|
1081
|
+
dr2 = (pos[0, :] - self.x) ** 2 + (pos[1, :] - self.y) ** 2
|
|
1106
1082
|
# which points are in the circle?
|
|
1107
|
-
if self.include_border
|
|
1108
|
-
|
|
1109
|
-
else:
|
|
1110
|
-
inds = (dr2 - self.r**2) < -self.abs_tol
|
|
1111
|
-
|
|
1112
|
-
|
|
1083
|
+
inds = dr2 - self.r**2 < self.abs_tol if self.include_border else dr2 - self.r**2 < -self.abs_tol
|
|
1084
|
+
|
|
1113
1085
|
# if there's no poit inside
|
|
1114
|
-
if ~inds.any() and self.default_nearest:
|
|
1086
|
+
if ~inds.any() and self.default_nearest:
|
|
1115
1087
|
inds[argmin(dr2)] = True
|
|
1116
|
-
|
|
1088
|
+
|
|
1117
1089
|
return inds
|
|
1118
1090
|
|
|
1119
1091
|
|
|
1120
|
-
class PolySector(
|
|
1121
|
-
"""
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
Can be used for 2D Grids for definining a polygon sector.
|
|
1092
|
+
class PolySector(SingleSector):
|
|
1093
|
+
"""Class for defining a polygon sector.
|
|
1094
|
+
|
|
1095
|
+
Can be used for 2D Grids for definining a polygon sector.
|
|
1125
1096
|
"""
|
|
1097
|
+
|
|
1126
1098
|
# x1, y1, x2, y2, ... xn, yn :
|
|
1127
|
-
edges = List(
|
|
1128
|
-
|
|
1099
|
+
edges = List(Float)
|
|
1129
1100
|
|
|
1130
|
-
def contains
|
|
1131
|
-
"""
|
|
1132
|
-
|
|
1133
|
-
ploygon sector.
|
|
1101
|
+
def contains(self, pos):
|
|
1102
|
+
"""Queries whether the coordinates in a given array lie within the
|
|
1103
|
+
ploygon sector.
|
|
1134
1104
|
If no coordinate is inside, the nearest one to the rectangle center
|
|
1135
1105
|
is returned if :attr:`~Sector.default_nearest` is True.
|
|
1136
|
-
|
|
1106
|
+
|
|
1137
1107
|
Parameters
|
|
1138
1108
|
----------
|
|
1139
1109
|
pos : array of floats
|
|
1140
1110
|
Array with the shape 3x[number of gridpoints] containing the
|
|
1141
1111
|
grid positions
|
|
1142
|
-
|
|
1112
|
+
|
|
1143
1113
|
Returns
|
|
1144
1114
|
-------
|
|
1145
1115
|
array of bools with as many entries as columns in pos
|
|
1146
1116
|
Array indicating which of the given positions lie within the
|
|
1147
|
-
given sector
|
|
1117
|
+
given sector
|
|
1118
|
+
|
|
1148
1119
|
"""
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
inds = dists >= -self.abs_tol
|
|
1154
|
-
else:
|
|
1155
|
-
inds = dists > 0
|
|
1156
|
-
|
|
1157
|
-
|
|
1120
|
+
poly = Polygon(array(self.edges).reshape(-1, 2)[:, 0], array(self.edges).reshape(-1, 2)[:, 1])
|
|
1121
|
+
dists = poly.is_inside(pos[0, :], pos[1, :])
|
|
1122
|
+
inds = dists >= -self.abs_tol if self.include_border else dists > 0
|
|
1123
|
+
|
|
1158
1124
|
# if none inside, take nearest
|
|
1159
1125
|
if ~inds.any() and self.default_nearest:
|
|
1160
|
-
dr2 = array(self.edges).reshape(-1,2).mean(0)
|
|
1126
|
+
dr2 = array(self.edges).reshape(-1, 2).mean(0)
|
|
1161
1127
|
inds[argmin(dr2)] = True
|
|
1162
|
-
|
|
1128
|
+
|
|
1163
1129
|
return inds
|
|
1164
1130
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1131
|
+
|
|
1132
|
+
class ConvexSector(SingleSector):
|
|
1133
|
+
"""Class for defining a convex hull sector.
|
|
1134
|
+
|
|
1135
|
+
Can be used for 2D Grids for definining a convex hull sector.
|
|
1170
1136
|
"""
|
|
1137
|
+
|
|
1171
1138
|
# x1, y1, x2, y2, ... xn, yn :
|
|
1172
|
-
edges = List(
|
|
1173
|
-
|
|
1139
|
+
edges = List(Float)
|
|
1174
1140
|
|
|
1175
|
-
def contains
|
|
1176
|
-
"""
|
|
1177
|
-
|
|
1178
|
-
convex sector.
|
|
1141
|
+
def contains(self, pos):
|
|
1142
|
+
"""Queries whether the coordinates in a given array lie within the
|
|
1143
|
+
convex sector.
|
|
1179
1144
|
If no coordinate is inside, the nearest one to the rectangle center
|
|
1180
|
-
is returned if :attr:`~Sector.default_nearest` is True.
|
|
1181
|
-
|
|
1145
|
+
is returned if :attr:`~Sector.default_nearest` is True.
|
|
1146
|
+
|
|
1182
1147
|
Parameters
|
|
1183
1148
|
----------
|
|
1184
1149
|
pos : array of floats
|
|
1185
1150
|
Array with the shape 3x[number of gridpoints] containing the
|
|
1186
1151
|
grid positions
|
|
1187
|
-
|
|
1152
|
+
|
|
1188
1153
|
Returns
|
|
1189
1154
|
-------
|
|
1190
1155
|
array of bools with as many entries as columns in pos
|
|
1191
1156
|
Array indicating which of the given positions lie within the
|
|
1192
|
-
given sector
|
|
1157
|
+
given sector
|
|
1158
|
+
|
|
1193
1159
|
"""
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
border = self.include_border ,tol = self.abs_tol)
|
|
1197
|
-
|
|
1160
|
+
inds = in_hull(pos[:2, :].T, array(self.edges).reshape(-1, 2), border=self.include_border, tol=self.abs_tol)
|
|
1161
|
+
|
|
1198
1162
|
# if none inside, take nearest
|
|
1199
1163
|
if ~inds.any() and self.default_nearest:
|
|
1200
|
-
dr2 = array(self.edges).reshape(-1,2).mean(0)
|
|
1164
|
+
dr2 = array(self.edges).reshape(-1, 2).mean(0)
|
|
1201
1165
|
inds[argmin(dr2)] = True
|
|
1202
|
-
|
|
1203
|
-
return inds
|
|
1204
1166
|
|
|
1167
|
+
return inds
|
|
1205
1168
|
|
|
1206
1169
|
|
|
1207
1170
|
class MultiSector(Sector):
|
|
1208
|
-
"""
|
|
1209
|
-
|
|
1210
|
-
|
|
1171
|
+
"""Class for defining a sector consisting of multiple sectors.
|
|
1172
|
+
|
|
1211
1173
|
Can be used to sum over different sectors. Takes a list of sectors
|
|
1212
1174
|
and returns the points contained in each sector.
|
|
1213
|
-
|
|
1175
|
+
|
|
1214
1176
|
"""
|
|
1215
|
-
|
|
1177
|
+
|
|
1216
1178
|
#: List of :class:`acoular.grids.Sector` objects
|
|
1217
1179
|
#: to be mixed.
|
|
1218
|
-
sectors = List(Instance(Sector))
|
|
1219
|
-
|
|
1220
|
-
def contains
|
|
1221
|
-
"""
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1180
|
+
sectors = List(Instance(Sector))
|
|
1181
|
+
|
|
1182
|
+
def contains(self, pos):
|
|
1183
|
+
"""Queries whether the coordinates in a given array lie within any
|
|
1184
|
+
of the sub-sectors.
|
|
1185
|
+
|
|
1225
1186
|
Parameters
|
|
1226
1187
|
----------
|
|
1227
1188
|
pos : array of floats
|
|
1228
1189
|
Array with the shape 3x[number of gridpoints] containing the
|
|
1229
1190
|
grid positions
|
|
1230
|
-
|
|
1191
|
+
|
|
1231
1192
|
Returns
|
|
1232
1193
|
-------
|
|
1233
1194
|
array of bools with as many entries as columns in pos
|
|
1234
1195
|
Array indicating which of the given positions lie within the
|
|
1235
|
-
sectors
|
|
1196
|
+
sectors
|
|
1197
|
+
|
|
1236
1198
|
"""
|
|
1237
1199
|
# initialize with only "False" entries
|
|
1238
1200
|
inds = zeros(pos.shape[1], dtype=bool)
|
|
1239
|
-
|
|
1201
|
+
|
|
1240
1202
|
# add points contained in each sector
|
|
1241
1203
|
for sec in self.sectors:
|
|
1242
1204
|
inds += sec.contains(pos)
|
|
1243
|
-
|
|
1244
|
-
return inds.astype(bool)
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
1205
|
|
|
1206
|
+
return inds.astype(bool)
|