Skip to content

Commit 350c5a5

Browse files
committed
add relprop for atom selection and corresponding UT
1 parent a3672f2 commit 350c5a5

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

package/MDAnalysis/core/selection.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,51 @@ def _apply(self, group):
13531353
return group[mask]
13541354

13551355

1356+
class RelPropertySelection(PropertySelection):
1357+
"""Some of the possible properties:
1358+
x, y, z,
1359+
1360+
.. versionadded:: 2.9.0
1361+
"""
1362+
1363+
token = "relprop"
1364+
precedence = 1
1365+
1366+
def __init__(self, parser, tokens):
1367+
super().__init__(parser, tokens)
1368+
self.sel = parser.parse_expression(self.precedence)
1369+
# self.ori_value = self.value
1370+
1371+
def _apply(self, group):
1372+
try:
1373+
values = getattr(group, self.props[self.prop])
1374+
except KeyError:
1375+
errmsg = f"Expected one of {list(self.props.keys())}"
1376+
raise SelectionError(errmsg) from None
1377+
except NoDataError:
1378+
attr = self.props[self.prop]
1379+
errmsg = f"This Universe does not contain {attr} information"
1380+
raise SelectionError(errmsg) from None
1381+
1382+
try:
1383+
col = {"x": 0, "y": 1, "z": 2}[self.prop]
1384+
except KeyError:
1385+
pass
1386+
else:
1387+
values = values[:, col]
1388+
sel = self.sel.apply(group)
1389+
rel_value = (
1390+
sel.center_of_geometry().reshape(3).astype(np.float32)[col]
1391+
)
1392+
values -= rel_value
1393+
1394+
if self.absolute:
1395+
values = np.abs(values)
1396+
mask = self.operator(values, self.value)
1397+
1398+
return group[mask]
1399+
1400+
13561401
class SameSelection(Selection):
13571402
"""
13581403
Selects all atoms that have the same subkeyword value as any atom in selection

testsuite/MDAnalysisTests/core/test_atomselections.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,17 @@ def test_prop(self, universe):
253253
assert_equal(len(sel), 3194)
254254
assert_equal(len(sel2), 2001)
255255

256+
def test_relprop(self, universe):
257+
sel1 = universe.select_atoms("relprop z <= 1 index 0")
258+
sel2 = universe.select_atoms("relprop abs z <= 1 index 0")
259+
260+
positions = universe.trajectory[0].positions
261+
ref = positions[0, 2]
262+
mask_1 = (positions[:, 2] - ref) <= 1
263+
assert_equal(len(sel1), np.count_nonzero(mask_1))
264+
mask_2 = np.abs(positions[:, 2] - ref) <= 1
265+
assert_equal(len(sel2), np.count_nonzero(mask_2))
266+
256267
def test_bynum(self, universe):
257268
"Tests the bynum selection, also from AtomGroup instances (Issue 275)"
258269
sel = universe.select_atoms('bynum 5')

0 commit comments

Comments
 (0)