From 1cde4be114e93701597aae1f216a31e603709255 Mon Sep 17 00:00:00 2001 From: Gabriel Studer <gabriel.studer@unibas.ch> Date: Tue, 19 Apr 2022 14:36:48 +0200 Subject: [PATCH] lDDT: make matching residue names in model/target optional (on by default) --- modules/mol/alg/pymod/lddt.py | 9 ++++++--- modules/mol/alg/tests/test_lddt.py | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/modules/mol/alg/pymod/lddt.py b/modules/mol/alg/pymod/lddt.py index 7fba7a74c..2d7b675dd 100644 --- a/modules/mol/alg/pymod/lddt.py +++ b/modules/mol/alg/pymod/lddt.py @@ -307,7 +307,7 @@ class lDDTScorer: local_lddt_prop=None, local_contact_prop=None, chain_mapping=None, no_interchain=False, penalize_extra_chains=False, residue_mapping=None, - return_dist_test=False): + return_dist_test=False, check_resnames=True): """Computes lDDT of *model* - globally and per-residue :param model: Model to be scored @@ -373,7 +373,10 @@ class lDDTScorer: Fifth: numpy matrix of shape (len(scored_residues), len(thresholds)) specifying how many for each threshold are - conserved. + conserved. + :param check_resnames: On by default. Enforces residue name matches + between mapped model and target residues. + :type check_resnames: :class:`bool` :returns: global and per-residue lDDT scores as a tuple - first element is global lDDT score and second element a list of per-residue scores with length len(*model*.residues) @@ -437,7 +440,7 @@ class lDDTScorer: if res_mapper_key not in self.res_mapper: continue r_idx = self.res_mapper[res_mapper_key] - if r.name != self.compound_names[r_idx]: + if check_resnames and r.name != self.compound_names[r_idx]: raise RuntimeError( f"Residue name mismatch for {r}, " f" expect {self.compound_names[r_idx]}" diff --git a/modules/mol/alg/tests/test_lddt.py b/modules/mol/alg/tests/test_lddt.py index 0a0e365b1..84c274ac7 100644 --- a/modules/mol/alg/tests/test_lddt.py +++ b/modules/mol/alg/tests/test_lddt.py @@ -172,6 +172,23 @@ class TestlDDT(unittest.TestCase): for a,b in zip(per_res_scores_one, per_res_scores_three): self.assertAlmostEqual(a, b, places=5) + def test_resname_match(self): + model = _LoadFile("7SGN_C_model.pdb") + target = _LoadFile("7SGN_C_target.pdb") + + # introduce name mismatch + ed = model.handle.EditXCS() + ed.RenameResidue(model.residues[42], "asdf") + + # do scoring and select aname=CA + scorer = lDDTScorer(target.Select("aname=CA"), + conop.GetDefaultLib()) + + with self.assertRaises(RuntimeError): + scorer.lDDT(model) + + scorer.lDDT(model, check_resnames=False) + if __name__ == "__main__": from ost import testutils if testutils.SetDefaultCompoundLib(): -- GitLab