Skip to content

Commit 9fa18bc

Browse files
Final black formatting and recursion fix for PKDTree
1 parent 5c4a49f commit 9fa18bc

2 files changed

Lines changed: 87 additions & 60 deletions

File tree

package/MDAnalysis/lib/pkdtree.py

Lines changed: 82 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ class AugmentedPKDTree(object):
5656
duplicate particles while maintaining correctness.
5757
"""
5858

59-
def __init__(
60-
self, box: Optional[npt.ArrayLike] = None, leafsize: int = 10
61-
) -> None:
59+
def __init__(self, box: Optional[npt.ArrayLike] = None, leafsize: int = 10) -> None:
6260
"""
6361
6462
Parameters
@@ -78,15 +76,15 @@ def __init__(
7876
self.leafsize = leafsize
7977
self.dim = 3 # 3D systems
8078
self.box = box
81-
79+
8280
if self.box is not None:
8381
self.box = np.asarray(box, dtype=np.float32)
8482
# Cache orthorhombic check - don't recompute every time
8583
self._is_ortho = self._check_orthorhombic()
8684
else:
8785
self.box = None
8886
self._is_ortho = True
89-
87+
9088
self._built = False
9189
self.cutoff: Optional[float] = None
9290
self.mapping = None # For compatibility, always None in this implementation
@@ -113,9 +111,7 @@ def pbc(self):
113111
"""
114112
return self.box is not None
115113

116-
def set_coords(
117-
self, coords: npt.ArrayLike, cutoff: Optional[float] = None
118-
) -> None:
114+
def set_coords(self, coords: npt.ArrayLike, cutoff: Optional[float] = None) -> None:
119115
"""Constructs KDTree from the coordinates
120116
121117
For orthorhombic boxes, uses scipy's native boxsize parameter
@@ -139,29 +135,33 @@ def set_coords(
139135
# Set coords dtype to float32
140136
coords = np.asarray(coords, dtype=np.float32)
141137
self.cutoff = cutoff
142-
138+
143139
if self.box is None:
144140
# Non-periodic case
145141
if cutoff is not None:
146-
raise RuntimeError("Donot provide cutoff distance for non PBC aware calculations")
147-
142+
raise RuntimeError(
143+
"Donot provide cutoff distance for non PBC aware calculations"
144+
)
145+
148146
self.coords = coords
149147
self.ckdt = cKDTree(self.coords, leafsize=self.leafsize)
150148
self._use_scipy = True
151149
self._use_capped = False
152150
self._built = True
153151
return
154-
152+
155153
# Periodic case - cutoff required
156154
if cutoff is None:
157155
raise RuntimeError("Provide a cutoff distance with tree.set_coords(...)")
158-
156+
159157
if self._is_ortho:
160158
# Orthorhombic box - use scipy's native PBC support
161159
# Wrap coordinates once during tree construction
162160
# scipy's boxsize parameter handles PBC during queries efficiently
163161
self.coords = apply_PBC(coords, self.box)
164-
self.ckdt = cKDTree(self.coords, leafsize=self.leafsize, boxsize=self.box[:3])
162+
self.ckdt = cKDTree(
163+
self.coords, leafsize=self.leafsize, boxsize=self.box[:3]
164+
)
165165
self._use_scipy = True
166166
self._use_capped = False
167167
else:
@@ -197,7 +197,7 @@ def search(self, centers: npt.ArrayLike, radius: float) -> npt.NDArray:
197197
raise ValueError("Cutoff needs to be provided when working with PBC.")
198198
if self.cutoff < radius:
199199
raise RuntimeError("Set cutoff greater or equal to the radius.")
200-
200+
201201
if self._use_scipy:
202202
# scipy's boxsize parameter handles PBC, but wrap centers to be safe
203203
wrapped_centers = apply_PBC(centers, self.box)
@@ -215,18 +215,22 @@ def search(self, centers: npt.ArrayLike, radius: float) -> npt.NDArray:
215215
self.coords,
216216
radius,
217217
box=self.box,
218-
return_distances=False
218+
return_distances=False,
219219
)
220220
if len(pairs) > 0:
221221
all_indices.extend(pairs[:, 1])
222-
self._indices = np.array(all_indices, dtype=np.intp) if all_indices else np.array([], dtype=np.intp)
222+
self._indices = (
223+
np.array(all_indices, dtype=np.intp)
224+
if all_indices
225+
else np.array([], dtype=np.intp)
226+
)
223227
else:
224228
# Non-periodic case
225229
indices = list(self.ckdt.query_ball_point(centers, radius))
226230
self._indices = np.array(
227231
list(itertools.chain.from_iterable(indices)), dtype=np.intp
228232
)
229-
233+
230234
if self._indices.size > 0:
231235
self._indices = np.asarray(unique_int_1d(self._indices))
232236
return self._indices
@@ -262,13 +266,15 @@ def search_pairs(self, radius: float) -> npt.NDArray:
262266
raise ValueError("Cutoff needs to be provided when working with PBC.")
263267
if self.cutoff < radius:
264268
raise RuntimeError("Set cutoff greater or equal to the radius.")
265-
269+
266270
if self._use_scipy:
267271
# scipy handles PBC with boxsize parameter
268272
pairs = np.array(list(self.ckdt.query_pairs(radius)), dtype=np.intp)
269273
elif self._use_capped:
270274
# Use self_capped_distance for triclinic boxes
271-
pairs = self_capped_distance(self.coords, radius, box=self.box, return_distances=False)
275+
pairs = self_capped_distance(
276+
self.coords, radius, box=self.box, return_distances=False
277+
)
272278
pairs = np.asarray(pairs)
273279
else:
274280
# Non-periodic fallback
@@ -319,40 +325,49 @@ def search_tree(self, centers: npt.ArrayLike, radius: float) -> np.ndarray:
319325
raise ValueError("Cutoff needs to be provided when working with PBC.")
320326
if self.cutoff < radius:
321327
raise RuntimeError("Set cutoff greater or equal to the radius.")
322-
328+
323329
if self._use_scipy:
324330
if self.pbc:
325331
# Wrap centers for scipy's boxsize parameter
326332
wrapped_centers = apply_PBC(centers, self.box)
327-
other_tree = cKDTree(wrapped_centers, leafsize=self.leafsize, boxsize=self.box[:3])
333+
other_tree = cKDTree(
334+
wrapped_centers, leafsize=self.leafsize, boxsize=self.box[:3]
335+
)
328336
else:
329337
other_tree = cKDTree(centers, leafsize=self.leafsize)
330-
338+
331339
pairs_list = other_tree.query_ball_tree(self.ckdt, radius)
332-
pairs = np.array([[i, j] for i, lst in enumerate(pairs_list) for j in lst], dtype=np.intp)
333-
340+
pairs = np.array(
341+
[[i, j] for i, lst in enumerate(pairs_list) for j in lst], dtype=np.intp
342+
)
343+
334344
elif self._use_capped:
335345
# Wrap centers for triclinic boxes and use capped_distance
336346
wrapped_centers = apply_PBC(centers, self.box)
337-
pairs = capped_distance(wrapped_centers, self.coords, radius,
338-
box=self.box, return_distances=False)
347+
pairs = capped_distance(
348+
wrapped_centers,
349+
self.coords,
350+
radius,
351+
box=self.box,
352+
return_distances=False,
353+
)
339354
pairs = np.asarray(pairs)
340355
else:
341356
# Non-periodic fallback
342357
other_tree = cKDTree(centers, leafsize=self.leafsize)
343358
pairs_list = other_tree.query_ball_tree(self.ckdt, radius)
344-
pairs = np.array([[i, j] for i, lst in enumerate(pairs_list) for j in lst], dtype=np.intp)
345-
359+
pairs = np.array(
360+
[[i, j] for i, lst in enumerate(pairs_list) for j in lst], dtype=np.intp
361+
)
362+
346363
if pairs.size > 0:
347364
pairs = unique_rows(pairs)
348365
return pairs
349-
366+
350367

351368
class PeriodicKDTree(object):
352369

353-
def __init__(
354-
self, box: Optional[npt.ArrayLike] = None, leafsize: int = 10
355-
) -> None:
370+
def __init__(self, box: Optional[npt.ArrayLike] = None, leafsize: int = 10) -> None:
356371
"""
357372
358373
Parameters
@@ -373,9 +388,9 @@ def __init__(
373388
self.dim = 3 # 3D systems
374389
self.box = box
375390
self._built = False
376-
self.cutoff: Optional[float] = None
391+
self.cutoff: Optional[float] = None
377392
self.mapping = None # For compatibility, always None in this implementation
378-
393+
379394
_use_augmented = False
380395
if box is not None:
381396
box_array = np.asarray(box, dtype=np.float32)
@@ -384,11 +399,13 @@ def __init__(
384399
_use_augmented = True
385400
else:
386401
_use_augmented = True
387-
402+
388403
self._use_augmented = _use_augmented
389-
404+
390405
if self._use_augmented:
391-
self._tree: Union[AugmentedPKDTree, cKDTree, None] = AugmentedPKDTree(box=self.box, leafsize=leafsize)
406+
self._tree: Union[AugmentedPKDTree, cKDTree, None] = AugmentedPKDTree(
407+
box=self.box, leafsize=leafsize
408+
)
392409
else:
393410
self._tree = None
394411
if box is not None:
@@ -406,9 +423,7 @@ def pbc(self):
406423
"""
407424
return self.box is not None
408425

409-
def set_coords(
410-
self, coords: npt.ArrayLike, cutoff: Optional[float] = None
411-
) -> None:
426+
def set_coords(self, coords: npt.ArrayLike, cutoff: Optional[float] = None) -> None:
412427
"""Constructs KDTree from the coordinates
413428
414429
Parameters
@@ -427,19 +442,25 @@ def set_coords(
427442
else:
428443
coords = np.asarray(coords, dtype=np.float32)
429444
self.cutoff = cutoff
430-
445+
431446
if self.box is None:
432447
if cutoff is not None:
433-
raise RuntimeError("Donot provide cutoff distance for non PBC aware calculations")
448+
raise RuntimeError(
449+
"Donot provide cutoff distance for non PBC aware calculations"
450+
)
434451
self.coords = coords
435452
self._tree = cKDTree(self.coords, leafsize=self.leafsize)
436453
else:
437454
if cutoff is None:
438-
raise RuntimeError("Provide a cutoff distance with tree.set_coords(...)")
455+
raise RuntimeError(
456+
"Provide a cutoff distance with tree.set_coords(...)"
457+
)
439458
self.coords = apply_PBC(coords, self.box)
440459
box_array = np.asarray(self.box, dtype=np.float32)
441-
self._tree = cKDTree(self.coords, leafsize=self.leafsize, boxsize=box_array[:3])
442-
460+
self._tree = cKDTree(
461+
self.coords, leafsize=self.leafsize, boxsize=box_array[:3]
462+
)
463+
443464
self._built = True
444465

445466
def search(self, centers: npt.ArrayLike, radius: float) -> npt.NDArray:
@@ -458,7 +479,7 @@ def search(self, centers: npt.ArrayLike, radius: float) -> npt.NDArray:
458479
if self._use_augmented:
459480
assert self._tree is not None
460481
return self._tree.search(centers, radius)
461-
482+
462483
centers = np.asarray(centers, dtype=np.float32)
463484
if centers.shape == (self.dim,):
464485
centers = centers.reshape((1, self.dim))
@@ -474,11 +495,11 @@ def search(self, centers: npt.ArrayLike, radius: float) -> npt.NDArray:
474495
else:
475496
assert isinstance(self._tree, cKDTree)
476497
indices = list(self._tree.query_ball_point(centers, radius))
477-
498+
478499
self._indices = np.array(
479500
list(itertools.chain.from_iterable(indices)), dtype=np.intp
480501
)
481-
502+
482503
if self._indices.size > 0:
483504
self._indices = np.asarray(unique_int_1d(self._indices))
484505
return self._indices
@@ -515,16 +536,16 @@ def search_pairs(self, radius: float) -> npt.NDArray:
515536
if self._use_augmented:
516537
assert self._tree is not None
517538
return self._tree.search_pairs(radius)
518-
539+
519540
if self.pbc:
520541
if self.cutoff is None:
521542
raise ValueError("Cutoff needs to be provided when working with PBC.")
522543
if self.cutoff < radius:
523544
raise RuntimeError("Set cutoff greater or equal to the radius.")
524-
545+
525546
assert isinstance(self._tree, cKDTree)
526547
pairs = np.array(list(self._tree.query_pairs(radius)), dtype=np.intp)
527-
548+
528549
if pairs.size > 0:
529550
pairs = np.sort(pairs, axis=1)
530551
pairs = unique_rows(pairs)
@@ -556,7 +577,7 @@ def search_tree(self, centers: npt.ArrayLike, radius: float) -> np.ndarray:
556577
if self._use_augmented:
557578
assert self._tree is not None
558579
return self._tree.search_tree(centers, radius)
559-
580+
560581
centers = np.asarray(centers, dtype=np.float32)
561582
if centers.shape == (self.dim,):
562583
centers = centers.reshape((1, self.dim))
@@ -568,13 +589,17 @@ def search_tree(self, centers: npt.ArrayLike, radius: float) -> np.ndarray:
568589
raise RuntimeError("Set cutoff greater or equal to the radius.")
569590
wrapped_centers = apply_PBC(centers, self.box)
570591
box_array = np.asarray(self.box, dtype=np.float32)
571-
other_tree = cKDTree(wrapped_centers, leafsize=self.leafsize, boxsize=box_array[:3])
592+
other_tree = cKDTree(
593+
wrapped_centers, leafsize=self.leafsize, boxsize=box_array[:3]
594+
)
572595
else:
573596
other_tree = cKDTree(centers, leafsize=self.leafsize)
574-
597+
575598
pairs_list = other_tree.query_ball_tree(self._tree, radius)
576-
pairs = np.array([[i, j] for i, lst in enumerate(pairs_list) for j in lst], dtype=np.intp)
599+
pairs = np.array(
600+
[[i, j] for i, lst in enumerate(pairs_list) for j in lst], dtype=np.intp
601+
)
577602

578603
if pairs.size > 0:
579604
pairs = unique_rows(pairs)
580-
return pairs
605+
return pairs

testsuite/MDAnalysisTests/lib/test_pkdtree.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929
from MDAnalysis.lib.pkdtree import PeriodicKDTree, AugmentedPKDTree
3030
from MDAnalysis.lib.distances import transform_StoR
3131

32+
3233
@pytest.fixture(params=[PeriodicKDTree, AugmentedPKDTree])
3334
def tree_class(request):
3435
"""Fixture to run tests on both PeriodicKDTree and AugmentedPKDTree."""
3536
return request.param
3637

38+
3739
# fractional coordinates for data points
3840
f_dataset = np.array(
3941
[
@@ -62,7 +64,7 @@ def tree_class(request):
6264
),
6365
),
6466
)
65-
def test_setcoords(tree_class , b, cut, result):
67+
def test_setcoords(tree_class, b, cut, result):
6668
coords = np.array([[1, 1, 1], [2, 2, 2]], dtype=np.float32)
6769
if b is not None:
6870
b = np.array(b, dtype=np.float32)
@@ -93,7 +95,7 @@ def test_searchfail(tree_class):
9395
([10, 10, 10, 45, 60, 90], [2.1, -3.1, 0.1], [2, 3]),
9496
),
9597
)
96-
def test_search(tree_class , b, q, result):
98+
def test_search(tree_class, b, q, result):
9799
b = np.array(b, dtype=np.float32)
98100
q = transform_StoR(np.array(q, dtype=np.float32), b)
99101
cutoff = 3.0
@@ -165,7 +167,7 @@ def test_ckd_searchpairs_nopbc(tree_class, radius, result):
165167
[0, 3]])
166168
))
167169
# fmt: on
168-
def test_searchtree(tree_class , b, q, result):
170+
def test_searchtree(tree_class, b, q, result):
169171
b = np.array(b, dtype=np.float32)
170172
cutoff = 3.0
171173
coords = transform_StoR(f_dataset, b)

0 commit comments

Comments
 (0)