6 from ost
import settings
17 from ost
import bindings
23 """Scorer specific for a reference/model pair
25 Finds best possible binding site representation of reference in model given
26 lDDT score. Uses :class:`ost.mol.alg.chain_mapping.ChainMapper` to deal with
29 :param reference: Reference structure
30 :type reference: :class:`ost.mol.EntityView`/:class:`ost.mol.EntityHandle`
31 :param model: Model structure
32 :type model: :class:`ost.mol.EntityView`/:class:`ost.mol.EntityHandle`
33 :param residue_number_alignment: Passed to ChainMapper constructor
34 :type residue_number_alignment: :class:`bool`
37 residue_number_alignment=
False):
39 resnum_alignments=residue_number_alignment)
40 self.
ref = self.chain_mapper.target
43 def ScoreBS(self, ligand, radius = 4.0, lddt_radius=10.0):
44 """Computes binding site lDDT score given *ligand*. Best possible
45 binding site representation is selected by lDDT but other scores such as
46 CA based RMSD and GDT are computed too and returned.
48 :param ligand: Defines the scored binding site, i.e. provides positions
49 to perform proximity search
50 :type ligand: r'((Residue)|(Chain)|(Entity))((View)|(Handle))'
51 :param radius: Reference residues with any atom position within *radius*
52 of *ligand* consitute the scored binding site
53 :type radius: :class:`float`
54 :param lddt_radius: Passed as *inclusion_radius* to
55 :class:`ost.mol.alg.lddt.lDDTScorer`
56 :type lddt_radius: :class:`float`
57 :returns: Object of type :class:`ost.mol.alg.chain_mapping.ReprResult`
58 containing all atom lDDT score and mapping information.
59 None if no representation could be found.
63 ref_residues_hashes = set()
64 for ligand_at
in ligand.atoms:
65 close_atoms = self.ref.FindWithin(ligand_at.GetPos(), radius)
66 for close_at
in close_atoms:
67 ref_res = close_at.GetResidue()
68 h = ref_res.handle.GetHashCode()
69 if h
not in ref_residues_hashes:
70 ref_residues_hashes.add(h)
75 ref_bs = self.ref.CreateEmptyView()
76 for ch
in self.ref.chains:
78 if r.handle.GetHashCode()
in ref_residues_hashes:
79 ref_bs.AddResidue(r, mol.ViewAddFlag.INCLUDE_ALL)
82 bs_repr = self.chain_mapper.GetRepr(ref_bs, self.
mdl,
83 inclusion_radius = lddt_radius)
91 """ Helper class to access the various scores available from ost.mol.alg
93 Deals with structure cleanup, chain mapping, interface identification etc.
94 Intermediate results are available as attributes.
96 :param model: Model structure - a deep copy is available as :attr:`model`.
97 Additionally, :func:`ost.mol.alg.Molck` using *molck_settings*
99 :type model: :class:`ost.mol.EntityHandle`/:class:`ost.mol.EntityView`
100 :param target: Target structure - a deep copy is available as :attr:`target`.
101 Additionally, :func:`ost.mol.alg.Molck` using *molck_settings*
103 :type target: :class:`ost.mol.EntityHandle`/:class:`ost.mol.EntityView`
104 :param resnum_alignments: Whether alignments between chemically equivalent
105 chains in *model* and *target* can be computed
106 based on residue numbers. This can be assumed in
107 benchmarking setups such as CAMEO/CASP.
108 :type resnum_alignments: :class:`bool`
109 :param molck_settings: Settings used for Molck on *model* and *target*, if
110 set to None, a default object is constructed by
111 setting everything except rm_zero_occ_atoms and
113 :class:`ost.mol.alg.MolckSettings` constructor.
114 :type molck_settings: :class:`ost.mol.alg.MolckSettings`
115 :param cad_score_exec: Explicit path to voronota-cadscore executable from
116 voronota installation from
117 https://github.com/kliment-olechnovic/voronota. If
118 not given, voronota-cadscore must be in PATH if any
119 of the CAD score related attributes is requested.
120 :type cad_score_exec: :class:`str`
121 :param custom_mapping: Provide custom chain mapping between *model* and
122 *target*. Dictionary with target chain names as key
123 and model chain names as value.
124 :type custom_mapping: :class:`dict`
125 :param usalign_exec: Explicit path to USalign executable used to compute
126 TM-score. If not given, TM-score will be computed
127 with OpenStructure internal copy of USalign code.
128 :type usalign_exec: :class:`str`
129 :param lddt_no_stereochecks: Whether to compute lDDT without stereochemistry
131 :type lddt_no_stereochecks: :class:`bool`
132 :param n_max_naive: Parameter for chain mapping. If the number of possible
133 mappings is <= *n_max_naive*, the full
134 mapping solution space is enumerated to find the
135 the optimum. A heuristic is used otherwise. The default
136 of 40320 corresponds to an octamer (8! = 40320).
137 A structure with stoichiometry A6B2 would be
139 :type n_max_naive: :class:`int`
140 :param oum: Override USalign Mapping. Inject mapping of :class:`Scorer`
141 object into USalign to compute TM-score. Experimental feature
143 :type oum: :class:`bool`
145 def __init__(self, model, target, resnum_alignments=False,
146 molck_settings =
None, cad_score_exec =
None,
147 custom_mapping=
None, usalign_exec =
None,
148 lddt_no_stereochecks=
False, n_max_naive=40320,
157 self.
_model = self._model_orig.Copy()
162 self.
_target = self._target_orig.Copy()
164 if molck_settings
is None:
169 rm_zero_occ_atoms=
False,
173 Molck(self.
_model, conop.GetDefaultLib(), molck_settings)
174 Molck(self.
_target, conop.GetDefaultLib(), molck_settings)
175 self.
_model = self._model.Select(
"peptide=True or nucleotide=True")
176 self.
_target = self._target.Select(
"peptide=True or nucleotide=True")
179 for ch
in self._model.chains:
180 if ch.GetName().strip() ==
"":
181 raise RuntimeError(
"Model chains must have valid chain names")
184 for ch
in self._target.chains:
185 if ch.GetName().strip() ==
"":
186 raise RuntimeError(
"Target chains must have valid chain names")
188 if resnum_alignments:
192 for ch
in self._model.chains:
193 ins_codes = [r.GetNumber().GetInsCode()
for r
in ch.residues]
194 if len(set(ins_codes)) != 1
or ins_codes[0] !=
'\0':
195 raise RuntimeError(
"Residue numbers in each model chain "
196 "must not contain insertion codes if "
197 "resnum_alignments are enabled")
198 nums = [r.GetNumber().GetNum()
for r
in ch.residues]
199 if not all(i < j
for i, j
in zip(nums, nums[1:])):
200 raise RuntimeError(
"Residue numbers in each model chain "
201 "must be strictly increasing if "
202 "resnum_alignments are enabled")
204 for ch
in self._target.chains:
205 ins_codes = [r.GetNumber().GetInsCode()
for r
in ch.residues]
206 if len(set(ins_codes)) != 1
or ins_codes[0] !=
'\0':
207 raise RuntimeError(
"Residue numbers in each target chain "
208 "must not contain insertion codes if "
209 "resnum_alignments are enabled")
210 nums = [r.GetNumber().GetNum()
for r
in ch.residues]
211 if not all(i < j
for i, j
in zip(nums, nums[1:])):
212 raise RuntimeError(
"Residue numbers in each target chain "
213 "must be strictly increasing if "
214 "resnum_alignments are enabled")
216 if usalign_exec
is not None:
217 if not os.path.exists(usalign_exec):
218 raise RuntimeError(f
"USalign exec ({usalign_exec}) "
220 if not os.access(usalign_exec, os.X_OK):
221 raise RuntimeError(f
"USalign exec ({usalign_exec}) "
222 f
"is not executable")
317 if custom_mapping
is not None:
322 """ Model with Molck cleanup
324 :type: :class:`ost.mol.EntityHandle`
330 """ The original model passed at object construction
332 :type: :class:`ost.mol.EntityHandle`/:class:`ost.mol.EntityView`
338 """ Target with Molck cleanup
340 :type: :class:`ost.mol.EntityHandle`
346 """ The original target passed at object construction
348 :type: :class:`ost.mol.EntityHandle`/:class:`ost.mol.EntityView`
354 """ Alignments of :attr:`model`/:attr:`target` chains
356 Alignments for each pair of chains mapped in :attr:`mapping`.
357 First sequence is target sequence, second sequence the model sequence.
359 :type: :class:`list` of :class:`ost.seq.AlignmentHandle`
361 if self.
_aln is None:
367 """ Stereochecked equivalent of :attr:`aln`
369 The alignments may differ, as stereochecks potentially remove residues
371 :type: :class:`list` of :class:`ost.seq.AlignmentHandle`
379 """ Alignments of :attr:`model_orig`/:attr:`target_orig` chains
381 Selects for peptide and nucleotide residues before sequence
382 extraction. Includes residues that would be removed by molck in
383 structure preprocessing.
385 :type: :class:`list` of :class:`ost.seq.AlignmentHandle`
393 """ View of :attr:`~model` that has stereochemistry checks applied
395 First, a selection for peptide/nucleotide residues is performed,
396 secondly peptide sidechains with stereochemical irregularities are
397 removed (full residue if backbone atoms are involved). Irregularities
398 are clashes or bond lengths/angles more than 12 standard deviations
399 from expected values.
401 :type: :class:`ost.mol.EntityView`
409 """ Clashing model atoms
411 :type: :class:`list` of :class:`ost.mol.alg.stereochemistry.ClashInfo`
419 """ Model bonds with unexpected stereochemistry
421 :type: :class:`list` of
422 :class:`ost.mol.alg.stereochemistry.BondViolationInfo`
430 """ Model angles with unexpected stereochemistry
432 :type: :class:`list` of
433 :class:`ost.mol.alg.stereochemistry.AngleViolationInfo`
441 """ Same as :attr:`~stereochecked_model` for :attr:`~target`
443 :type: :class:`ost.mol.EntityView`
451 """ Clashing target atoms
453 :type: :class:`list` of :class:`ost.mol.alg.stereochemistry.ClashInfo`
461 """ Target bonds with unexpected stereochemistry
463 :type: :class:`list` of
464 :class:`ost.mol.alg.stereochemistry.BondViolationInfo`
472 """ Target angles with unexpected stereochemistry
474 :type: :class:`list` of
475 :class:`ost.mol.alg.stereochemistry.AngleViolationInfo`
483 """ Chain mapper object for given :attr:`target`
485 :type: :class:`ost.mol.alg.chain_mapping.ChainMapper`
495 """ Full chain mapping result for :attr:`target`/:attr:`model`
497 :type: :class:`ost.mol.alg.chain_mapping.MappingResult`
501 self.chain_mapper.GetMapping(self.
model,
507 """ Interface residues in :attr:`~model`
509 Thats all residues having a contact with at least one residue from
510 another chain (CB-CB distance <= 8A, CA in case of Glycine)
512 :type: :class:`dict` with chain names as key and and :class:`list`
513 with residue numbers of the respective interface residues.
522 """ Same as :attr:`~model_interface_residues` for :attr:`~target`
524 :type: :class:`dict` with chain names as key and and :class:`list`
525 with residue numbers of the respective interface residues.
534 """ lDDT scorer for :attr:`~stereochecked_target` (default parameters)
536 :type: :class:`ost.mol.alg.lddt.lDDTScorer`
547 """ Backbone only lDDT scorer for :attr:`~target`
549 No stereochecks applied for bb only lDDT which considers CA atoms
550 for peptides and C3' atoms for nucleotides.
552 :type: :class:`ost.mol.alg.lddt.lDDTScorer`
560 """ QS scorer constructed from :attr:`~mapping`
562 The scorer object is constructed with default parameters and relates to
563 :attr:`~model` and :attr:`~target` (no stereochecks).
565 :type: :class:`ost.mol.alg.qsscore.QSScorer`
580 """ Global lDDT score in range [0.0, 1.0]
582 Computed based on :attr:`~stereochecked_model`. In case of oligomers,
583 :attr:`~mapping` is used.
585 :type: :class:`float`
587 if self.
_lddt is None:
593 """ Per residue lDDT scores in range [0.0, 1.0]
595 Computed based on :attr:`~stereochecked_model` but scores for all
596 residues in :attr:`~model` are reported. If a residue has been removed
597 by stereochemistry checks, the respective score is set to 0.0. If a
598 residue is not covered by the target or is in a chain skipped by the
599 chain mapping procedure (happens for super short chains), the respective
600 score is set to None. In case of oligomers, :attr:`~mapping` is used.
610 """ Backbone only global lDDT score in range [0.0, 1.0]
612 Computed based on :attr:`~model` on backbone atoms only. This is CA for
613 peptides and C3' for nucleotides. No stereochecks are performed. In case
614 of oligomers, :attr:`~mapping` is used.
616 :type: :class:`float`
624 """ Backbone only per residue lDDT scores in range [0.0, 1.0]
626 Computed based on :attr:`~model` on backbone atoms only. This is CA for
627 peptides and C3' for nucleotides. No stereochecks are performed. If a
628 residue is not covered by the target or is in a chain skipped by the
629 chain mapping procedure (happens for super short chains), the respective
630 score is set to None. In case of oligomers, :attr:`~mapping` is used.
642 Computed based on :attr:`model` using :attr:`mapping`
644 :type: :class:`float`
652 """ Global QS-score - only computed on aligned residues
654 Computed based on :attr:`model` using :attr:`mapping`. The QS-score
655 computation only considers contacts between residues with a mapping
656 between target and model. As a result, the score won't be lowered in
657 case of additional chains/residues in any of the structures.
659 :type: :class:`float`
667 """ Interfaces in :attr:`~target` with non-zero contribution to
668 :attr:`~qs_global`/:attr:`~qs_best`
670 Chain names are lexicographically sorted.
672 :type: :class:`list` of :class:`tuple` with 2 elements each:
683 """ Interfaces in :attr:`~model` with non-zero contribution to
684 :attr:`~qs_global`/:attr:`~qs_best`
686 Chain names are lexicographically sorted.
688 :type: :class:`list` of :class:`tuple` with 2 elements each:
700 """ Interfaces in :attr:`~qs_target_interfaces` that can be mapped
703 Target chain names are lexicographically sorted.
705 :type: :class:`list` of :class:`tuple` with 4 elements each:
706 (trg_ch1, trg_ch2, mdl_ch1, mdl_ch2)
710 flat_mapping = self.mapping.GetFlatMapping()
712 if i[0]
in flat_mapping
and i[1]
in flat_mapping:
713 self._qs_interfaces.append((i[0], i[1],
720 """ QS-score for each interface in :attr:`qs_interfaces`
722 :type: :class:`list` of :class:`float`
730 """ QS-score for each interface in :attr:`qs_interfaces`
732 Only computed on aligned residues
734 :type: :class:`list` of :class:`float`
744 A contact is a pair or residues from distinct chains that have
745 a minimal heavy atom distance < 5A. Contacts are specified as
746 :class:`tuple` with two strings in format:
747 <cname>.<rnum>.<ins_code>
749 :type: :class:`list` of :class:`tuple`
765 """ Interfaces in :class:`target` which have at least one contact
767 Contact as defined in :attr:`~native_contacts`,
768 chain names are lexicographically sorted.
770 :type: :class:`list` of :class:`tuple` with 2 elements each
774 tmp = self.contact_scorer.cent1.interacting_chains
775 tmp = [(min(x[0],x[1]), max(x[0],x[1]))
for x
in tmp]
781 """ Interfaces in :class:`model` which have at least one contact
783 Contact as defined in :attr:`~native_contacts`,
784 chain names are lexicographically sorted.
786 :type: :class:`list` of :class:`tuple` with 2 elements each
790 tmp = self.contact_scorer.cent2.interacting_chains
791 tmp = [(min(x[0],x[1]), max(x[0],x[1]))
for x
in tmp]
797 """ Fraction of model contacts that are also present in target
799 :type: :class:`float`
807 """ Fraction of target contacts that are correctly reproduced in model
809 :type: :class:`float`
817 """ ICS (Interface Contact Similarity) score
819 Combination of :attr:`~ics_precision` and :attr:`~ics_recall`
822 :type: :class:`float`
824 if self.
_ics is None:
830 """ Per-interface ICS precision
832 :attr:`~ics_precision` for each interface in
833 :attr:`~contact_target_interfaces`
835 :type: :class:`list` of :class:`float`
844 """ Per-interface ICS recall
846 :attr:`~ics_recall` for each interface in
847 :attr:`~contact_target_interfaces`
849 :type: :class:`list` of :class:`float`
857 """ Per-interface ICS (Interface Contact Similarity) score
859 :attr:`~ics` for each interface in
860 :attr:`~contact_target_interfaces`
862 :type: :class:`float`
872 """ Fraction of model interface residues that are also interface
875 :type: :class:`float`
883 """ Fraction of target interface residues that are also interface
886 :type: :class:`float`
894 """ IPS (Interface Patch Similarity) score
896 Jaccard coefficient of interface residues in target and their mapped
897 counterparts in model
899 :type: :class:`float`
901 if self.
_ips is None:
907 """ Per-interface IPS precision
909 :attr:`~ips_precision` for each interface in
910 :attr:`~contact_target_interfaces`
912 :type: :class:`list` of :class:`float`
921 """ Per-interface IPS recall
923 :attr:`~ips_recall` for each interface in
924 :attr:`~contact_target_interfaces`
926 :type: :class:`list` of :class:`float`
934 """ Per-interface IPS (Interface Patch Similarity) score
936 :attr:`~ips` for each interface in
937 :attr:`~contact_target_interfaces`
939 :type: :class:`list` of :class:`float`
948 """ Interfaces in :attr:`target` that are relevant for DockQ
950 In principle a subset of :attr:`~contact_target_interfaces` that only
951 contains peptide sequences. Chain names are lexicographically sorted.
953 :type: :class:`list` of :class:`tuple` with 2 elements each:
958 pep_seqs = set([s.GetName()
for s
in self.chain_mapper.polypep_seqs])
960 if interface[0]
in pep_seqs
and interface[1]
in pep_seqs:
961 self._dockq_target_interfaces.append(interface)
966 """ Interfaces in :attr:`dockq_target_interfaces` that can be mapped
969 Target chain names are lexicographically sorted
971 :type: :class:`list` of :class:`tuple` with 4 elements each:
972 (trg_ch1, trg_ch2, mdl_ch1, mdl_ch2)
976 flat_mapping = self.mapping.GetFlatMapping()
978 if i[0]
in flat_mapping
and i[1]
in flat_mapping:
979 self._dockq_interfaces.append((i[0], i[1],
986 """ DockQ scores for interfaces in :attr:`~dockq_interfaces`
988 :class:`list` of :class:`float`
996 """ fnat scores for interfaces in :attr:`~dockq_interfaces`
998 fnat: Fraction of native contacts that are also present in model
1000 :class:`list` of :class:`float`
1002 if self.
_fnat is None:
1008 """ N native contacts for interfaces in :attr:`~dockq_interfaces`
1010 :class:`list` of :class:`int`
1012 if self.
_nnat is None:
1018 """ N model contacts for interfaces in :attr:`~dockq_interfaces`
1020 :class:`list` of :class:`int`
1022 if self.
_nmdl is None:
1028 """ fnonnat scores for interfaces in :attr:`~dockq_interfaces`
1030 fnat: Fraction of model contacts that are not present in target
1032 :class:`list` of :class:`float`
1040 """ irmsd scores for interfaces in :attr:`~dockq_interfaces`
1042 irmsd: RMSD of interface (RMSD computed on N, CA, C, O atoms) which
1043 consists of each residue that has at least one heavy atom within 10A of
1046 :class:`list` of :class:`float`
1054 """ lrmsd scores for interfaces in :attr:`~dockq_interfaces`
1056 lrmsd: The interfaces are superposed based on the receptor (rigid
1057 min RMSD superposition) and RMSD for the ligand is reported.
1058 Superposition and RMSD are based on N, CA, C and O positions,
1059 receptor is the chain contributing to the interface with more
1062 :class:`list` of :class:`float`
1070 """ Average of DockQ scores in :attr:`dockq_scores`
1072 In its original implementation, DockQ only operates on single
1073 interfaces. Thus the requirement to combine scores for higher order
1076 :type: :class:`float`
1084 """ Same as :attr:`dockq_ave`, weighted by native contacts
1086 :type: :class:`float`
1094 """ Same as :attr:`~dockq_ave` but penalizing for missing interfaces
1096 Interfaces that are not covered in model are added as 0.0
1097 in average computation.
1099 :type: :class:`float`
1107 """ Same as :attr:`~dockq_ave_full`, but weighted
1109 Interfaces that are not covered in model are added as 0.0 in
1110 average computations and the respective weights are derived from
1111 number of contacts in respective target interface.
1119 """ Mapped representative positions in target
1121 Thats CA positions for peptide residues and C3' positions for
1122 nucleotides. Has same length as :attr:`~mapped_model_pos` and mapping
1123 is based on :attr:`~mapping`.
1125 :type: :class:`ost.geom.Vec3List`
1133 """ Mapped representative positions in model
1135 Thats CA positions for peptide residues and C3' positions for
1136 nucleotides. Has same length as :attr:`~mapped_target_pos` and mapping
1137 is based on :attr:`~mapping`.
1139 :type: :class:`ost.geom.Vec3List`
1147 """ :attr:`~mapped_model_pos` with :attr:`~transform` applied
1149 :type: :class:`ost.geom.Vec3List`
1154 self._transformed_mapped_model_pos.ApplyTransform(self.
transform)
1159 """ Number of target residues which have no mapping to model
1169 """ Transform: :attr:`~mapped_model_pos` onto :attr:`~mapped_target_pos`
1171 Computed using Kabsch minimal rmsd algorithm
1173 :type: :class:`ost.geom.Mat4`
1186 """ GDT with thresholds: 8.0A, 4.0A, 2.0A and 1.0A
1188 Computed on :attr:`~transformed_mapped_model_pos` and
1189 :attr:`mapped_target_pos`
1191 :type: :class:`float`
1199 self.
_gdtts = float(n) / n_full
1206 """ GDT with thresholds: 4.0A, 2.0A, 1.0A and 0.5A
1208 Computed on :attr:`~transformed_mapped_model_pos` and
1209 :attr:`mapped_target_pos`
1211 :type: :class:`float`
1219 self.
_gdtha = float(n) / n_full
1228 Computed on :attr:`~transformed_mapped_model_pos` and
1229 :attr:`mapped_target_pos`
1231 :type: :class:`float`
1233 if self.
_rmsd is None:
1240 """ The global CAD atom-atom (AA) score
1242 Computed based on :attr:`~model`. In case of oligomers, :attr:`~mapping`
1245 :type: :class:`float`
1253 """ The per-residue CAD atom-atom (AA) scores
1255 Computed based on :attr:`~model`. In case of oligomers, :attr:`~mapping`
1258 :type: :class:`dict`
1266 """ Patch QS-scores for each residue in :attr:`model_interface_residues`
1268 Representative patches for each residue r in chain c are computed as
1271 * mdl_patch_one: All residues in c with CB (CA for GLY) positions within
1272 8A of r and within 12A of residues from any other chain.
1273 * mdl_patch_two: Closest residue x to r in any other chain gets
1274 identified. Patch is then constructed by selecting all residues from
1275 any other chain within 8A of x and within 12A from any residue in c.
1276 * trg_patch_one: Chain name and residue number based mapping from
1278 * trg_patch_two: Chain name and residue number based mapping from
1281 Results are stored in the same manner as
1282 :attr:`model_interface_residues`, with corresponding scores instead of
1283 residue numbers. Scores for residues which are not
1284 :class:`mol.ChemType.AMINOACIDS` are set to None. Additionally,
1285 interface patches are derived from :attr:`model`. If they contain
1286 residues which are not covered by :attr:`target`, the score is set to
1289 :type: :class:`dict` with chain names as key and and :class:`list`
1290 with scores of the respective interface residues.
1298 """ Same as :attr:`patch_qs` but for DockQ scores
1306 """ TM-score computed with USalign
1308 USalign executable can be specified with usalign_exec kwarg at Scorer
1309 construction, an OpenStructure internal copy of the USalign code is
1312 :type: :class:`float`
1320 """ Mapping computed with USalign
1322 Dictionary with target chain names as key and model chain names as
1323 values. No guarantee that all chains are mapped. USalign executable
1324 can be specified with usalign_exec kwarg at Scorer construction, an
1325 OpenStructure internal copy of the USalign code is used otherwise.
1327 :type: :class:`dict`
1333 def _aln_helper(self, target, model):
1338 for ch
in target.chains:
1339 cname = ch.GetName()
1340 s =
''.join([r.one_letter_code
for r
in ch.residues])
1341 s = seq.CreateSequence(ch.GetName(), s)
1342 s.AttachView(target.Select(f
"cname={cname}"))
1343 trg_seqs[ch.GetName()] = s
1345 for ch
in model.chains:
1346 cname = ch.GetName()
1347 s =
''.join([r.one_letter_code
for r
in ch.residues])
1348 s = seq.CreateSequence(cname, s)
1349 s.AttachView(model.Select(f
"cname={cname}"))
1350 mdl_seqs[ch.GetName()] = s
1353 trg_pep_chains = [s.GetName()
for s
in self.chain_mapper.polypep_seqs]
1354 trg_nuc_chains = [s.GetName()
for s
in self.chain_mapper.polynuc_seqs]
1355 trg_pep_chains = set(trg_pep_chains)
1356 trg_nuc_chains = set(trg_nuc_chains)
1357 for trg_ch, mdl_ch
in self.mapping.GetFlatMapping().items():
1358 if mdl_ch
in mdl_seqs
and trg_ch
in trg_seqs:
1359 if trg_ch
in trg_pep_chains:
1360 stype = mol.ChemType.AMINOACIDS
1361 elif trg_ch
in trg_nuc_chains:
1362 stype = mol.ChemType.NUCLEOTIDES
1364 raise RuntimeError(
"Chain name inconsistency... ask "
1366 alns.append(self.chain_mapper.Align(trg_seqs[trg_ch],
1369 alns[-1].AttachView(0, trg_seqs[trg_ch].GetAttachedView())
1370 alns[-1].AttachView(1, mdl_seqs[mdl_ch].GetAttachedView())
1373 def _compute_pepnuc_aln(self):
1374 query =
"peptide=true or nucleotide=true"
1375 pep_nuc_target = self.target_orig.Select(query)
1376 pep_nuc_model = self.model_orig.Select(query)
1379 def _compute_aln(self):
1382 def _compute_stereochecked_aln(self):
1386 def _compute_lddt(self):
1388 flat_mapping = self.mapping.GetFlatMapping(mdl_as_key=
True)
1391 stereochecked_alns = dict()
1393 mdl_seq = aln.GetSequence(1)
1394 stereochecked_alns[mdl_seq.name] = aln
1396 for aln
in self.
aln:
1397 mdl_seq = aln.GetSequence(1)
1398 alns[mdl_seq.name] = aln
1405 lddt_chain_mapping = dict()
1406 for mdl_ch, trg_ch
in flat_mapping.items():
1408 lddt_chain_mapping[mdl_ch] = trg_ch
1409 lddt_score = self.lddt_scorer.lDDT(self.
model,
1410 chain_mapping = lddt_chain_mapping,
1411 residue_mapping = alns,
1412 check_resnames=
False,
1413 local_lddt_prop=
"lddt")[0]
1415 for r
in self.model.residues:
1416 cname = r.GetChain().GetName()
1417 if cname
not in local_lddt:
1418 local_lddt[cname] = dict()
1419 if r.HasProp(
"lddt"):
1420 score = round(r.GetFloatProp(
"lddt"), 3)
1421 local_lddt[cname][r.GetNumber()] = score
1425 local_lddt[cname][r.GetNumber()] =
None
1428 lddt_chain_mapping = dict()
1429 for mdl_ch, trg_ch
in flat_mapping.items():
1430 if mdl_ch
in stereochecked_alns:
1431 lddt_chain_mapping[mdl_ch] = trg_ch
1433 chain_mapping = lddt_chain_mapping,
1434 residue_mapping = stereochecked_alns,
1435 check_resnames=
False,
1436 local_lddt_prop=
"lddt")[0]
1438 for r
in self.model.residues:
1439 cname = r.GetChain().GetName()
1440 if cname
not in local_lddt:
1441 local_lddt[cname] = dict()
1442 if r.HasProp(
"lddt"):
1443 score = round(r.GetFloatProp(
"lddt"), 3)
1444 local_lddt[cname][r.GetNumber()] = score
1447 mdl_res = self.stereochecked_model.FindResidue(cname, r.GetNumber())
1448 if mdl_res.IsValid():
1451 local_lddt[cname][r.GetNumber()] =
None
1458 if cname
in flat_mapping:
1459 for col
in alns[cname]:
1460 if col[0] !=
'-' and col[1] !=
'-':
1461 if col.GetResidue(1).number == r.number:
1462 trg_r = col.GetResidue(0)
1465 local_lddt[cname][r.GetNumber()] =
None
1467 local_lddt[cname][r.GetNumber()] = 0.0
1469 self.
_lddt = lddt_score
1472 def _compute_bb_lddt(self):
1476 for aln
in self.
aln:
1477 mdl_seq = aln.GetSequence(1)
1478 alns[mdl_seq.name] = aln
1481 flat_mapping = self.mapping.GetFlatMapping(mdl_as_key=
True)
1482 lddt_chain_mapping = dict()
1483 for mdl_ch, trg_ch
in flat_mapping.items():
1485 lddt_chain_mapping[mdl_ch] = trg_ch
1487 lddt_score = self.bb_lddt_scorer.lDDT(self.
model,
1488 chain_mapping = lddt_chain_mapping,
1489 residue_mapping = alns,
1490 check_resnames=
False,
1491 local_lddt_prop=
"bb_lddt")[0]
1493 for r
in self.model.residues:
1494 cname = r.GetChain().GetName()
1495 if cname
not in local_lddt:
1496 local_lddt[cname] = dict()
1497 if r.HasProp(
"bb_lddt"):
1498 score = round(r.GetFloatProp(
"bb_lddt"), 3)
1499 local_lddt[cname][r.GetNumber()] = score
1503 local_lddt[cname][r.GetNumber()] =
None
1508 def _compute_qs(self):
1509 qs_score_result = self.qs_scorer.Score(self.mapping.mapping)
1511 self.
_qs_best = qs_score_result.QS_best
1513 def _compute_per_interface_qs_scores(self):
1518 trg_ch1 = interface[0]
1519 trg_ch2 = interface[1]
1520 mdl_ch1 = interface[2]
1521 mdl_ch2 = interface[3]
1522 qs_res = self.qs_scorer.ScoreInterface(trg_ch1, trg_ch2,
1524 self._per_interface_qs_best.append(qs_res.QS_best)
1525 self._per_interface_qs_global.append(qs_res.QS_global)
1527 def _compute_ics_scores(self):
1528 contact_scorer_res = self.contact_scorer.ScoreICS(self.mapping.mapping)
1531 self.
_ics = contact_scorer_res.ics
1535 flat_mapping = self.mapping.GetFlatMapping()
1537 trg_ch1 = trg_int[0]
1538 trg_ch2 = trg_int[1]
1539 if trg_ch1
in flat_mapping
and trg_ch2
in flat_mapping:
1540 mdl_ch1 = flat_mapping[trg_ch1]
1541 mdl_ch2 = flat_mapping[trg_ch2]
1542 res = self.contact_scorer.ScoreICSInterface(trg_ch1, trg_ch2,
1544 self._per_interface_ics_precision.append(res.precision)
1545 self._per_interface_ics_recall.append(res.recall)
1546 self._per_interface_ics.append(res.ics)
1548 self._per_interface_ics_precision.append(
None)
1549 self._per_interface_ics_recall.append(
None)
1550 self._per_interface_ics.append(
None)
1552 def _compute_ips_scores(self):
1553 contact_scorer_res = self.contact_scorer.ScoreIPS(self.mapping.mapping)
1556 self.
_ips = contact_scorer_res.ips
1561 flat_mapping = self.mapping.GetFlatMapping()
1563 trg_ch1 = trg_int[0]
1564 trg_ch2 = trg_int[1]
1565 if trg_ch1
in flat_mapping
and trg_ch2
in flat_mapping:
1566 mdl_ch1 = flat_mapping[trg_ch1]
1567 mdl_ch2 = flat_mapping[trg_ch2]
1568 res = self.contact_scorer.ScoreIPSInterface(trg_ch1, trg_ch2,
1570 self._per_interface_ips_precision.append(res.precision)
1571 self._per_interface_ips_recall.append(res.recall)
1572 self._per_interface_ips.append(res.ips)
1574 self._per_interface_ips_precision.append(
None)
1575 self._per_interface_ips_recall.append(
None)
1576 self._per_interface_ips.append(
None)
1578 def _compute_dockq_scores(self):
1589 for aln
in self.
aln:
1590 trg_s = aln.GetSequence(0)
1591 mdl_s = aln.GetSequence(1)
1592 dockq_alns[(trg_s.GetName(), mdl_s.GetName())] = aln
1595 trg_ch1 = interface[0]
1596 trg_ch2 = interface[1]
1597 mdl_ch1 = interface[2]
1598 mdl_ch2 = interface[3]
1599 aln1 = dockq_alns[(trg_ch1, mdl_ch1)]
1600 aln2 = dockq_alns[(trg_ch2, mdl_ch2)]
1601 res = dockq.DockQ(self.
model, self.
target, mdl_ch1, mdl_ch2,
1602 trg_ch1, trg_ch2, ch1_aln=aln1,
1604 self._fnat.append(res[
"fnat"])
1605 self._fnonnat.append(res[
"fnonnat"])
1606 self._irmsd.append(res[
"irmsd"])
1607 self._lrmsd.append(res[
"lrmsd"])
1608 self._dockq_scores.append(res[
"DockQ"])
1609 self._nnat.append(res[
"nnat"])
1610 self._nmdl.append(res[
"nmdl"])
1615 not_covered_counts = list()
1618 if interface
not in proc_trg_interfaces:
1622 trg_ch1 = interface[0]
1623 trg_ch2 = interface[1]
1625 trg_ch1, trg_ch2, trg_ch1, trg_ch2)
1626 not_covered_counts.apend(res[
"nnat"])
1633 weights = np.array([self.
_nnat])
1638 self.
_dockq_wave = np.sum(np.multiply(weights/np.sum(weights), scores))
1639 scores = np.append(scores, [0.0]*len(not_covered_counts))
1640 weights = np.append(weights, not_covered_counts)
1648 def _extract_mapped_pos(self):
1652 processed_trg_chains = set()
1653 for trg_ch, mdl_ch
in self.mapping.GetFlatMapping().items():
1654 processed_trg_chains.add(trg_ch)
1655 aln = self.mapping.alns[(trg_ch, mdl_ch)]
1657 if col[0] !=
'-' and col[1] !=
'-':
1658 trg_res = col.GetResidue(0)
1659 mdl_res = col.GetResidue(1)
1660 trg_at = trg_res.FindAtom(
"CA")
1661 mdl_at = mdl_res.FindAtom(
"CA")
1662 if not trg_at.IsValid():
1663 trg_at = trg_res.FindAtom(
"C3'")
1664 if not mdl_at.IsValid():
1665 mdl_at = mdl_res.FindAtom(
"C3'")
1666 self._mapped_target_pos.append(trg_at.GetPos())
1667 self._mapped_model_pos.append(mdl_at.GetPos())
1671 for ch
in self.mapping.target.chains:
1672 if ch.GetName()
not in processed_trg_chains:
1675 def _compute_cad_score(self):
1677 raise RuntimeError(
"CAD score computations rely on residue numbers "
1678 "that are consistent between target and model "
1679 "chains, i.e. only work if resnum_alignments "
1680 "is True at Scorer construction.")
1683 settings.Locate(
"voronota-cadscore",
1685 except Exception
as e:
1686 raise RuntimeError(
"voronota-cadscore must be in PATH for CAD "
1687 "score scoring")
from e
1688 cad_bin_dir = os.path.dirname(cad_score_exec)
1689 m = self.mapping.GetFlatMapping(mdl_as_key=
True)
1690 cad_result = cadscore.CADScore(self.
model, self.
target,
1694 cad_bin_path=cad_bin_dir,
1698 for r
in self.model.residues:
1699 cname = r.GetChain().GetName()
1700 if cname
not in local_cad:
1701 local_cad[cname] = dict()
1702 if r.HasProp(
"localcad"):
1703 score = round(r.GetFloatProp(
"localcad"), 3)
1704 local_cad[cname][r.GetNumber()] = score
1706 local_cad[cname][r.GetNumber()] =
None
1711 def _get_repr_view(self, ent):
1712 """ Returns view with representative peptide atoms => CB, CA for GLY
1714 Ensures that each residue has exactly one atom with assertions
1716 :param ent: Entity for which you want the representative view
1717 :param ent: :class:`ost.mol.EntityHandle`/:class:`ost.mol.EntityView`
1718 :returns: :class:`ost.mol.EntityView` derived from ent
1720 repr_ent = ent.Select(
"(aname=\"CB\" or (rname=\"GLY\" and aname=\"CA\"))")
1721 for r
in repr_ent.residues:
1722 assert(len(r.atoms) == 1)
1725 def _get_interface_residues(self, ent):
1726 """ Get interface residues
1728 Thats all residues having a contact with at least one residue from another
1729 chain (CB-CB distance <= 8A, CA in case of Glycine)
1731 :param ent: Model for which to extract interface residues
1732 :type ent: :class:`ost.mol.EntityView`
1733 :returns: :class:`dict` with chain names as key and and :class:`list`
1734 with residue numbers of the respective interface residues.
1738 result = {ch.GetName(): list()
for ch
in ent.chains}
1739 for ch
in ent.chains:
1740 cname = ch.GetName()
1741 sel = repr_ent.Select(f
"(cname={cname} and 8 <> [cname!={cname}])")
1742 result[cname] = [r.GetNumber()
for r
in sel.residues]
1745 def _do_stereochecks(self):
1746 """ Perform stereochemistry checks on model and target
1748 data = stereochemistry.GetDefaultStereoData()
1749 l_data = stereochemistry.GetDefaultStereoLinkData()
1751 a, b, c, d = stereochemistry.StereoCheck(self.
model, stereo_data = data,
1752 stereo_link_data = l_data)
1758 a, b, c, d = stereochemistry.StereoCheck(self.
target, stereo_data = data,
1759 stereo_link_data = l_data)
1766 def _get_interface_patches(self, mdl_ch, mdl_rnum):
1767 """ Select interface patches representative for specified residue
1769 The patches for specified residue r in chain c are selected as follows:
1771 * mdl_patch_one: All residues in c with CB (CA for GLY) positions within 8A
1772 of r and within 12A of residues from any other chain.
1773 * mdl_patch_two: Closest residue x to r in any other chain gets identified.
1774 Patch is then constructed by selecting all residues from any other chain
1775 within 8A of x and within 12A from any residue in c.
1776 * trg_patch_one: Chain name and residue number based mapping from
1778 * trg_patch_two: Chain name and residue number based mapping from
1781 :param mdl_ch: Name of chain in *self.model* of residue of interest
1782 :type mdl_ch: :class:`str`
1783 :param mdl_rnum: Residue number of residue of interest
1784 :type mdl_rnum: :class:`ost.mol.ResNum`
1785 :returns: Tuple with 5 elements: 1) :class:`bool` flag whether all residues
1786 in *mdl* patches are covered in *trg* 2) mtl_patch_one
1787 3) mdl_patch_two 4) trg_patch_one 5) trg_patch_two
1790 repr_mdl = self.
_get_repr_view(self.model.Select(
"peptide=true"))
1793 r = self.model.FindResidue(mdl_ch, mdl_rnum)
1795 raise RuntimeError(f
"Cannot find residue {mdl_rnum} in chain {mdl_ch}")
1796 if r.GetName() ==
"GLY":
1797 at = r.FindAtom(
"CA")
1799 at = r.FindAtom(
"CB")
1800 if not at.IsValid():
1801 raise RuntimeError(
"Cannot find interface views for res without CB/CA")
1808 q1 = f
"(cname={mdl_ch} and 8 <> {{{r_pos[0]},{r_pos[1]},{r_pos[2]}}})"
1810 q2 = f
"(12 <> [cname!={mdl_ch}])"
1811 mdl_patch_one = self.model.CreateEmptyView()
1812 sel = repr_mdl.Select(
" and ".join([q1, q2]))
1813 for r
in sel.residues:
1814 mdl_r = self.model.FindResidue(r.GetChain().GetName(), r.GetNumber())
1815 mdl_patch_one.AddResidue(mdl_r, mol.ViewAddFlag.INCLUDE_ALL)
1821 sel = repr_mdl.Select(f
"(cname!={mdl_ch})")
1822 close_stuff = sel.FindWithin(r_pos, 8)
1825 for close_at
in close_stuff:
1828 min_pos = close_at.GetPos()
1832 q1 = f
"(cname!={mdl_ch} and 8 <> {{{min_pos[0]},{min_pos[1]},{min_pos[2]}}})"
1834 q2 = f
"(12 <> [cname={mdl_ch}])"
1835 mdl_patch_two = self.model.CreateEmptyView()
1836 sel = repr_mdl.Select(
" and ".join([q1, q2]))
1837 for r
in sel.residues:
1838 mdl_r = self.model.FindResidue(r.GetChain().GetName(), r.GetNumber())
1839 mdl_patch_two.AddResidue(mdl_r, mol.ViewAddFlag.INCLUDE_ALL)
1842 flat_mapping = self.mapping.GetFlatMapping(mdl_as_key=
True)
1843 full_trg_coverage =
True
1844 trg_patch_one = self.target.CreateEmptyView()
1845 for r
in mdl_patch_one.residues:
1847 mdl_cname = r.GetChain().GetName()
1848 if mdl_cname
in flat_mapping:
1849 aln = self.mapping.alns[(flat_mapping[mdl_cname], mdl_cname)]
1851 if col[0] !=
'-' and col[1] !=
'-':
1852 if col.GetResidue(1).GetNumber() == r.GetNumber():
1853 trg_r = col.GetResidue(0)
1855 if trg_r
is not None:
1856 trg_patch_one.AddResidue(trg_r.handle,
1857 mol.ViewAddFlag.INCLUDE_ALL)
1859 full_trg_coverage =
False
1861 trg_patch_two = self.target.CreateEmptyView()
1862 for r
in mdl_patch_two.residues:
1864 mdl_cname = r.GetChain().GetName()
1865 if mdl_cname
in flat_mapping:
1866 aln = self.mapping.alns[(flat_mapping[mdl_cname], mdl_cname)]
1868 if col[0] !=
'-' and col[1] !=
'-':
1869 if col.GetResidue(1).GetNumber() == r.GetNumber():
1870 trg_r = col.GetResidue(0)
1872 if trg_r
is not None:
1873 trg_patch_two.AddResidue(trg_r.handle,
1874 mol.ViewAddFlag.INCLUDE_ALL)
1876 full_trg_coverage =
False
1878 return (full_trg_coverage, mdl_patch_one, mdl_patch_two,
1879 trg_patch_one, trg_patch_two)
1881 def _compute_patchqs_scores(self):
1883 for cname, rnums
in self.model_interface_residues.items():
1887 r = self.model.FindResidue(cname, rnum)
1888 if r.IsValid()
and r.GetChemType() == mol.ChemType.AMINOACIDS:
1889 full_trg_coverage, mdl_patch_one, mdl_patch_two, \
1890 trg_patch_one, trg_patch_two = \
1892 if full_trg_coverage:
1893 score = self.
_patchqs(mdl_patch_one, mdl_patch_two,
1894 trg_patch_one, trg_patch_two)
1895 scores.append(score)
1898 def _compute_patchdockq_scores(self):
1900 for cname, rnums
in self.model_interface_residues.items():
1904 r = self.model.FindResidue(cname, rnum)
1905 if r.IsValid()
and r.GetChemType() == mol.ChemType.AMINOACIDS:
1906 full_trg_coverage, mdl_patch_one, mdl_patch_two, \
1907 trg_patch_one, trg_patch_two = \
1909 if full_trg_coverage:
1910 score = self.
_patchdockq(mdl_patch_one, mdl_patch_two,
1911 trg_patch_one, trg_patch_two)
1912 scores.append(score)
1915 def _patchqs(self, mdl_patch_one, mdl_patch_two, trg_patch_one, trg_patch_two):
1916 """ Score interface residue patches with QS-score
1918 In detail: Construct two entities with two chains each. First chain
1919 consists of residues from <x>_patch_one and second chain consists of
1920 <x>_patch_two. The returned score is the QS-score between the two
1923 :param mdl_patch_one: Interface patch representing scored residue
1924 :type mdl_patch_one: :class:`ost.mol.EntityView`
1925 :param mdl_patch_two: Interface patch representing scored residue
1926 :type mdl_patch_two: :class:`ost.mol.EntityView`
1927 :param trg_patch_one: Interface patch representing scored residue
1928 :type trg_patch_one: :class:`ost.mol.EntityView`
1929 :param trg_patch_two: Interface patch representing scored residue
1930 :type trg_patch_two: :class:`ost.mol.EntityView`
1931 :returns: PatchQS score
1936 alnA = seq.CreateAlignment()
1937 s =
''.join([r.one_letter_code
for r
in mdl_patch_one.residues])
1938 alnA.AddSequence(seq.CreateSequence(
"A", s))
1939 s =
''.join([r.one_letter_code
for r
in trg_patch_one.residues])
1940 alnA.AddSequence(seq.CreateSequence(
"A", s))
1942 alnB = seq.CreateAlignment()
1943 s =
''.join([r.one_letter_code
for r
in mdl_patch_two.residues])
1944 alnB.AddSequence(seq.CreateSequence(
"B", s))
1945 s =
''.join([r.one_letter_code
for r
in trg_patch_two.residues])
1946 alnB.AddSequence(seq.CreateSequence(
"B", s))
1947 alns = {(
"A",
"A"): alnA, (
"B",
"B"): alnB}
1949 scorer =
QSScorer(qs_ent_mdl, [[
"A"], [
"B"]], qs_ent_trg, alns)
1950 score_result = scorer.Score([[
"A"], [
"B"]])
1952 return score_result.QS_global
1954 def _patchdockq(self, mdl_patch_one, mdl_patch_two, trg_patch_one,
1956 """ Score interface residue patches with DockQ
1958 In detail: Construct two entities with two chains each. First chain
1959 consists of residues from <x>_patch_one and second chain consists of
1960 <x>_patch_two. The returned score is the QS-score between the two
1963 :param mdl_patch_one: Interface patch representing scored residue
1964 :type mdl_patch_one: :class:`ost.mol.EntityView`
1965 :param mdl_patch_two: Interface patch representing scored residue
1966 :type mdl_patch_two: :class:`ost.mol.EntityView`
1967 :param trg_patch_one: Interface patch representing scored residue
1968 :type trg_patch_one: :class:`ost.mol.EntityView`
1969 :param trg_patch_two: Interface patch representing scored residue
1970 :type trg_patch_two: :class:`ost.mol.EntityView`
1971 :returns: DockQ score
1975 dockq_result = dockq.DockQ(t, m,
"A",
"B",
"A",
"B")
1976 if dockq_result[
"nnat"] > 0:
1977 return dockq_result[
"DockQ"]
1980 def _qs_ent_from_patches(self, patch_one, patch_two):
1981 """ Constructs Entity with two chains named "A" and "B""
1983 Blindly adds all residues from *patch_one* to chain A and residues from
1984 patch_two to chain B.
1986 ent = mol.CreateEntity()
1988 added_ch = ed.InsertChain(
"A")
1989 for r
in patch_one.residues:
1990 added_r = ed.AppendResidue(added_ch, r.GetName())
1991 added_r.SetChemClass(str(r.GetChemClass()))
1993 ed.InsertAtom(added_r, a.handle)
1994 added_ch = ed.InsertChain(
"B")
1995 for r
in patch_two.residues:
1996 added_r = ed.AppendResidue(added_ch, r.GetName())
1997 added_r.SetChemClass(str(r.GetChemClass()))
1999 ed.InsertAtom(added_r, a.handle)
2002 def _set_custom_mapping(self, mapping):
2003 """ sets self._mapping with a full blown MappingResult object
2005 :param mapping: mapping with trg chains as key and mdl ch as values
2006 :type mapping: :class:`dict`
2010 chem_mapping, chem_group_alns, mdl = \
2011 chain_mapper.GetChemMapping(self.
model)
2016 if len(mapping) != len(set(mapping.keys())):
2017 raise RuntimeError(f
"Expect unique trg chain names in mapping. Got "
2018 f
"{mapping.keys()}")
2019 if len(mapping) != len(set(mapping.values())):
2020 raise RuntimeError(f
"Expect unique mdl chain names in mapping. Got "
2021 f
"{mapping.values()}")
2023 trg_chains = set([ch.GetName()
for ch
in chain_mapper.target.chains])
2024 mdl_chains = set([ch.GetName()
for ch
in mdl.chains])
2025 for k,v
in mapping.items():
2026 if k
not in trg_chains:
2027 raise RuntimeError(f
"Target chain \"{k}\" is not available "
2028 f
"in target processed for chain mapping "
2030 if v
not in mdl_chains:
2031 raise RuntimeError(f
"Model chain \"{v}\" is not available "
2032 f
"in model processed for chain mapping "
2035 for trg_ch, mdl_ch
in mapping.items():
2036 trg_group_idx =
None
2037 mdl_group_idx =
None
2038 for idx, group
in enumerate(chain_mapper.chem_groups):
2042 for idx, group
in enumerate(chem_mapping):
2046 if trg_group_idx
is None or mdl_group_idx
is None:
2047 raise RuntimeError(
"Could not establish a valid chem grouping "
2048 "of chain names provided in custom mapping.")
2050 if trg_group_idx != mdl_group_idx:
2051 raise RuntimeError(f
"Chem group mismatch in custom mapping: "
2052 f
"target chain \"{trg_ch}\" groups with the "
2053 f
"following chemically equivalent target "
2055 f
"{chain_mapper.chem_groups[trg_group_idx]} "
2056 f
"but model chain \"{mdl_ch}\" maps to the "
2057 f
"following target chains: "
2058 f
"{chain_mapper.chem_groups[mdl_group_idx]}")
2060 pairs = set([(trg_ch, mdl_ch)
for trg_ch, mdl_ch
in mapping.items()])
2062 chain_mapping._GetRefMdlAlns(chain_mapper.chem_groups,
2063 chain_mapper.chem_group_alignments,
2069 final_mapping = list()
2070 for ref_chains
in chain_mapper.chem_groups:
2071 mapped_mdl_chains = list()
2072 for ref_ch
in ref_chains:
2073 if ref_ch
in mapping:
2074 mapped_mdl_chains.append(mapping[ref_ch])
2076 mapped_mdl_chains.append(
None)
2077 final_mapping.append(mapped_mdl_chains)
2080 for ref_group, mdl_group
in zip(chain_mapper.chem_groups,
2082 for ref_ch, mdl_ch
in zip(ref_group, mdl_group):
2083 if ref_ch
is not None and mdl_ch
is not None:
2084 aln = ref_mdl_alns[(ref_ch, mdl_ch)]
2085 trg_view = chain_mapper.target.Select(f
"cname={ref_ch}")
2086 mdl_view = mdl.Select(f
"cname={mdl_ch}")
2087 aln.AttachView(0, trg_view)
2088 aln.AttachView(1, mdl_view)
2089 alns[(ref_ch, mdl_ch)] = aln
2092 chain_mapper.chem_groups,
2094 final_mapping, alns)
2096 def _compute_tmscore(self):
2100 flat_mapping = self.mapping.GetFlatMapping()
2101 res = res = bindings.WrappedMMAlign(self.
model, self.
target,
2102 mapping=flat_mapping)
2104 res = bindings.WrappedMMAlign(self.
model, self.
target)
2107 flat_mapping = self.mapping.GetFlatMapping()
2110 custom_chain_mapping = flat_mapping)
2117 for a,b
in zip(res.ent1_mapped_chains, res.ent2_mapped_chains):
def _compute_dockq_scores
void Molck(ost::mol::EntityHandle &ent, ost::conop::CompoundLibPtr lib, const MolckSettings &settings, bool prune=true)
def _get_interface_residues
_contact_model_interfaces
_per_interface_ics_precision
def transformed_mapped_model_pos
_per_interface_ics_recall
def contact_model_interfaces
def per_interface_qs_global
def per_interface_ics_precision
def per_interface_qs_best
def per_interface_ips_precision
def _compute_stereochecked_aln
def per_interface_ips_recall
_per_interface_ips_recall
Real Distance(const Vec3 &p1, const Vec3 &p2)
returns the distance between two points
_transformed_mapped_model_pos
def dockq_target_interfaces
def per_interface_ics_recall
def model_interface_residues
def contact_target_interfaces
def _compute_per_interface_qs_scores
_per_interface_ips_precision
def target_interface_residues
def _get_interface_patches
_target_interface_residues
def _compute_patchdockq_scores
_contact_target_interfaces
_model_interface_residues
def _compute_patchqs_scores