Skip to content
Snippets Groups Projects
Commit 5ae2da3f authored by Gerardo Tauriello's avatar Gerardo Tauriello
Browse files

SCHWED-2440: use "peptide" flag to filter chains in mol.alg.Superpose.

This changes behaviors in MatchResidueByLocalAln and MatchResidueByGlobalAln (
or Superpose with match = local-aln or global-aln) which previously failed for
non-"protein" chains (i.e. anything w/o peptide bonds). Now, amino acid chains
without peptide bonds (e.g. CA-only) are acceptable and other chains (e.g.
ligands / water) are skipped correctly.
parent c57f05a5
Branches
Tags
No related merge requests found
...@@ -193,8 +193,8 @@ def _MatchResidueByAln(ent_a, ent_b, atoms, alnmethod): ...@@ -193,8 +193,8 @@ def _MatchResidueByAln(ent_a, ent_b, atoms, alnmethod):
## fetch chains (peptide-linking residues only) ## fetch chains (peptide-linking residues only)
chain_a = ent_a.chains[i] chain_a = ent_a.chains[i]
chain_b = ent_b.chains[i] chain_b = ent_b.chains[i]
chain_view_a = chain_a.Select('protein=true') chain_view_a = chain_a.Select('peptide=true')
chain_view_b = chain_b.Select('protein=true') chain_view_b = chain_b.Select('peptide=true')
if chain_view_a.chain_count == 0 or chain_view_b.chain_count == 0: if chain_view_a.chain_count == 0 or chain_view_b.chain_count == 0:
# skip empty chains # skip empty chains
continue continue
...@@ -240,12 +240,12 @@ def MatchResidueByLocalAln(ent_a, ent_b, atoms='all'): ...@@ -240,12 +240,12 @@ def MatchResidueByLocalAln(ent_a, ent_b, atoms='all'):
""" """
Match residues by local alignment. Takes **ent_a** and **ent_b**, extracts the Match residues by local alignment. Takes **ent_a** and **ent_b**, extracts the
sequences chain-wise and aligns them in Smith/Waterman manner using the sequences chain-wise and aligns them in Smith/Waterman manner using the
BLOSUM62 matrix for scoring. Only residues which are marked as "protein" (see BLOSUM62 matrix for scoring. Only residues which are marked as :attr:`peptide
:attr:`~ost.mol.ResidueHandle.is_protein`) are considered for alignment. The linking <ost.mol.ResidueHandle.peptide_linking>` are considered for alignment.
residues of the entities are then matched based on this alignment. Only atoms The residues of the entities are then matched based on this alignment. Only
present in both residues are included in the views. Chains are processed in atoms present in both residues are included in the views. Chains are processed
order of appearance. If **ent_a** and **ent_b** contain a different number of in order of appearance. If **ent_a** and **ent_b** contain a different number
chains, processing stops with the lower count. of chains, processing stops with the lower count.
:param ent_a: The first entity :param ent_a: The first entity
:type ent_a: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle` :type ent_a: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle`
......
...@@ -176,7 +176,7 @@ class TestConvenientSuperpose(unittest.TestCase): ...@@ -176,7 +176,7 @@ class TestConvenientSuperpose(unittest.TestCase):
view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view_wrong, ent_view) view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view_wrong, ent_view)
self.assertEqualAtomOrder(view1, view2) self.assertEqualAtomOrder(view1, view2)
def testWrongResidueOrder(self): def testWrongResidueOrder(self):
ent_view = io.LoadEntity(os.path.join("testfiles","1aho.pdb")).Select("") ent_view = io.LoadEntity(os.path.join("testfiles","1aho.pdb")).Select("")
ent_view_wrong = ent_view.CreateEmptyView() ent_view_wrong = ent_view.CreateEmptyView()
for c in ent_view.chains: for c in ent_view.chains:
...@@ -193,6 +193,37 @@ class TestConvenientSuperpose(unittest.TestCase): ...@@ -193,6 +193,37 @@ class TestConvenientSuperpose(unittest.TestCase):
view1, view2 = mol.alg.MatchResidueByNum(ent_view_wrong, ent_view) view1, view2 = mol.alg.MatchResidueByNum(ent_view_wrong, ent_view)
self.assertEqualAtomOrder(view1, view2) self.assertEqualAtomOrder(view1, view2)
def testPeptideFilter(self):
# check that CA only chains are ok and ligand chains are skipped
ent_1_full = io.LoadPDB(os.path.join("testfiles", "5tglA.pdb"))
ent_2_full = io.LoadPDB(os.path.join("testfiles", "5tglA_modified.pdb"))
exp_atom_count = 253
# check CA-only chain
ent_1 = ent_1_full.Select("cname=A")
ent_2 = ent_2_full.Select("cname=A")
view1, view2 = mol.alg.MatchResidueByLocalAln(ent_1, ent_2)
self.assertEqual(view1.atom_count, exp_atom_count)
self.assertEqual(view2.atom_count, exp_atom_count)
view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_1, ent_2)
self.assertEqual(view1.atom_count, exp_atom_count)
self.assertEqual(view2.atom_count, exp_atom_count)
# check ligand chain
ent_1_ligand = ent_1_full.Select("cname='_'")
ent_2_ligand = ent_2_full.Select("cname='_'")
view1, view2 = mol.alg.MatchResidueByLocalAln(ent_1_ligand, ent_2_ligand)
self.assertEqual(view1.atom_count, 0)
self.assertEqual(view2.atom_count, 0)
view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_1_ligand, ent_2_ligand)
self.assertEqual(view1.atom_count, 0)
self.assertEqual(view2.atom_count, 0)
# check both together
view1, view2 = mol.alg.MatchResidueByLocalAln(ent_1_full, ent_2_full)
self.assertEqual(view1.atom_count, exp_atom_count)
self.assertEqual(view2.atom_count, exp_atom_count)
view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_1_full, ent_2_full)
self.assertEqual(view1.atom_count, exp_atom_count)
self.assertEqual(view2.atom_count, exp_atom_count)
if __name__ == "__main__": if __name__ == "__main__":
from ost import testutils from ost import testutils
testutils.RunTests() testutils.RunTests()
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment