diff --git a/modules/mol/alg/pymod/ligand_scoring.py b/modules/mol/alg/pymod/ligand_scoring.py index 187facafc6ebda39b161475f70b54602df808428..879a75e4c5643b1fab36498ec4d87a13ae96481b 100644 --- a/modules/mol/alg/pymod/ligand_scoring.py +++ b/modules/mol/alg/pymod/ligand_scoring.py @@ -169,23 +169,25 @@ class LigandScorer: Return the new residue handle.""" nonlocal next_chain_num, new_editor + # Does a residue with the same name already exist? + already_exists = new_entity.FindResidue(handle.chain.name, + handle.number).IsValid() + if already_exists: + msg = "A residue number %s already exists in chain %s" %( + handle.number, handle.chain.name) + raise RuntimeError(msg) + # Instanciate the editor if new_editor is None: new_editor = new_entity.EditXCS() - # Add a new chain - new_chain = None - while new_chain is None: - try: - new_chain = new_editor.InsertChain(str(next_chain_num)) - next_chain_num += 1 - break - except Exception: - next_chain_num += 1 - # Add the residue with residue number 1 + # Get or create the chain + new_chain = new_entity.FindChain(handle.chain.name) + if not new_chain.IsValid(): + new_chain = new_editor.InsertChain(handle.chain.name) + # Add the residue with its original residue number new_res = new_editor.AppendResidue(new_chain, handle, deep=True) new_res.SetIsLigand(True) - new_editor.SetResidueNumber(new_res, mol.ResNum(1)) return new_res def _process_ligand_residue(res): diff --git a/modules/mol/alg/tests/test_ligand_scoring.py b/modules/mol/alg/tests/test_ligand_scoring.py index fa0abd8226977169eac3d7c89dd13037e2df3f86..ed8cbf98beedf34d5c4f5dac9d03fdf69bd5cff7 100644 --- a/modules/mol/alg/tests/test_ligand_scoring.py +++ b/modules/mol/alg/tests/test_ligand_scoring.py @@ -56,7 +56,6 @@ class TestLigandScoring(unittest.TestCase): assert len(sc.target.Select("rname=G3D").residues) == 2 assert len(sc.model.Select("rname=G3D").residues) == 1 - def test_init_sdf_ligands(self): """Test that we can instantiate the scorer with ligands from separate SDF files. @@ -93,6 +92,29 @@ class TestLigandScoring(unittest.TestCase): assert len(sc.target_ligands) == 7 assert len(sc.model_ligands) == 1 + def test_init_reject_duplicate_ligands(self): + """Test that we reject input if multiple ligands with the same chain + name/residue number are given. + """ + mdl = io.LoadPDB(os.path.join('testfiles', "P84080_model_02_nolig.pdb")) + mdl_ligs = [io.LoadEntity(os.path.join('testfiles', "P84080_model_02_ligand_0.sdf"))] + trg = io.LoadPDB(os.path.join('testfiles', "1r8q_protein.pdb.gz")) + trg_ligs = [io.LoadEntity(os.path.join('testfiles', "1r8q_ligand_%d.sdf" % i)) for i in range(7)] + + # Reject identical model ligands + with self.assertRaises(RuntimeError): + sc = LigandScorer(mdl, trg, [mdl_ligs[0], mdl_ligs[0]], trg_ligs) + + # Reject identical target ligands + lig0 = trg_ligs[0] + lig1 = trg_ligs[1] + ed1 = lig1.EditXCS() + ed1.RenameChain(lig1.chains[0], lig0.chains[0].name) + ed1.SetResidueNumber(lig1.residues[0], lig0.residues[0].number) + with self.assertRaises(RuntimeError): + sc = LigandScorer(mdl, trg, mdl_ligs, [lig0, lig1]) + + if __name__ == "__main__": from ost import testutils