diff --git a/modules/mol/alg/pymod/superpose.py b/modules/mol/alg/pymod/superpose.py index e50a814bc9d2bcac7c56a89a71722761f4ff960d..4cf8de56d57c97e2dc7a46352cff3e3ab30d259c 100644 --- a/modules/mol/alg/pymod/superpose.py +++ b/modules/mol/alg/pymod/superpose.py @@ -203,8 +203,8 @@ def _MatchResidueByAln(ent_a, ent_b, atoms, alnmethod): ## evaluate alignment for aln in aln_a_b: ## bind chain to alignment - aln.AttachView(0, chain_a.Select("")) - aln.AttachView(1, chain_b.Select("")) + aln.AttachView(0, chain_a.Select('protein=True')) + aln.AttachView(1, chain_b.Select('protein=True')) ## select residues (only replacement edges) for i in range(0, aln.GetLength()): if aln.sequences[0][i]!='-' and aln.sequences[1][i]!='-': @@ -218,13 +218,12 @@ def _MatchResidueByAln(ent_a, ent_b, atoms, alnmethod): def MatchResidueByLocalAln(ent_a, ent_b, atoms='all'): """ Match residues by local alignment. Takes **ent_a** and **ent_b**, extracts - the sequences chain-wise and aligns them in Smith/Waterman manner. For - scoring, the BLOSUM62 matrix is used. The local alignment is used to gather - residues from both entities, only touching atoms as defined by **atoms**. - Regardless of what the list of **atoms** says, only those present in two - matched residues will be included in the returned views. Chains are processed - in order of appearance. If **ent_a** and **ent_b** contain a different number - of chains, processing stops with the lower count. + the sequences chain-wise and aligns them in Smith/Waterman manner using the + BLOSUM62 matrix for scoring. The residues of the entities are then matched + based on this alignment. Only atoms present in both residues are included in + the views. Chains are processed in order of appearance. If **ent_a** and + **ent_b** contain a different number of chains, processing stops with + the lower count. :param ent_a: The first entity :type ent_a: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle` @@ -240,13 +239,12 @@ def MatchResidueByLocalAln(ent_a, ent_b, atoms='all'): def MatchResidueByGlobalAln(ent_a, ent_b, atoms='all'): """ Match residues by global alignment. Takes **ent_a** and **ent_b**, extracts - the sequences chain-wise and aligns them in Needleman/Wunsch manner. For - scoring, the BLOSUM62 matrix is used. The global alignment is used to gather - residues from both entities, only touching atoms as defined by **atoms**. - Regardless of what the list of **atoms** says, only those present in two - matched residues will be included in the returned views. Chains are processed - in order of appearance. If **ent_a** and **ent_b** contain a different number - of chains, processing stops with the lower count. + the sequences chain-wise and aligns them in Needleman/Wunsch manner using the + BLOSUM62 matrix for scoring. The residues of the entities are then matched + based on this alignment. Only atoms present in both residues are included in + the views. Chains are processed in order of appearance. If **ent_a** and + **ent_b** contain a different number of chains, processing stops with + the lower count. :param ent_a: The first entity :type ent_a: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle` @@ -274,10 +272,10 @@ def Superpose(ent_a, ent_b, match='number', atoms='all'): * ``index`` - select residues by index in chain, includes **atoms**, calls :func:`~ost.mol.alg.MatchResidueByIdx` - * ``local`` - select residues from a Smith/Waterman alignment, includes + * ``local-aln`` - select residues from a Smith/Waterman alignment, includes **atoms**, calls :func:`~ost.mol.alg.MatchResidueByLocalAln` - * ``global`` - select residues from a Needleman/Wunsch alignment, includes + * ``global-aln`` - select residues from a Needleman/Wunsch alignment, includes **atoms**, calls :func:`~ost.mol.alg.MatchResidueByGlobalAln` :param ent_a: The first entity @@ -290,7 +288,7 @@ def Superpose(ent_a, ent_b, match='number', atoms='all'): :type atoms: :class:`str`, :class:`list`, :class:`set` :returns: An instance of :class:`SuperpositionResult`, containing members - * ``rmsd`` - Rmsd of the superposed entities + * ``rmsd`` - RMSD of the superposed entities * ``view1`` - First :class:`~ost.mol.EntityView` used @@ -302,10 +300,10 @@ def Superpose(ent_a, ent_b, match='number', atoms='all'): view_a, view_b = MatchResidueByNum(ent_a, ent_b, atoms) elif match.upper() == 'INDEX': view_a, view_b=MatchResidueByIdx(ent_a, ent_b, atoms) - elif match.upper() == 'LOCAL': + elif match.upper() == 'LOCAL-ALN': view_a, view_b=_MatchResidueByAln(ent_a, ent_b, atoms, ost.seq.alg.LocalAlign) - elif match.upper() == 'GLOBAL': + elif match.upper() == 'GLOBAL-ALN': view_a, view_b=_MatchResidueByAln(ent_a, ent_b, atoms, ost.seq.alg.GlobalAlign) else: diff --git a/modules/mol/alg/tests/test_convenient_superpose.py b/modules/mol/alg/tests/test_convenient_superpose.py index e247b68b2de26b8b5ee0cbf3b66b4a5c3219e8cf..7e03558c06647705589200688fb313df909e5c5b 100644 --- a/modules/mol/alg/tests/test_convenient_superpose.py +++ b/modules/mol/alg/tests/test_convenient_superpose.py @@ -27,7 +27,7 @@ class TestConvenientSuperpose(unittest.TestCase): ent1_view = ent1_ent.Select("") ## test MatchResidueByNum view1, view2 = mol.alg.MatchResidueByNum(ent1_ent, ent1_ent) - self.assertEqualAtomOrder(view1, view2) + self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByNum(ent1_view, ent1_ent) self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByNum(ent1_ent, ent1_view) @@ -36,14 +36,32 @@ class TestConvenientSuperpose(unittest.TestCase): self.assertEqualAtomOrder(view1, view2) ## test MatchResidueByIdx view1, view2 = mol.alg.MatchResidueByIdx(ent1_ent, ent1_ent) - self.assertEqualAtomOrder(view1, view2) + self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByIdx(ent1_view, ent1_ent) self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByIdx(ent1_ent, ent1_view) self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByIdx(ent1_view, ent1_view) self.assertEqualAtomOrder(view1, view2) - + ## test MatchResidueByGlobalAln + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent1_ent, ent1_ent) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent1_view, ent1_ent) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent1_ent, ent1_view) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent1_view, ent1_view) + self.assertEqualAtomOrder(view1, view2) + ## test MatchResidueByLocalAln + view1, view2 = mol.alg.MatchResidueByLocalAln(ent1_ent, ent1_ent) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByLocalAln(ent1_view, ent1_ent) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByLocalAln(ent1_ent, ent1_view) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByLocalAln(ent1_view, ent1_view) + self.assertEqualAtomOrder(view1, view2) + def testMissingFirstAtom(self): ent_view = io.LoadEntity(os.path.join("testfiles","1aho.pdb")).Select("") ent_view_missing = ent_view.Select("not (cname=A and rnum=1 and aname=N)") @@ -57,7 +75,17 @@ class TestConvenientSuperpose(unittest.TestCase): self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByIdx(ent_view_missing, ent_view) self.assertEqualAtomOrder(view1, view2) - + ## test MatchResidueByGlobalAln + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_view, ent_view_missing) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_view_missing, ent_view) + self.assertEqualAtomOrder(view1, view2) + ## test MatchResidueByLocalAln + view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view, ent_view_missing) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view_missing, ent_view) + self.assertEqualAtomOrder(view1, view2) + def testMissingManyAtoms(self): ent_view = io.LoadEntity(os.path.join("testfiles","1aho.pdb")).Select("") ent_view_missing = ent_view.Select("not (cname=A and rnum=3,19,32 and aname=CB,CA,CD)") @@ -71,7 +99,17 @@ class TestConvenientSuperpose(unittest.TestCase): self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByIdx(ent_view_missing, ent_view) self.assertEqualAtomOrder(view1, view2) - + ## test MatchResidueByGlobalAln + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_view, ent_view_missing) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_view_missing, ent_view) + self.assertEqualAtomOrder(view1, view2) + ## test MatchResidueByLocalAln + view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view, ent_view_missing) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view_missing, ent_view) + self.assertEqualAtomOrder(view1, view2) + def testMissingFirstResidue(self): ent_view = io.LoadEntity(os.path.join("testfiles","1aho.pdb")).Select("") ent_view_missing = ent_view.Select("not (cname=A and rnum=1)") @@ -80,6 +118,16 @@ class TestConvenientSuperpose(unittest.TestCase): self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByNum(ent_view_missing, ent_view) self.assertEqualAtomOrder(view1, view2) + ## test MatchResidueByGlobalAln + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_view, ent_view_missing) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_view_missing, ent_view) + self.assertEqualAtomOrder(view1, view2) + ## test MatchResidueByLocalAln + view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view, ent_view_missing) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view_missing, ent_view) + self.assertEqualAtomOrder(view1, view2) def testMissingHydrogens(self): ent_view = io.LoadEntity(os.path.join("testfiles","1aho.pdb")).Select("") @@ -116,7 +164,17 @@ class TestConvenientSuperpose(unittest.TestCase): self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByIdx(ent_view_wrong, ent_view) self.assertEqualAtomOrder(view1, view2) - + ## test MatchResidueByGlobalAln + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_view, ent_view_wrong) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByGlobalAln(ent_view_wrong, ent_view) + self.assertEqualAtomOrder(view1, view2) + ## test MatchResidueByLocalAln + view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view, ent_view_wrong) + self.assertEqualAtomOrder(view1, view2) + view1, view2 = mol.alg.MatchResidueByLocalAln(ent_view_wrong, ent_view) + self.assertEqualAtomOrder(view1, view2) + def testWrongResidueOrder(self): ent_view = io.LoadEntity(os.path.join("testfiles","1aho.pdb")).Select("") ent_view_wrong = ent_view.CreateEmptyView() @@ -133,6 +191,6 @@ class TestConvenientSuperpose(unittest.TestCase): self.assertEqualAtomOrder(view1, view2) view1, view2 = mol.alg.MatchResidueByNum(ent_view_wrong, ent_view) self.assertEqualAtomOrder(view1, view2) - + if __name__ == "__main__": unittest.main()