acoular 25.7__py3-none-any.whl → 26.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/aiaa/aiaa.py +8 -10
- acoular/base.py +13 -16
- acoular/calib.py +25 -24
- acoular/configuration.py +2 -2
- acoular/demo/__init__.py +97 -9
- acoular/demo/__main__.py +37 -0
- acoular/environments.py +119 -130
- acoular/fbeamform.py +438 -440
- acoular/fprocess.py +18 -13
- acoular/grids.py +122 -301
- acoular/h5cache.py +5 -1
- acoular/h5files.py +96 -9
- acoular/microphones.py +30 -35
- acoular/process.py +14 -25
- acoular/sdinput.py +9 -14
- acoular/signals.py +36 -34
- acoular/sources.py +263 -380
- acoular/spectra.py +60 -80
- acoular/tbeamform.py +242 -224
- acoular/tools/helpers.py +25 -33
- acoular/tools/metrics.py +5 -10
- acoular/tools/utils.py +168 -0
- acoular/tprocess.py +248 -271
- acoular/trajectory.py +5 -6
- acoular/version.py +2 -2
- {acoular-25.7.dist-info → acoular-26.1.dist-info}/METADATA +54 -105
- acoular-26.1.dist-info/RECORD +56 -0
- {acoular-25.7.dist-info → acoular-26.1.dist-info}/WHEEL +1 -1
- acoular/demo/acoular_demo.py +0 -135
- acoular-25.7.dist-info/RECORD +0 -56
- {acoular-25.7.dist-info → acoular-26.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {acoular-25.7.dist-info → acoular-26.1.dist-info}/licenses/LICENSE +0 -0
acoular/grids.py
CHANGED
|
@@ -4,6 +4,24 @@
|
|
|
4
4
|
"""
|
|
5
5
|
Implement support for multidimensional grids and integration sectors.
|
|
6
6
|
|
|
7
|
+
.. inheritance-diagram::
|
|
8
|
+
acoular.grids.Grid
|
|
9
|
+
acoular.grids.RectGrid
|
|
10
|
+
acoular.grids.RectGrid3D
|
|
11
|
+
acoular.grids.ImportGrid
|
|
12
|
+
acoular.grids.LineGrid
|
|
13
|
+
acoular.grids.MergeGrid
|
|
14
|
+
:top-classes:
|
|
15
|
+
acoular.grids.Grid
|
|
16
|
+
:parts: 1
|
|
17
|
+
|
|
18
|
+
.. inheritance-diagram::
|
|
19
|
+
acoular.grids.Sector
|
|
20
|
+
:include-subclasses:
|
|
21
|
+
:top-classes:
|
|
22
|
+
acoular.grids.Sector
|
|
23
|
+
:parts: 1
|
|
24
|
+
|
|
7
25
|
.. autosummary::
|
|
8
26
|
:toctree: generated/
|
|
9
27
|
|
|
@@ -30,31 +48,8 @@ import xml.dom.minidom
|
|
|
30
48
|
from abc import abstractmethod
|
|
31
49
|
from pathlib import Path
|
|
32
50
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
append,
|
|
36
|
-
arange,
|
|
37
|
-
argmin,
|
|
38
|
-
array,
|
|
39
|
-
asarray,
|
|
40
|
-
concatenate,
|
|
41
|
-
copysign,
|
|
42
|
-
fabs,
|
|
43
|
-
inf,
|
|
44
|
-
isscalar,
|
|
45
|
-
ma,
|
|
46
|
-
mgrid,
|
|
47
|
-
newaxis,
|
|
48
|
-
ones,
|
|
49
|
-
ones_like,
|
|
50
|
-
s_,
|
|
51
|
-
sum, # noqa: A004
|
|
52
|
-
tile,
|
|
53
|
-
unique,
|
|
54
|
-
where,
|
|
55
|
-
zeros,
|
|
56
|
-
)
|
|
57
|
-
from scipy.linalg import norm
|
|
51
|
+
import numpy as np
|
|
52
|
+
import scipy.linalg as spla
|
|
58
53
|
|
|
59
54
|
# from matplotlib.path import Path
|
|
60
55
|
from scipy.spatial import Delaunay
|
|
@@ -73,14 +68,13 @@ from traits.api import (
|
|
|
73
68
|
Union,
|
|
74
69
|
cached_property,
|
|
75
70
|
observe,
|
|
76
|
-
on_trait_change,
|
|
77
71
|
property_depends_on,
|
|
78
72
|
)
|
|
79
73
|
from traits.trait_errors import TraitError
|
|
80
74
|
|
|
81
75
|
# acoular imports
|
|
82
|
-
from .deprecation import deprecated_alias
|
|
83
76
|
from .internal import digest, ldigest
|
|
77
|
+
from .tools.utils import Polygon
|
|
84
78
|
|
|
85
79
|
|
|
86
80
|
def in_hull(p, hull, border=True, tol=0):
|
|
@@ -135,174 +129,6 @@ def in_hull(p, hull, border=True, tol=0):
|
|
|
135
129
|
return hull.find_simplex(p, tol=tol) > 0
|
|
136
130
|
|
|
137
131
|
|
|
138
|
-
def _det(xvert, yvert):
|
|
139
|
-
xvert = asarray(xvert, dtype=float)
|
|
140
|
-
yvert = asarray(yvert, dtype=float)
|
|
141
|
-
x_prev = concatenate(([xvert[-1]], xvert[:-1]))
|
|
142
|
-
y_prev = concatenate(([yvert[-1]], yvert[:-1]))
|
|
143
|
-
return sum(yvert * x_prev - xvert * y_prev, axis=0)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
class Polygon:
|
|
147
|
-
"""
|
|
148
|
-
Create an object representing a general polygon in a 2D plane.
|
|
149
|
-
|
|
150
|
-
This class allows defining a polygon by specifying the coordinates of its vertices and provides
|
|
151
|
-
methods for checking whether a set of points lies inside the polygon, or if a point is closer to
|
|
152
|
-
a side or vertex of the polygon.
|
|
153
|
-
|
|
154
|
-
Parameters
|
|
155
|
-
----------
|
|
156
|
-
x : array_like
|
|
157
|
-
Array of x-coordinates of the vertices that define the polygon. These coordinates should
|
|
158
|
-
form a closed shape (i.e., the last point should be the same as the first point).
|
|
159
|
-
|
|
160
|
-
y : array_like
|
|
161
|
-
Array of y-coordinates of the vertices that define the polygon. These coordinates should
|
|
162
|
-
correspond to the x-coordinates, forming a closed shape.
|
|
163
|
-
|
|
164
|
-
Attributes
|
|
165
|
-
----------
|
|
166
|
-
x : :class:`numpy.ndarray`
|
|
167
|
-
Array of x-coordinates of the polygon vertices.
|
|
168
|
-
|
|
169
|
-
y : :class:`numpy.ndarray`
|
|
170
|
-
Array of y-coordinates of the polygon vertices.
|
|
171
|
-
"""
|
|
172
|
-
|
|
173
|
-
def __init__(self, x, y):
|
|
174
|
-
if len(x) != len(y):
|
|
175
|
-
msg = 'x and y must be equally sized.'
|
|
176
|
-
raise IndexError(msg)
|
|
177
|
-
self.x = asarray(x, dtype=float)
|
|
178
|
-
self.y = asarray(y, dtype=float)
|
|
179
|
-
# Closes the polygon if were open
|
|
180
|
-
x1, y1 = x[0], y[0]
|
|
181
|
-
xn, yn = x[-1], y[-1]
|
|
182
|
-
if x1 != xn or y1 != yn:
|
|
183
|
-
self.x = concatenate((self.x, [x1]))
|
|
184
|
-
self.y = concatenate((self.y, [y1]))
|
|
185
|
-
# Anti-clockwise coordinates
|
|
186
|
-
if _det(self.x, self.y) < 0:
|
|
187
|
-
self.x = self.x[::-1]
|
|
188
|
-
self.y = self.y[::-1]
|
|
189
|
-
|
|
190
|
-
def is_inside(self, xpoint, ypoint, smalld=1e-12):
|
|
191
|
-
"""
|
|
192
|
-
Check if a point or set of points are inside the polygon.
|
|
193
|
-
|
|
194
|
-
Parameters
|
|
195
|
-
----------
|
|
196
|
-
xpoint : :class:`float` or array_like
|
|
197
|
-
Array of x-coordinates of the points to be tested.
|
|
198
|
-
|
|
199
|
-
ypoint : :class:`float` or array_like
|
|
200
|
-
Array of y-coordinates of the points to be tested.
|
|
201
|
-
|
|
202
|
-
smalld : :class:`float`, optional
|
|
203
|
-
Tolerance used for floating point comparisons when checking if a point is exactly on a
|
|
204
|
-
polygon's edge. The default value is ``1e-12``.
|
|
205
|
-
|
|
206
|
-
Returns
|
|
207
|
-
-------
|
|
208
|
-
:class:`float` or array_like
|
|
209
|
-
The distance from the point to the nearest point on the polygon. The values returned
|
|
210
|
-
have the following meanings:
|
|
211
|
-
- ``mindst < 0``: Point is outside the polygon.
|
|
212
|
-
- ``mindst = 0``: Point is on an edge of the polygon.
|
|
213
|
-
- ``mindst > 0``: Point is inside the polygon.
|
|
214
|
-
|
|
215
|
-
Notes
|
|
216
|
-
-----
|
|
217
|
-
The method uses an improved algorithm based on Nordbeck and Rydstedt for determining
|
|
218
|
-
whether a point is inside a polygon :cite:`SLOAN198545`.
|
|
219
|
-
"""
|
|
220
|
-
xpoint = asarray(xpoint, dtype=float)
|
|
221
|
-
ypoint = asarray(ypoint, dtype=float)
|
|
222
|
-
# Scalar to array
|
|
223
|
-
if xpoint.shape == ():
|
|
224
|
-
xpoint = array([xpoint], dtype=float)
|
|
225
|
-
ypoint = array([ypoint], dtype=float)
|
|
226
|
-
scalar = True
|
|
227
|
-
else:
|
|
228
|
-
scalar = False
|
|
229
|
-
# Check consistency
|
|
230
|
-
if xpoint.shape != ypoint.shape:
|
|
231
|
-
msg = 'x and y has different shapes'
|
|
232
|
-
raise IndexError(msg)
|
|
233
|
-
# If snear = True: Dist to nearest side < nearest vertex
|
|
234
|
-
# If snear = False: Dist to nearest vertex < nearest side
|
|
235
|
-
snear = ma.masked_all(xpoint.shape, dtype=bool)
|
|
236
|
-
# Initialize arrays
|
|
237
|
-
mindst = ones_like(xpoint, dtype=float) * inf
|
|
238
|
-
j = ma.masked_all(xpoint.shape, dtype=int)
|
|
239
|
-
x = self.x
|
|
240
|
-
y = self.y
|
|
241
|
-
n = len(x) - 1 # Number of sides/vertices defining the polygon
|
|
242
|
-
# Loop over each side defining polygon
|
|
243
|
-
for i in range(n):
|
|
244
|
-
d = ones_like(xpoint, dtype=float) * inf
|
|
245
|
-
# Start of side has coords (x1, y1)
|
|
246
|
-
# End of side has coords (x2, y2)
|
|
247
|
-
# Point has coords (xpoint, ypoint)
|
|
248
|
-
x1 = x[i]
|
|
249
|
-
y1 = y[i]
|
|
250
|
-
x21 = x[i + 1] - x1
|
|
251
|
-
y21 = y[i + 1] - y1
|
|
252
|
-
x1p = x1 - xpoint
|
|
253
|
-
y1p = y1 - ypoint
|
|
254
|
-
# Points on infinite line defined by
|
|
255
|
-
# x = x1 + t * (x1 - x2)
|
|
256
|
-
# y = y1 + t * (y1 - y2)
|
|
257
|
-
# where
|
|
258
|
-
# t = 0 at (x1, y1)
|
|
259
|
-
# t = 1 at (x2, y2)
|
|
260
|
-
# Find where normal passing through (xpoint, ypoint) intersects
|
|
261
|
-
# infinite line
|
|
262
|
-
t = -(x1p * x21 + y1p * y21) / (x21**2 + y21**2)
|
|
263
|
-
tlt0 = t < 0
|
|
264
|
-
tle1 = (t >= 0) & (t <= 1)
|
|
265
|
-
# Normal intersects side
|
|
266
|
-
d[tle1] = (x1p[tle1] + t[tle1] * x21) ** 2 + (y1p[tle1] + t[tle1] * y21) ** 2
|
|
267
|
-
# Normal does not intersects side
|
|
268
|
-
# Point is closest to vertex (x1, y1)
|
|
269
|
-
# Compute square of distance to this vertex
|
|
270
|
-
d[tlt0] = x1p[tlt0] ** 2 + y1p[tlt0] ** 2
|
|
271
|
-
# Store distances
|
|
272
|
-
mask = d < mindst
|
|
273
|
-
mindst[mask] = d[mask]
|
|
274
|
-
j[mask] = i
|
|
275
|
-
# Point is closer to (x1, y1) than any other vertex or side
|
|
276
|
-
snear[mask & tlt0] = False
|
|
277
|
-
# Point is closer to this side than to any other side or vertex
|
|
278
|
-
snear[mask & tle1] = True
|
|
279
|
-
if ma.count(snear) != snear.size:
|
|
280
|
-
msg = 'Error computing distances'
|
|
281
|
-
raise IndexError(msg)
|
|
282
|
-
mindst **= 0.5
|
|
283
|
-
# Point is closer to its nearest vertex than its nearest side, check if
|
|
284
|
-
# nearest vertex is concave.
|
|
285
|
-
# If the nearest vertex is concave then point is inside the polygon,
|
|
286
|
-
# else the point is outside the polygon.
|
|
287
|
-
jo = j.copy()
|
|
288
|
-
jo[j == 0] -= 1
|
|
289
|
-
area = _det([x[j + 1], x[j], x[jo - 1]], [y[j + 1], y[j], y[jo - 1]])
|
|
290
|
-
mindst[~snear] = copysign(mindst, area)[~snear]
|
|
291
|
-
# Point is closer to its nearest side than to its nearest vertex, check
|
|
292
|
-
# if point is to left or right of this side.
|
|
293
|
-
# If point is to left of side it is inside polygon, else point is
|
|
294
|
-
# outside polygon.
|
|
295
|
-
area = _det([x[j], x[j + 1], xpoint], [y[j], y[j + 1], ypoint])
|
|
296
|
-
mindst[snear] = copysign(mindst, area)[snear]
|
|
297
|
-
# Point is on side of polygon
|
|
298
|
-
mindst[fabs(mindst) < smalld] = 0
|
|
299
|
-
# If input values were scalar then the output should be too
|
|
300
|
-
if scalar:
|
|
301
|
-
mindst = float(mindst)
|
|
302
|
-
return mindst
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
@deprecated_alias({'gpos': 'pos'}, removal_version='25.10')
|
|
306
132
|
class Grid(ABCHasStrictTraits):
|
|
307
133
|
"""
|
|
308
134
|
Abstract base class for grid geometries.
|
|
@@ -312,28 +138,27 @@ class Grid(ABCHasStrictTraits):
|
|
|
312
138
|
implementations and should not be instantiated directly as it lacks concrete functionality.
|
|
313
139
|
|
|
314
140
|
.. _units_note_grids:
|
|
141
|
+
.. admonition:: Unit of length
|
|
315
142
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
If the positions' coordinates are provided in a unit other than meter, it is advisable to change
|
|
322
|
-
the :attr:`~acoular.environments.Environment.c` attribute to match the given unit.
|
|
143
|
+
The source code is agnostic to the unit of length. The positions' coordinates are assumed to
|
|
144
|
+
be in meters. This is consistent with the standard :class:`~acoular.environments.Environment`
|
|
145
|
+
class which uses the speed of sound at 20°C at sea level under standard atmosphere pressure in
|
|
146
|
+
m/s. If the positions' coordinates are provided in a unit other than meter, it is advisable to
|
|
147
|
+
change the :attr:`~acoular.environments.Environment.c` attribute to match the given unit.
|
|
323
148
|
"""
|
|
324
149
|
|
|
325
150
|
#: The total number of grid points. This property is automatically calculated based on other
|
|
326
151
|
#: defining attributes of the grid. (read-only)
|
|
327
|
-
size = Property(
|
|
152
|
+
size = Property()
|
|
328
153
|
|
|
329
154
|
#: The shape of the grid, represented as a tuple. Primarily useful for Cartesian grids.
|
|
330
155
|
#: (read-only)
|
|
331
|
-
shape = Property(
|
|
156
|
+
shape = Property()
|
|
332
157
|
|
|
333
158
|
#: The grid positions represented as a (3, :attr:`size`) array of :class:`floats<float>`.
|
|
334
159
|
#: (read-only)
|
|
335
|
-
#: All positions' coordinates are in meters by default (
|
|
336
|
-
pos = Property(
|
|
160
|
+
#: All positions' coordinates are in meters by default (:ref:`see here <units_note_grids>`).
|
|
161
|
+
pos = Property()
|
|
337
162
|
|
|
338
163
|
#: A unique identifier for the grid, based on its properties. (read-only)
|
|
339
164
|
digest = Property
|
|
@@ -385,7 +210,7 @@ class Grid(ABCHasStrictTraits):
|
|
|
385
210
|
# construct grid-shaped array with "True" entries where sector is
|
|
386
211
|
xyi = sector.contains(xpos).reshape(self.shape)
|
|
387
212
|
# return indices of "True" entries
|
|
388
|
-
return where(xyi)
|
|
213
|
+
return np.where(xyi)
|
|
389
214
|
|
|
390
215
|
def export_gpos(self, filename):
|
|
391
216
|
"""
|
|
@@ -446,7 +271,7 @@ class Grid(ABCHasStrictTraits):
|
|
|
446
271
|
pos_str = ' '.join(
|
|
447
272
|
[
|
|
448
273
|
' <pos',
|
|
449
|
-
f'Name="Point {i+1}"',
|
|
274
|
+
f'Name="Point {i + 1}"',
|
|
450
275
|
f'x="{self.pos[0, i]}"',
|
|
451
276
|
f'y="{self.pos[1, i]}"',
|
|
452
277
|
f'z="{self.pos[2, i]}"',
|
|
@@ -457,7 +282,6 @@ class Grid(ABCHasStrictTraits):
|
|
|
457
282
|
f.write('</Grid>')
|
|
458
283
|
|
|
459
284
|
|
|
460
|
-
@deprecated_alias({'gpos': 'pos'}, read_only=True, removal_version='25.10')
|
|
461
285
|
class RectGrid(Grid):
|
|
462
286
|
"""
|
|
463
287
|
Provides a 2D Cartesian grid for beamforming results.
|
|
@@ -467,31 +291,31 @@ class RectGrid(Grid):
|
|
|
467
291
|
"""
|
|
468
292
|
|
|
469
293
|
#: The lower x-limit that defines the grid. Default is ``-1``.
|
|
470
|
-
x_min = Float(-1.0
|
|
294
|
+
x_min = Float(-1.0)
|
|
471
295
|
|
|
472
296
|
#: The upper x-limit that defines the grid. Default is ``1``.
|
|
473
|
-
x_max = Float(1.0
|
|
297
|
+
x_max = Float(1.0)
|
|
474
298
|
|
|
475
299
|
#: The lower y-limit that defines the grid. Default is ``-1``.
|
|
476
|
-
y_min = Float(-1.0
|
|
300
|
+
y_min = Float(-1.0)
|
|
477
301
|
|
|
478
302
|
#: The upper y-limit that defines the grid. Default is ``1``.
|
|
479
|
-
y_max = Float(1.0
|
|
303
|
+
y_max = Float(1.0)
|
|
480
304
|
|
|
481
305
|
#: The constant z-coordinate of the grid plane. Default is ``1.0``.
|
|
482
|
-
z = Float(1.0
|
|
306
|
+
z = Float(1.0)
|
|
483
307
|
|
|
484
308
|
#: The side length of each cell. Default is ``0.1``.
|
|
485
|
-
increment = Float(0.1
|
|
309
|
+
increment = Float(0.1)
|
|
486
310
|
|
|
487
311
|
#: Number of grid points along x-axis. (read-only)
|
|
488
|
-
nxsteps = Property(
|
|
312
|
+
nxsteps = Property()
|
|
489
313
|
|
|
490
314
|
#: Number of grid points along y-axis. (read-only)
|
|
491
|
-
nysteps = Property(
|
|
315
|
+
nysteps = Property()
|
|
492
316
|
|
|
493
317
|
#: The grid's extension in :obj:`matplotlib.pyplot.imshow` compatible form. (read-only)
|
|
494
|
-
extent = Property(
|
|
318
|
+
extent = Property()
|
|
495
319
|
|
|
496
320
|
#: A unique identifier for the grid, based on its properties. (read-only)
|
|
497
321
|
digest = Property(
|
|
@@ -526,7 +350,7 @@ class RectGrid(Grid):
|
|
|
526
350
|
|
|
527
351
|
@property_depends_on(['x_min', 'x_max', 'y_min', 'y_max', 'increment'])
|
|
528
352
|
def _get_pos(self):
|
|
529
|
-
bpos = mgrid[
|
|
353
|
+
bpos = np.mgrid[
|
|
530
354
|
self.x_min : self.x_max : self.nxsteps * 1j,
|
|
531
355
|
self.y_min : self.y_max : self.nysteps * 1j,
|
|
532
356
|
self.z : self.z + 0.1,
|
|
@@ -642,36 +466,36 @@ class RectGrid(Grid):
|
|
|
642
466
|
dr2 = (xpos[0, :] - r[0]) ** 2 + (xpos[1, :] - r[1]) ** 2
|
|
643
467
|
# array with true/false entries
|
|
644
468
|
inds = dr2 <= r[2] ** 2
|
|
645
|
-
for
|
|
646
|
-
xi, yi = self.index(xpos[0,
|
|
469
|
+
for n_p in np.arange(self.size)[inds]: # n_p -- points in x2-circle
|
|
470
|
+
xi, yi = self.index(xpos[0, n_p], xpos[1, n_p])
|
|
647
471
|
xis += [xi]
|
|
648
472
|
yis += [yi]
|
|
649
473
|
if not (xis and yis): # if no points in circle, take nearest one
|
|
650
474
|
return self.index(r[0], r[1])
|
|
651
|
-
return array(xis), array(yis)
|
|
475
|
+
return np.array(xis), np.array(yis)
|
|
652
476
|
if len(r) == 4: # rectangular subdomain - old functionality
|
|
653
477
|
xi1, yi1 = self.index(min(r[0], r[2]), min(r[1], r[3]))
|
|
654
478
|
xi2, yi2 = self.index(max(r[0], r[2]), max(r[1], r[3]))
|
|
655
|
-
return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1]
|
|
479
|
+
return np.s_[xi1 : xi2 + 1], np.s_[yi1 : yi2 + 1]
|
|
656
480
|
xpos = self.pos
|
|
657
481
|
xis = []
|
|
658
482
|
yis = []
|
|
659
483
|
# replaced matplotlib Path by numpy
|
|
660
|
-
# p = Path(array(r).reshape(-1,2))
|
|
484
|
+
# p = Path(np.array(r).reshape(-1,2))
|
|
661
485
|
# inds = p.contains_points()
|
|
662
|
-
# inds = in_poly(xpos[:2,:].T,array(r).reshape(-1,2))
|
|
663
|
-
poly = Polygon(array(r).reshape(-1, 2)[:, 0], array(r).reshape(-1, 2)[:, 1])
|
|
486
|
+
# inds = in_poly(xpos[:2,:].T,np.array(r).reshape(-1,2))
|
|
487
|
+
poly = Polygon(np.array(r).reshape(-1, 2)[:, 0], np.array(r).reshape(-1, 2)[:, 1])
|
|
664
488
|
dists = poly.is_inside(xpos[0, :], xpos[1, :])
|
|
665
489
|
inds = dists >= 0
|
|
666
|
-
for
|
|
667
|
-
xi, yi = self.index(xpos[0,
|
|
490
|
+
for n_p in np.arange(self.size)[inds]: # n_p -- points in x2-circle
|
|
491
|
+
xi, yi = self.index(xpos[0, n_p], xpos[1, n_p])
|
|
668
492
|
xis += [xi]
|
|
669
493
|
yis += [yi]
|
|
670
494
|
if not (xis and yis): # if no points inside, take nearest to center
|
|
671
|
-
center = array(r).reshape(-1, 2).mean(0)
|
|
495
|
+
center = np.array(r).reshape(-1, 2).mean(0)
|
|
672
496
|
return self.index(center[0], center[1])
|
|
673
|
-
return array(xis), array(yis)
|
|
674
|
-
# return arange(self.size)[inds]
|
|
497
|
+
return np.array(xis), np.array(yis)
|
|
498
|
+
# return np.arange(self.size)[inds]
|
|
675
499
|
|
|
676
500
|
|
|
677
501
|
class RectGrid3D(RectGrid):
|
|
@@ -682,39 +506,38 @@ class RectGrid3D(RectGrid):
|
|
|
682
506
|
"""
|
|
683
507
|
|
|
684
508
|
#: The lower z-limit that defines the grid. Default is ``-1.0``.
|
|
685
|
-
z_min = Float(-1.0
|
|
509
|
+
z_min = Float(-1.0)
|
|
686
510
|
|
|
687
511
|
#: The upper z-limit that defines the grid. Default is ``1.0``.
|
|
688
|
-
z_max = Float(1.0
|
|
512
|
+
z_max = Float(1.0)
|
|
689
513
|
|
|
690
514
|
#: Number of grid points along x-axis. (read-only)
|
|
691
|
-
nxsteps = Property(
|
|
515
|
+
nxsteps = Property()
|
|
692
516
|
|
|
693
517
|
#: Number of grid points along y-axis. (read-only)
|
|
694
|
-
nysteps = Property(
|
|
518
|
+
nysteps = Property()
|
|
695
519
|
|
|
696
520
|
#: Number of grid points along z-axis. (read-only)
|
|
697
|
-
nzsteps = Property(
|
|
521
|
+
nzsteps = Property()
|
|
698
522
|
|
|
699
|
-
|
|
700
|
-
_increment = Union(Float(), CArray(shape=(3,), dtype=float), default_value=0.1, desc='step size')
|
|
523
|
+
_increment = Union(Float(), CArray(shape=(3,), dtype=float), default_value=0.1)
|
|
701
524
|
|
|
702
525
|
#: The cell side length for the grid. This can either be a scalar (same increments in all 3
|
|
703
526
|
#: dimensions) or a (3,) array of :class:`tuple` of :class:`floats<float>` with respective
|
|
704
527
|
#: increments in x-, y-, and z-direction. Default is ``0.1``.
|
|
705
|
-
increment = Property(
|
|
528
|
+
increment = Property()
|
|
706
529
|
|
|
707
530
|
def _get_increment(self):
|
|
708
531
|
return self._increment
|
|
709
532
|
|
|
710
533
|
def _set_increment(self, increment):
|
|
711
|
-
if isscalar(increment):
|
|
534
|
+
if np.isscalar(increment):
|
|
712
535
|
try:
|
|
713
|
-
self._increment =
|
|
536
|
+
self._increment = np.abs(float(increment))
|
|
714
537
|
except ValueError as ve:
|
|
715
538
|
raise TraitError(args=self, name='increment', info='Float or CArray(3,)', value=increment) from ve
|
|
716
539
|
elif len(increment) == 3:
|
|
717
|
-
self._increment = array(increment, dtype=float)
|
|
540
|
+
self._increment = np.array(increment, dtype=float)
|
|
718
541
|
else:
|
|
719
542
|
raise (TraitError(args=self, name='increment', info='Float or CArray(3,)', value=increment))
|
|
720
543
|
|
|
@@ -733,28 +556,28 @@ class RectGrid3D(RectGrid):
|
|
|
733
556
|
|
|
734
557
|
@property_depends_on(['x_min', 'x_max', '_increment'])
|
|
735
558
|
def _get_nxsteps(self):
|
|
736
|
-
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[0])
|
|
559
|
+
i = abs(self.increment) if np.isscalar(self.increment) else abs(self.increment[0])
|
|
737
560
|
if i != 0:
|
|
738
561
|
return int(round((abs(self.x_max - self.x_min) + i) / i))
|
|
739
562
|
return 1
|
|
740
563
|
|
|
741
564
|
@property_depends_on(['y_min', 'y_max', '_increment'])
|
|
742
565
|
def _get_nysteps(self):
|
|
743
|
-
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[1])
|
|
566
|
+
i = abs(self.increment) if np.isscalar(self.increment) else abs(self.increment[1])
|
|
744
567
|
if i != 0:
|
|
745
568
|
return int(round((abs(self.y_max - self.y_min) + i) / i))
|
|
746
569
|
return 1
|
|
747
570
|
|
|
748
571
|
@property_depends_on(['z_min', 'z_max', '_increment'])
|
|
749
572
|
def _get_nzsteps(self):
|
|
750
|
-
i = abs(self.increment) if isscalar(self.increment) else abs(self.increment[2])
|
|
573
|
+
i = abs(self.increment) if np.isscalar(self.increment) else abs(self.increment[2])
|
|
751
574
|
if i != 0:
|
|
752
575
|
return int(round((abs(self.z_max - self.z_min) + i) / i))
|
|
753
576
|
return 1
|
|
754
577
|
|
|
755
578
|
@property_depends_on('digest')
|
|
756
579
|
def _get_pos(self):
|
|
757
|
-
bpos = mgrid[
|
|
580
|
+
bpos = np.mgrid[
|
|
758
581
|
self.x_min : self.x_max : self.nxsteps * 1j,
|
|
759
582
|
self.y_min : self.y_max : self.nysteps * 1j,
|
|
760
583
|
self.z_min : self.z_max : self.nzsteps * 1j,
|
|
@@ -810,7 +633,7 @@ class RectGrid3D(RectGrid):
|
|
|
810
633
|
if z < self.z_min or z > self.z_max:
|
|
811
634
|
msg = f'z-value out of range {z:f} ({self.z_min:f}, {self.z_max:f})'
|
|
812
635
|
raise ValueError(msg)
|
|
813
|
-
if isscalar(self.increment):
|
|
636
|
+
if np.isscalar(self.increment):
|
|
814
637
|
incx = incy = incz = self.increment
|
|
815
638
|
else:
|
|
816
639
|
incx, incy, incz = self.increment
|
|
@@ -863,10 +686,9 @@ class RectGrid3D(RectGrid):
|
|
|
863
686
|
"""
|
|
864
687
|
xi1, yi1, zi1 = self.index(min(x1, x2), min(y1, y2), min(z1, z2))
|
|
865
688
|
xi2, yi2, zi2 = self.index(max(x1, x2), max(y1, y2), max(z1, z2))
|
|
866
|
-
return s_[xi1 : xi2 + 1], s_[yi1 : yi2 + 1], s_[zi1 : zi2 + 1]
|
|
689
|
+
return np.s_[xi1 : xi2 + 1], np.s_[yi1 : yi2 + 1], np.s_[zi1 : zi2 + 1]
|
|
867
690
|
|
|
868
691
|
|
|
869
|
-
@deprecated_alias({'from_file': 'file', 'gpos_file': 'pos'}, removal_version='25.10')
|
|
870
692
|
class ImportGrid(Grid):
|
|
871
693
|
"""
|
|
872
694
|
Load a 3D grid from an XML file.
|
|
@@ -876,13 +698,14 @@ class ImportGrid(Grid):
|
|
|
876
698
|
"""
|
|
877
699
|
|
|
878
700
|
#: Name of the .xml-file from which to read the data.
|
|
879
|
-
file = Union(None, File(filter=['*.xml'], exists=True)
|
|
701
|
+
file = Union(None, File(filter=['*.xml'], exists=True))
|
|
880
702
|
|
|
881
|
-
|
|
703
|
+
#: x, y, z position of all Grid Points
|
|
704
|
+
_gpos = CArray(dtype=float)
|
|
882
705
|
|
|
883
706
|
#: Names of subgrids for each point.
|
|
884
707
|
#: This is an optional property, typically used when grids are divided into named subregions.
|
|
885
|
-
subgrids = CArray(
|
|
708
|
+
subgrids = CArray()
|
|
886
709
|
|
|
887
710
|
#: A unique identifier for the grid, based on its properties. (read-only)
|
|
888
711
|
digest = Property(depends_on=['_gpos'])
|
|
@@ -906,8 +729,8 @@ class ImportGrid(Grid):
|
|
|
906
729
|
def _set_pos(self, pos):
|
|
907
730
|
self._gpos = pos
|
|
908
731
|
|
|
909
|
-
@
|
|
910
|
-
def
|
|
732
|
+
@observe('file')
|
|
733
|
+
def _import_pos(self, event): # noqa ARG002
|
|
911
734
|
"""
|
|
912
735
|
Import the grid point locations and subgrid names from an XML file.
|
|
913
736
|
|
|
@@ -924,14 +747,14 @@ class ImportGrid(Grid):
|
|
|
924
747
|
|
|
925
748
|
>>> import numpy as np
|
|
926
749
|
>>>
|
|
927
|
-
>>> # Grid 1: ten points
|
|
750
|
+
>>> # Grid 1: ten points arranged in a circle in the x-y plane at z=0
|
|
928
751
|
>>> args = 2 * np.pi * np.arange(10) / 10
|
|
929
752
|
>>> x1 = np.cos(args)
|
|
930
753
|
>>> y1 = np.sin(args)
|
|
931
754
|
>>> z1 = np.zeros_like(x1)
|
|
932
755
|
>>> grid1 = np.vstack([x1, y1, z1]).T
|
|
933
756
|
>>>
|
|
934
|
-
>>> # Grid 2: nine points
|
|
757
|
+
>>> # Grid 2: nine points arranged in a mesh grid in the x-y plane at z=1
|
|
935
758
|
>>> a = np.linspace(-1, 1, 3)
|
|
936
759
|
>>> x2, y2 = np.meshgrid(a, a)
|
|
937
760
|
>>> z2 = np.ones_like(x2)
|
|
@@ -1030,11 +853,10 @@ class ImportGrid(Grid):
|
|
|
1030
853
|
for el in doc.getElementsByTagName('pos'):
|
|
1031
854
|
names.append(el.getAttribute('subgrid'))
|
|
1032
855
|
xyz.append([float(el.getAttribute(a)) for a in 'xyz'])
|
|
1033
|
-
self._gpos = array(xyz, 'd').swapaxes(0, 1)
|
|
1034
|
-
self.subgrids = array(names)
|
|
856
|
+
self._gpos = np.array(xyz, 'd').swapaxes(0, 1)
|
|
857
|
+
self.subgrids = np.array(names)
|
|
1035
858
|
|
|
1036
859
|
|
|
1037
|
-
@deprecated_alias({'gpos': 'pos', 'numpoints': 'num_points'}, read_only=['gpos'], removal_version='25.10')
|
|
1038
860
|
class LineGrid(Grid):
|
|
1039
861
|
"""
|
|
1040
862
|
Define a 3D grid for a line geometry.
|
|
@@ -1070,22 +892,22 @@ class LineGrid(Grid):
|
|
|
1070
892
|
loc = Tuple((0.0, 0.0, 0.0))
|
|
1071
893
|
|
|
1072
894
|
#: A vector defining the orientation of the line in 3D space. Default is ``(1.0, 0.0, 0.0)``.
|
|
1073
|
-
direction = Tuple((1.0, 0.0, 0.0)
|
|
895
|
+
direction = Tuple((1.0, 0.0, 0.0))
|
|
1074
896
|
|
|
1075
897
|
#: Total length of the line. Default is ``1.0``.
|
|
1076
|
-
length = Float(1
|
|
898
|
+
length = Float(1)
|
|
1077
899
|
|
|
1078
900
|
#: Number of grid points along the line. Default is ``1``.
|
|
1079
|
-
num_points = Int(1
|
|
901
|
+
num_points = Int(1)
|
|
1080
902
|
|
|
1081
903
|
#: The total number of grid points. Automatically updated when other grid-defining attributes
|
|
1082
904
|
#: are set. (read-only)
|
|
1083
|
-
size = Property(
|
|
905
|
+
size = Property()
|
|
1084
906
|
|
|
1085
907
|
#: A (3, :attr:`size`) array containing the x, y, and z positions of the grid points.
|
|
1086
908
|
#: (read-only)
|
|
1087
|
-
#: All positions' coordinates are in meters by default (
|
|
1088
|
-
pos = Property(
|
|
909
|
+
#: All positions' coordinates are in meters by default (:ref:`see here <units_note_grids>`).
|
|
910
|
+
pos = Property()
|
|
1089
911
|
|
|
1090
912
|
#: A unique identifier for the grid, based on its properties. (read-only)
|
|
1091
913
|
digest = Property(
|
|
@@ -1107,15 +929,14 @@ class LineGrid(Grid):
|
|
|
1107
929
|
@property_depends_on(['num_points', 'length', 'direction', 'loc'])
|
|
1108
930
|
def _get_pos(self):
|
|
1109
931
|
dist = self.length / (self.num_points - 1)
|
|
1110
|
-
loc = array(self.loc, dtype=float).reshape((3, 1))
|
|
1111
|
-
direc_n = array(self.direction) / norm(self.direction)
|
|
1112
|
-
pos = zeros((self.num_points, 3))
|
|
932
|
+
loc = np.array(self.loc, dtype=float).reshape((3, 1))
|
|
933
|
+
direc_n = np.array(self.direction) / spla.norm(self.direction)
|
|
934
|
+
pos = np.zeros((self.num_points, 3))
|
|
1113
935
|
for s in range(self.num_points):
|
|
1114
936
|
pos[s] = loc.T + direc_n * dist * s
|
|
1115
937
|
return pos.T
|
|
1116
938
|
|
|
1117
939
|
|
|
1118
|
-
@deprecated_alias({'gpos': 'pos'}, read_only=True, removal_version='25.10')
|
|
1119
940
|
class MergeGrid(Grid):
|
|
1120
941
|
"""
|
|
1121
942
|
Base class for merging multiple grid geometries.
|
|
@@ -1148,13 +969,13 @@ class MergeGrid(Grid):
|
|
|
1148
969
|
|
|
1149
970
|
#: A list of :class:`Grid` objects to be merged. Each grid is treated as a subdomain in the
|
|
1150
971
|
#: resulting merged grid.
|
|
1151
|
-
grids = List(
|
|
972
|
+
grids = List()
|
|
1152
973
|
|
|
1153
974
|
#: A list of unique digests for each grid being merged. (read-only)
|
|
1154
|
-
grid_digest = Str(
|
|
975
|
+
grid_digest = Str()
|
|
1155
976
|
|
|
1156
977
|
#: Names of subgrids corresponding to each point in the merged grid. (read-only)
|
|
1157
|
-
subgrids = Property(
|
|
978
|
+
subgrids = Property()
|
|
1158
979
|
|
|
1159
980
|
#: A unique identifier for the grid, based on its properties. (read-only)
|
|
1160
981
|
digest = Property(depends_on=['grids', 'grid_digest'])
|
|
@@ -1177,17 +998,17 @@ class MergeGrid(Grid):
|
|
|
1177
998
|
|
|
1178
999
|
@property_depends_on(['digest'])
|
|
1179
1000
|
def _get_subgrids(self):
|
|
1180
|
-
subgrids = zeros((1, 0), dtype=str)
|
|
1001
|
+
subgrids = np.zeros((1, 0), dtype=str)
|
|
1181
1002
|
for grid in self.grids:
|
|
1182
|
-
subgrids = append(subgrids, tile(grid.__class__.__name__ + grid.digest, grid.size))
|
|
1183
|
-
return subgrids[:, newaxis].T
|
|
1003
|
+
subgrids = np.append(subgrids, np.tile(grid.__class__.__name__ + grid.digest, grid.size))
|
|
1004
|
+
return subgrids[:, np.newaxis].T
|
|
1184
1005
|
|
|
1185
1006
|
@property_depends_on(['digest'])
|
|
1186
1007
|
def _get_pos(self):
|
|
1187
|
-
bpos = zeros((3, 0))
|
|
1008
|
+
bpos = np.zeros((3, 0))
|
|
1188
1009
|
for grid in self.grids:
|
|
1189
|
-
bpos = append(bpos, grid.pos, axis=1)
|
|
1190
|
-
return unique(bpos, axis=1)
|
|
1010
|
+
bpos = np.append(bpos, grid.pos, axis=1)
|
|
1011
|
+
return np.unique(bpos, axis=1)
|
|
1191
1012
|
|
|
1192
1013
|
|
|
1193
1014
|
class Sector(ABCHasStrictTraits):
|
|
@@ -1241,7 +1062,7 @@ class Sector(ABCHasStrictTraits):
|
|
|
1241
1062
|
>>> sector.contains(positions)
|
|
1242
1063
|
array([ True, True])
|
|
1243
1064
|
"""
|
|
1244
|
-
return ones(pos.shape[1], dtype=bool)
|
|
1065
|
+
return np.ones(pos.shape[1], dtype=bool)
|
|
1245
1066
|
|
|
1246
1067
|
|
|
1247
1068
|
class SingleSector(Sector):
|
|
@@ -1261,16 +1082,16 @@ class SingleSector(Sector):
|
|
|
1261
1082
|
|
|
1262
1083
|
#: If ``True``, grid points lying on the sector border are included in the sector. Default is
|
|
1263
1084
|
#: ``True``.
|
|
1264
|
-
include_border = Bool(True
|
|
1085
|
+
include_border = Bool(True)
|
|
1265
1086
|
|
|
1266
1087
|
#: The absolute tolerance to apply when determining if a grid point lies on the sector border.
|
|
1267
1088
|
#: Default is ``1e-12``.
|
|
1268
|
-
abs_tol = Float(1e-12
|
|
1089
|
+
abs_tol = Float(1e-12)
|
|
1269
1090
|
|
|
1270
1091
|
#: If ``True``, the ``contains`` method (as in :meth:`RectSector.contains`,
|
|
1271
1092
|
#: :meth:`RectSector3D.contains`, :meth:`CircSector.contains`, and :meth:`PolySector.contains`)
|
|
1272
1093
|
#: returns the nearest grid point if no grid points are inside the sector. Default is ``True``.
|
|
1273
|
-
default_nearest = Bool(True
|
|
1094
|
+
default_nearest = Bool(True)
|
|
1274
1095
|
|
|
1275
1096
|
|
|
1276
1097
|
class RectSector(SingleSector):
|
|
@@ -1289,16 +1110,16 @@ class RectSector(SingleSector):
|
|
|
1289
1110
|
"""
|
|
1290
1111
|
|
|
1291
1112
|
#: The minimum x position of the rectangle. Default is ``-1.0``.
|
|
1292
|
-
x_min = Float(-1.0
|
|
1113
|
+
x_min = Float(-1.0)
|
|
1293
1114
|
|
|
1294
1115
|
#: The maximum x position of the rectangle. Default is ``1.0``.
|
|
1295
|
-
x_max = Float(1.0
|
|
1116
|
+
x_max = Float(1.0)
|
|
1296
1117
|
|
|
1297
1118
|
#: The minimum y position of the rectangle. Default is ``-1.0``.
|
|
1298
|
-
y_min = Float(-1.0
|
|
1119
|
+
y_min = Float(-1.0)
|
|
1299
1120
|
|
|
1300
1121
|
#: The maximum y position of the rectangle. Default is ``1.0``.
|
|
1301
|
-
y_max = Float(1.0
|
|
1122
|
+
y_max = Float(1.0)
|
|
1302
1123
|
|
|
1303
1124
|
def contains(self, pos):
|
|
1304
1125
|
"""
|
|
@@ -1354,7 +1175,7 @@ class RectSector(SingleSector):
|
|
|
1354
1175
|
x = (xmin + xmax) / 2.0
|
|
1355
1176
|
y = (ymin + ymax) / 2.0
|
|
1356
1177
|
dr2 = (pos[0, :] - x) ** 2 + (pos[1, :] - y) ** 2
|
|
1357
|
-
inds[argmin(dr2)] = True
|
|
1178
|
+
inds[np.argmin(dr2)] = True
|
|
1358
1179
|
|
|
1359
1180
|
return inds.astype(bool)
|
|
1360
1181
|
|
|
@@ -1373,10 +1194,10 @@ class RectSector3D(RectSector):
|
|
|
1373
1194
|
"""
|
|
1374
1195
|
|
|
1375
1196
|
#: The lower z position of the cuboid. Default is ``-1.0``.
|
|
1376
|
-
z_min = Float(-1.0
|
|
1197
|
+
z_min = Float(-1.0)
|
|
1377
1198
|
|
|
1378
1199
|
#: The upper z position of the cuboid. Default is ``1.0``.
|
|
1379
|
-
z_max = Float(1.0
|
|
1200
|
+
z_max = Float(1.0)
|
|
1380
1201
|
|
|
1381
1202
|
def contains(self, pos):
|
|
1382
1203
|
"""
|
|
@@ -1442,7 +1263,7 @@ class RectSector3D(RectSector):
|
|
|
1442
1263
|
x = (xmin + xmax) / 2.0
|
|
1443
1264
|
y = (ymin + ymax) / 2.0
|
|
1444
1265
|
dr2 = (pos[0, :] - x) ** 2 + (pos[1, :] - y) ** 2
|
|
1445
|
-
inds[argmin(dr2)] = True
|
|
1266
|
+
inds[np.argmin(dr2)] = True
|
|
1446
1267
|
|
|
1447
1268
|
return inds.astype(bool)
|
|
1448
1269
|
|
|
@@ -1462,13 +1283,13 @@ class CircSector(SingleSector):
|
|
|
1462
1283
|
"""
|
|
1463
1284
|
|
|
1464
1285
|
#: The x position of the circle center. Default is ``0.0``.
|
|
1465
|
-
x = Float(0.0
|
|
1286
|
+
x = Float(0.0)
|
|
1466
1287
|
|
|
1467
1288
|
#: The y position of the circle center. Default is ``0.0``.
|
|
1468
|
-
y = Float(0.0
|
|
1289
|
+
y = Float(0.0)
|
|
1469
1290
|
|
|
1470
1291
|
#: Radius of the circle. Default is ``1.0``.
|
|
1471
|
-
r = Float(1.0
|
|
1292
|
+
r = Float(1.0)
|
|
1472
1293
|
|
|
1473
1294
|
def contains(self, pos):
|
|
1474
1295
|
"""
|
|
@@ -1510,7 +1331,7 @@ class CircSector(SingleSector):
|
|
|
1510
1331
|
|
|
1511
1332
|
# if there's no point inside
|
|
1512
1333
|
if ~inds.any() and self.default_nearest:
|
|
1513
|
-
inds[argmin(dr2)] = True
|
|
1334
|
+
inds[np.argmin(dr2)] = True
|
|
1514
1335
|
|
|
1515
1336
|
return inds
|
|
1516
1337
|
|
|
@@ -1567,14 +1388,14 @@ class PolySector(SingleSector):
|
|
|
1567
1388
|
>>> sec.contains(grid.pos)
|
|
1568
1389
|
array([False, False, False, False, True, True, False, True, True])
|
|
1569
1390
|
"""
|
|
1570
|
-
poly = Polygon(array(self.edges).reshape(-1, 2)[:, 0], array(self.edges).reshape(-1, 2)[:, 1])
|
|
1391
|
+
poly = Polygon(np.array(self.edges).reshape(-1, 2)[:, 0], np.array(self.edges).reshape(-1, 2)[:, 1])
|
|
1571
1392
|
dists = poly.is_inside(pos[0, :], pos[1, :])
|
|
1572
1393
|
inds = dists >= -self.abs_tol if self.include_border else dists > 0
|
|
1573
1394
|
|
|
1574
1395
|
# if none inside, take nearest
|
|
1575
1396
|
if ~inds.any() and self.default_nearest:
|
|
1576
|
-
dr2 = array(self.edges).reshape(-1, 2).mean(0)
|
|
1577
|
-
inds[argmin(dr2)] = True
|
|
1397
|
+
dr2 = np.array(self.edges).reshape(-1, 2).mean(0)
|
|
1398
|
+
inds[np.argmin(dr2)] = True
|
|
1578
1399
|
|
|
1579
1400
|
return inds
|
|
1580
1401
|
|
|
@@ -1627,12 +1448,12 @@ class ConvexSector(SingleSector):
|
|
|
1627
1448
|
>>> sec.contains(grid.pos)
|
|
1628
1449
|
array([False, False, False, False, True, True, False, True, True])
|
|
1629
1450
|
"""
|
|
1630
|
-
inds = in_hull(pos[:2, :].T, array(self.edges).reshape(-1, 2), border=self.include_border, tol=self.abs_tol)
|
|
1451
|
+
inds = in_hull(pos[:2, :].T, np.array(self.edges).reshape(-1, 2), border=self.include_border, tol=self.abs_tol)
|
|
1631
1452
|
|
|
1632
1453
|
# if none inside, take nearest
|
|
1633
1454
|
if ~inds.any() and self.default_nearest:
|
|
1634
|
-
dr2 = array(self.edges).reshape(-1, 2).mean(0) # Use the centroid of the polygon as the "center"
|
|
1635
|
-
inds[argmin(dr2)] = True
|
|
1455
|
+
dr2 = np.array(self.edges).reshape(-1, 2).mean(0) # Use the centroid of the polygon as the "center"
|
|
1456
|
+
inds[np.argmin(dr2)] = True
|
|
1636
1457
|
|
|
1637
1458
|
return inds
|
|
1638
1459
|
|
|
@@ -1687,7 +1508,7 @@ class MultiSector(Sector):
|
|
|
1687
1508
|
array([False, False, False, False, True, True, False, True, True])
|
|
1688
1509
|
"""
|
|
1689
1510
|
# initialize with only "False" entries
|
|
1690
|
-
inds = zeros(pos.shape[1], dtype=bool)
|
|
1511
|
+
inds = np.zeros(pos.shape[1], dtype=bool)
|
|
1691
1512
|
|
|
1692
1513
|
# add points contained in each sector
|
|
1693
1514
|
for sec in self.sectors:
|