Skip to content

Commit 9ccde9b

Browse files
authored
Allow using selection keywords as residue names (#5119)
* Allow selecting residues that share a name with a keyword * Update selection docs with example of how to escape keywords when selecting atoms * Add tests for selecting residues that share a name with a keyword
1 parent c0685ac commit 9ccde9b

File tree

4 files changed

+21
-4
lines changed

4 files changed

+21
-4
lines changed

package/CHANGELOG

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ The rules for this file:
1616
-------------------------------------------------------------------------------
1717
??/??/?? IAlibay, orbeckst, BHM-Bob, TRY-ER, Abdulrahman-PROG, pbuslaev,
1818
yuxuanzhuang, yuyuan871111, tanishy7777, tulga-rdn, Gareth-elliott,
19-
hmacdope, tylerjereddy, cbouy, talagayev, DrDomenicoMarson, amruthesht
19+
hmacdope, tylerjereddy, cbouy, talagayev, DrDomenicoMarson, amruthesht,
20+
p-j-smith
2021

2122

2223
* 2.10.0
2324

2425
Fixes
26+
* Fix atom selection parsing to allow escaping keywords with a backslash
27+
(Issue #5111, PR #5119)
2528
* Fix DCDWriter to correctly write unit cell angles as cosines following
2629
NAMD/VMD convention (Issue #5069)
2730
* Fixed an integer overflow in large DCD file seeks on Windows

package/MDAnalysis/core/selection.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ def is_keyword(val):
8585
def grab_not_keywords(tokens):
8686
"""Pop tokens from the left until you hit a keyword
8787
88+
Keywords can be escaped with a backslash to allow their use as names,
89+
e.g. '\\protein'
90+
8891
Parameters
8992
----------
9093
tokens : collections.deque
@@ -113,8 +116,8 @@ def grab_not_keywords(tokens):
113116
values = []
114117
while not is_keyword(tokens[0]):
115118
val = tokens.popleft()
116-
# Insert escape characters here to use keywords as names?
117-
values.append(val)
119+
# Remove escape sequence to allow use of keywords as names
120+
values.append(val.removeprefix("\\"))
118121
return values
119122

120123

package/doc/sphinx/source/documentation_pages/selections.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ resnum *resnum-number-range*
138138
residue id in the original PDB structure.
139139

140140
resname *residue-name*
141-
select by residue name, e.g. ``resname LYS``
141+
select by residue name, e.g. ``resname LYS``. If a residue shares a name
142+
with a selection keyword, the name must be escaped e.g. ``resname \\water``.
142143

143144
name *atom-name*
144145
select by atom name (as given in the topology). Often, this is force

testsuite/MDAnalysisTests/core/test_atomselections.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ def test_protein_resnames(self, resname):
107107
# check that contents (atom indices) are identical afterwards
108108
assert_equal(myprot.atoms.ix, sel.ix)
109109

110+
def test_residue_named_protein(self):
111+
u = make_Universe(("resnames",))
112+
myprot = u.residues[::2]
113+
myprot.resnames = "protein"
114+
sel = u.select_atoms("resname \\protein")
115+
# check that contents (atom indices) are identical afterwards
116+
assert_equal(myprot.atoms.ix, sel.ix)
117+
110118
def test_backbone(self, universe):
111119
sel = universe.select_atoms("backbone")
112120
assert_equal(sel.n_atoms, 855)
@@ -1226,6 +1234,7 @@ def universe():
12261234
"resnum ",
12271235
"bynum or protein",
12281236
"index or protein",
1237+
"resname protein", # unexpected token
12291238
"prop mass < 4.0 hello", # unused token
12301239
"prop mass > 10. and group this", # missing group
12311240
# bad ranges
@@ -1472,6 +1481,7 @@ def test_similarity_selection_icodes(u_pdb_icodes, selection, n_atoms):
14721481
"name N*",
14731482
"resname stuff",
14741483
"resname ALA",
1484+
"resname \\protein",
14751485
"type O",
14761486
"index 0",
14771487
"index 1",

0 commit comments

Comments
 (0)