diff --git a/package/AUTHORS b/package/AUTHORS index 5e8122153db..0279ba7dde5 100644 --- a/package/AUTHORS +++ b/package/AUTHORS @@ -216,6 +216,7 @@ Chronological list of authors - Xiaoxu Ruan - Egor Marin - Shaivi Malik + - Daniel J. Evans External code ------------- diff --git a/package/CHANGELOG b/package/CHANGELOG index e228fdef8aa..7b116ca0f28 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -21,6 +21,8 @@ The rules for this file: * 2.5.0 Fixes + * Fix chi1_selections() ignored atom names CG1 OG OG1 SG and incorrectly returned + None for amino acids CYS, ILE, SER, THR, VAL (Issue #4108) * Fix parsing of box vector in H5MD reader (Issue #4076) * Fix the misleading 'AtomGroup.guess_bonds()' docs and passed missing arguments (PR #4059) @@ -37,6 +39,7 @@ Fixes (Issue #3336) Enhancements + * Improved speed of chi1_selection (PR #4109) * Add `progressbar_kwargs` parameter to `AnalysisBase.run` method, allowing to modify description, position etc of tqdm progressbars. * Add a nojump transformation, which unwraps trajectories so that particle paths are continuous. (Issue #3703, PR #4031) diff --git a/package/MDAnalysis/core/topologyattrs.py b/package/MDAnalysis/core/topologyattrs.py index 197e4fe96dc..c7685f7c5b6 100644 --- a/package/MDAnalysis/core/topologyattrs.py +++ b/package/MDAnalysis/core/topologyattrs.py @@ -1233,7 +1233,8 @@ def chi1_selection(residue, n_name='N', ca_name='CA', cb_name='CB', faster atom matching with boolean arrays. """ names = [n_name, ca_name, cb_name, cg_name] - ags = [residue.atoms.select_atoms(f"name {n}") for n in names] + atnames = residue.atoms.names + ags = [residue.atoms[np.in1d(atnames, n.split())] for n in names] if any(len(ag) != 1 for ag in ags): return None return sum(ags) @@ -1241,7 +1242,7 @@ def chi1_selection(residue, n_name='N', ca_name='CA', cb_name='CB', transplants[Residue].append(('chi1_selection', chi1_selection)) def chi1_selections(residues, n_name='N', ca_name='CA', cb_name='CB', - cg_name='CG'): + cg_name='CG CG1 OG OG1 SG'): """Select list of AtomGroups corresponding to the chi1 sidechain dihedral N-CA-CB-CG. @@ -1266,13 +1267,13 @@ def chi1_selections(residues, n_name='N', ca_name='CA', cb_name='CB', """ results = np.array([None]*len(residues)) names = [n_name, ca_name, cb_name, cg_name] - keep = [all(sum(r.atoms.names == n) == 1 for n in names) - for r in residues] + keep = [all(sum(np.in1d(r.atoms.names, n.split())) == 1 + for n in names) for r in residues] keepix = np.where(keep)[0] residues = residues[keep] atnames = residues.atoms.names - ags = [residues.atoms[atnames == n] for n in names] + ags = [residues.atoms[np.in1d(atnames, n.split())] for n in names] results[keepix] = [sum(atoms) for atoms in zip(*ags)] return list(results) diff --git a/testsuite/MDAnalysisTests/core/test_atomgroup.py b/testsuite/MDAnalysisTests/core/test_atomgroup.py index 2174e4794e4..2e3036bad35 100644 --- a/testsuite/MDAnalysisTests/core/test_atomgroup.py +++ b/testsuite/MDAnalysisTests/core/test_atomgroup.py @@ -874,6 +874,12 @@ def test_chi1_selections(self, resgroup): rssel = [r.chi1_selection() for r in resgroup] assert_equal(rgsel, rssel) + @pytest.mark.parametrize("resname", ["CYS", "ILE", "SER", "THR", "VAL"]) + def test_chi1_selections_non_cg(self, resname, PSFDCD): + resgroup = PSFDCD.select_atoms(f"resname {resname}").residues + rgsel = resgroup.chi1_selections() + assert not any(sel is None for sel in rgsel) + @pytest.mark.parametrize("resname", ["CYSH", "ILE", "SER", "THR", "VAL"]) def test_chi1_selection_non_cg_gromacs(self, resname, TPR): resgroup = TPR.select_atoms(f"resname {resname}").residues