diff --git a/actions/ost-compare-structures-new b/actions/ost-compare-structures-new index adb998504e42cfad385f7d36ec5fefb898216bd9..f4e562d5dc58ca2ce44b1a2202d14d61e2a11368 100644 --- a/actions/ost-compare-structures-new +++ b/actions/ost-compare-structures-new @@ -168,10 +168,11 @@ def _ParseArgs(): help=("Compute per-residue lDDT scores with default parameterization " "and store as key \"local_lddt\". Score for model residue with " "number 42 in chain X can be extracted with: " - "data[\"local_lddt\"][\"X\"][\"42\"]. Stereochemical irregularities " - "affecting lDDT are reported as keys \"model_clashes\", " - "\"model_bad_bonds\", \"model_bad_angles\" and the respective " - "reference counterparts.")) + "data[\"local_lddt\"][\"X\"][\"42\"]. If there is an insertion " + "code, lets say A, the last key becomes \"42A\" Stereochemical " + "irregularities affecting lDDT are reported as keys " + "\"model_clashes\", \"model_bad_bonds\", \"model_bad_angles\" " + "and the respective reference counterparts.")) parser.add_argument( "--cad-score", @@ -269,7 +270,8 @@ def _ParseArgs(): "the full patches are represented by the reference are set to " "None. Model interface residues are available as key " "\"model_interface_residues\", reference interface residues as " - "key \"reference_interface_residues\". The respective scores are " + "key \"reference_interface_residues\". Residues are represented " + "as string in form <num><inscode>. The respective scores are " "available as keys \"patch_qs\" and \"patch_dockq\"")) return parser.parse_args() @@ -330,6 +332,26 @@ def _GetInconsistentResidues(alns): lst = [f"{x[0].GetQualifiedName()}-{x[1].GetQualifiedName()}" for x in lst] return lst +def _LocalScoresToJSONDict(score_dict): + """ Score for model residue with number rnum in chain X can be extracted + with: data["local_cad_score"]["X"][rnum]. Convert ResNum object to str for + JSON serialization + """ + json_dict = dict() + for ch, ch_scores in score_dict.items(): + json_dict[ch] = {str(rnum): s for rnum, s in ch_scores.items()} + return json_dict + +def _InterfaceResiduesToJSONDict(interface_dict): + """ Interface residues are stored as + data["model_interface_residues"]["A"][rnum1, rnum2,...]. Convert ResNum + object to str for JSON serialization. + """ + json_dict = dict() + for ch, ch_nums in interface_dict.items(): + json_dict[ch] = [str(rnum) for rnum in ch_nums] + return json_dict + def _Process(model, reference, args): @@ -350,7 +372,7 @@ def _Process(model, reference, args): out["lddt"] = scorer.lddt if args.local_lddt: - out["local_lddt"] = scorer.local_lddt + out["local_lddt"] = _LocalScoresToJSONDict(scorer.local_lddt) if args.lddt or args.local_lddt: out["model_clashes"] = [x.ToJSON() for x in scorer.model_clashes] @@ -364,7 +386,7 @@ def _Process(model, reference, args): out["cad_score"] = scorer.cad_score if args.local_cad_score: - out["local_cad_score"] = scorer.local_cad_score + out["local_cad_score"] = _LocalScoresToJSONDict(scorer.local_cad_score) if args.qs_score: out["qs_global"] = scorer.qs_global @@ -394,8 +416,10 @@ def _Process(model, reference, args): out["dockq_wave_full"] = scorer.dockq_wave_full if args.patch_scores: - out["model_interface_residues"] = scorer.model_interface_residues - out["reference_interface_residues"] = scorer.target_interface_residues + out["model_interface_residues"] = \ + _InterfaceResiduesToJSONDict(scorer.model_interface_residues) + out["reference_interface_residues"] = \ + _InterfaceResiduesToJSONDict(scorer.target_interface_residues) out["patch_qs"] = scorer.patch_qs out["patch_dockq"] = scorer.patch_dockq diff --git a/modules/mol/alg/pymod/scoring.py b/modules/mol/alg/pymod/scoring.py index 2b8ecb3bcabbc3af8ddb41ed2e12a4c386ca348a..73d42464ffc54395aee3e77fb43abb007a927a10 100644 --- a/modules/mol/alg/pymod/scoring.py +++ b/modules/mol/alg/pymod/scoring.py @@ -974,14 +974,14 @@ class Scorer: local_lddt[cname] = dict() if r.HasProp("lddt"): score = round(r.GetFloatProp("lddt"), 3) - local_lddt[cname][r.GetNumber().GetNum()] = score + local_lddt[cname][r.GetNumber()] = score else: # rsc => residue stereo checked... mdl_res = self.stereochecked_model.FindResidue(cname, r.GetNumber()) if mdl_res.IsValid(): # not covered by trg or skipped in chain mapping procedure # the latter happens if its part of a super short chain - local_lddt[cname][r.GetNumber().GetNum()] = None + local_lddt[cname][r.GetNumber()] = None else: # opt 1: removed by stereochecks => assign 0.0 # opt 2: removed by stereochecks AND not covered by ref @@ -997,9 +997,9 @@ class Scorer: trg_r = col.GetResidue(0) break if trg_r is None: - local_lddt[cname][r.GetNumber().GetNum()] = None + local_lddt[cname][r.GetNumber()] = None else: - local_lddt[cname][r.GetNumber().GetNum()] = 0.0 + local_lddt[cname][r.GetNumber()] = 0.0 self._lddt = lddt_score self._local_lddt = local_lddt @@ -1149,9 +1149,9 @@ class Scorer: local_cad[cname] = dict() if r.HasProp("localcad"): score = round(r.GetFloatProp("localcad"), 3) - local_cad[cname][r.GetNumber().GetNum()] = score + local_cad[cname][r.GetNumber()] = score else: - local_cad[cname][r.GetNumber().GetNum()] = None + local_cad[cname][r.GetNumber()] = None self._cad_score = cad_result.globalAA self._local_cad_score = local_cad @@ -1187,7 +1187,7 @@ class Scorer: for ch in ent.chains: cname = ch.GetName() sel = repr_ent.Select(f"(cname={cname} and 8 <> [cname!={cname}])") - result[cname] = [r.GetNumber().GetNum() for r in sel.residues] + result[cname] = [r.GetNumber() for r in sel.residues] return result def _do_stereochecks(self): @@ -1229,7 +1229,7 @@ class Scorer: :param mdl_ch: Name of chain in *self.model* of residue of interest :type mdl_ch: :class:`str` :param mdl_rnum: Residue number of residue of interest - :type mdl_rnum: :class:`int` + :type mdl_rnum: :class:`ost.mol.ResNum` :returns: Tuple with 5 elements: 1) :class:`bool` flag whether all residues in *mdl* patches are covered in *trg* 2) mtl_patch_one 3) mdl_patch_two 4) trg_patch_one 5) trg_patch_two @@ -1238,7 +1238,7 @@ class Scorer: repr_mdl = self._get_repr_view(self.model.Select("peptide=true")) # get position for specified residue - r = self.model.FindResidue(mdl_ch, mol.ResNum(mdl_rnum)) + r = self.model.FindResidue(mdl_ch, mdl_rnum) if not r.IsValid(): raise RuntimeError(f"Cannot find residue {mdl_rnum} in chain {mdl_ch}") if r.GetName() == "GLY": @@ -1332,7 +1332,7 @@ class Scorer: scores = list() for rnum in rnums: score = None - r = self.model.FindResidue(cname, mol.ResNum(rnum)) + r = self.model.FindResidue(cname, rnum) if r.IsValid() and r.GetChemType() == mol.ChemType.AMINOACIDS: full_trg_coverage, mdl_patch_one, mdl_patch_two, \ trg_patch_one, trg_patch_two = \ @@ -1349,7 +1349,7 @@ class Scorer: scores = list() for rnum in rnums: score = None - r = self.model.FindResidue(cname, mol.ResNum(rnum)) + r = self.model.FindResidue(cname, rnum) if r.IsValid() and r.GetChemType() == mol.ChemType.AMINOACIDS: full_trg_coverage, mdl_patch_one, mdl_patch_two, \ trg_patch_one, trg_patch_two = \