diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 3e0f907ae284424631f868c9d145bae6586f67b9..135c5a6936cfef202bc3a9ffbded2d6d26e91bd5 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -5,9 +5,23 @@ Changes in Release 2.4.0 based, natively supports complexes and is able to score DNA/RNA. The deprecated lDDT implementation remains for consistency. * Add algorithms to establish one to one mappings between chains in a reference - structure and a model. + structure and a model. Chain mappings can be derived by optimizing oligomeric + lDDT, RMSD or QS-score. * Substitution matrixes for RNA/DNA to compute alignments: seq.alg.IDENTITY and - seq.alg.NUC44 + seq.alg.NUC44. + * Add binding to DockQ (https://github.com/bjornwallner/DockQ) as well as an + OpenStructure specific implementation of it. Also allows to extract CAPRI + specific oligo scores (fnat, fnonnat, irmsd, lrmsd etc.) + * Reimplentation of QS-score in mol.alg.qsscore. Implements speedups and + heavy caching which benefits heavy enumeration approaches in chain mapping. + * Stereochemistry related algorithms in mol.alg.stereochemistry. Identifies + clashes and non-sensible bond lengths/angles based on parameterizations from + CCP4 MON_LIB. + * Better compression in OMF structure format. + * One central scoring object: mol.alg.scoring.Scorer. Access to all + OpenStructure specific scoring capabilities including required + pre-processing of model/reference (cleanup, stereochemistry checks, + chain mapping etc.). * Several minor bug fixes and improvements. Changes in Release 2.3.1 diff --git a/modules/conop/tests/test_heuristic_builder.cc b/modules/conop/tests/test_heuristic_builder.cc deleted file mode 100644 index 8ec8b697c5db071f340b3b0e8a28d62a8ba19468..0000000000000000000000000000000000000000 --- a/modules/conop/tests/test_heuristic_builder.cc +++ /dev/null @@ -1,224 +0,0 @@ -// ------------------------------------------------------------------------------ -// This file is part of the OpenStructure project <www.openstructure.org> - -// Copyright (C) 2008-2020 by the OpenStructure authors - -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License as published by the Free -// Software Foundation; either version 3.0 of the License, or (at your option) -// any later version. -// This library is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -// details. - -// You should have received a copy of the GNU Lesser General Public License -// along with this library; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// ------------------------------------------------------------------------------ - -#include <ost/mol/mol.hh> -#include <ost/conop/heuristic_builder.hh> - -#define BOOST_TEST_DYN_LINK -#include <boost/test/unit_test.hpp> - -#include <ost/log.hh> -using boost::unit_test_framework::test_suite; -using namespace ost; -using namespace ost::conop; -using namespace ost::mol; -namespace { -} // anon ns - -ResidueHandle make_arg(ChainHandle chain) -{ - XCSEditor e=chain.GetEntity().EditXCS(); - ResidueHandle res = e.AppendResidue(chain, "ARG"); - e.InsertAtom(res, "N",geom::Vec3(20.202,33.112,58.011)); - e.InsertAtom(res, "CA",geom::Vec3(19.396,31.903,58.033)); - e.InsertAtom(res, "C",geom::Vec3(18.608,31.739,59.328)); - e.InsertAtom(res, "O",geom::Vec3(17.651,30.965,59.381)); - e.InsertAtom(res, "CB",geom::Vec3(20.284,30.681,57.801)); - e.InsertAtom(res, "CG",geom::Vec3(20.665,30.488,56.342)); - e.InsertAtom(res, "CD",geom::Vec3(21.557,29.281,56.154)); - e.InsertAtom(res, "NE",geom::Vec3(22.931,29.557,56.551)); - e.InsertAtom(res, "CZ",geom::Vec3(23.901,28.653,56.528)); - e.InsertAtom(res, "NH1",geom::Vec3(23.640,27.417,56.130)); - e.InsertAtom(res, "NH2",geom::Vec3(25.132,28.980,56.893)); - return res; -} - -ResidueHandle make_leu(ChainHandle chain) -{ - XCSEditor e=chain.GetEntity().EditXCS(); - ResidueHandle res=e.AppendResidue(chain, "LEU"); - - e.InsertAtom(res, "N", geom::Vec3(19.003,32.473,60.366)); - e.InsertAtom(res, "CA", geom::Vec3(18.330,32.402,61.664)); - e.InsertAtom(res, "C", geom::Vec3(17.884,33.787,62.117)); - e.InsertAtom(res, "O", geom::Vec3(17.853,34.091,63.308)); - e.InsertAtom(res, "CB", geom::Vec3(19.269,31.793,62.710)); - e.InsertAtom(res, "CG", geom::Vec3(19.695,30.340,62.501)); - e.InsertAtom(res, "CD1", geom::Vec3(20.585,29.897,63.648)); - e.InsertAtom(res, "CD2", geom::Vec3(18.461,29.459,62.420)); - return res; -} - -ResidueHandle make_defective_leu(ChainHandle chain) -{ - XCSEditor e=chain.GetEntity().EditXCS(); - ResidueHandle res=e.AppendResidue(chain, "LEU"); - - e.InsertAtom(res, "N", geom::Vec3(19.003,32.473,60.366)); - e.InsertAtom(res, "CA", geom::Vec3(18.330,32.402,61.664)); - e.InsertAtom(res, "C", geom::Vec3(17.884,33.787,62.117)); - e.InsertAtom(res, "O", geom::Vec3(17.853,34.091,63.308)); - e.InsertAtom(res, "CB", geom::Vec3(19.269,31.793,102.710)); - e.InsertAtom(res, "CG", geom::Vec3(19.695,30.340,62.501)); - e.InsertAtom(res, "CD1", geom::Vec3(20.585,29.897,63.648)); - e.InsertAtom(res, "CD2", geom::Vec3(18.461,29.459,62.420)); - return res; -} - -void verify_connectivity_x(const ResidueHandle& res) -{ - BOOST_CHECK(BondExists(res.FindAtom("XN"), - res.FindAtom("XCA"))); - BOOST_CHECK(BondExists(res.FindAtom("XCA"), - res.FindAtom("XC"))); - BOOST_CHECK(BondExists(res.FindAtom("XC"), - res.FindAtom("XO"))); - BOOST_CHECK(BondExists(res.FindAtom("XCA"), - res.FindAtom("XCB"))); - BOOST_CHECK(BondExists(res.FindAtom("XCB"), - res.FindAtom("XCG"))); - if (res.GetKey()=="ARG") { - - BOOST_CHECK(BondExists(res.FindAtom("XCB"), - res.FindAtom("XCG"))); - BOOST_CHECK(BondExists(res.FindAtom("XCG"), - res.FindAtom("XCD"))); - BOOST_CHECK(BondExists(res.FindAtom("XCD"), - res.FindAtom("XNE"))); - BOOST_CHECK(BondExists(res.FindAtom("XNE"), - res.FindAtom("XCZ"))); - BOOST_CHECK(BondExists(res.FindAtom("XCZ"), - res.FindAtom("XNH1"))); - BOOST_CHECK(BondExists(res.FindAtom("XCZ"), - res.FindAtom("XNH2"))); - // TODO: Check that no other atoms are connected! - } - if (res.GetKey()=="ILE") { - BOOST_CHECK(BondExists(res.FindAtom("XCG"), - res.FindAtom("XCD1"))); - BOOST_CHECK(BondExists(res.FindAtom("XCG"), - res.FindAtom("XCD2"))); - // TODO: Check that no other atoms are connected! - } -} - -void verify_connectivity(const ResidueHandle& res) -{ - BOOST_CHECK(BondExists(res.FindAtom("N"), - res.FindAtom("CA"))); - BOOST_CHECK(BondExists(res.FindAtom("CA"), - res.FindAtom("C"))); - BOOST_CHECK(BondExists(res.FindAtom("C"), - res.FindAtom("O"))); - BOOST_CHECK(BondExists(res.FindAtom("CA"), - res.FindAtom("CB"))); - BOOST_CHECK(BondExists(res.FindAtom("CB"), - res.FindAtom("CG"))); - if (res.GetKey()=="ARG") { - - BOOST_CHECK(BondExists(res.FindAtom("CB"), - res.FindAtom("CG"))); - BOOST_CHECK(BondExists(res.FindAtom("CG"), - res.FindAtom("CD"))); - BOOST_CHECK(BondExists(res.FindAtom("CD"), - res.FindAtom("NE"))); - BOOST_CHECK(BondExists(res.FindAtom("NE"), - res.FindAtom("CZ"))); - BOOST_CHECK(BondExists(res.FindAtom("CZ"), - res.FindAtom("NH1"))); - BOOST_CHECK(BondExists(res.FindAtom("CZ"), - res.FindAtom("NH2"))); - // TODO: Check that no other atoms are connected! - } - if (res.GetKey()=="ILE") { - BOOST_CHECK(BondExists(res.FindAtom("CG"), - res.FindAtom("CD1"))); - BOOST_CHECK(BondExists(res.FindAtom("CG"), - res.FindAtom("CD2"))); - // TODO: Check that no other atoms are connected! - } -} - -BOOST_AUTO_TEST_SUITE( conop ); - - -BOOST_AUTO_TEST_CASE(name_based_connect) -{ - EntityHandle e=CreateEntity(); - ChainHandle c=e.EditXCS().InsertChain("A"); - ResidueHandle ile=make_leu(c); - ResidueHandle arg=make_arg(c); - HeuristicBuilder heuristic_builder; - AtomHandleList atoms =e .GetAtomList(); - for (AtomHandleList::const_iterator i = atoms.begin(), e = atoms.end(); i!=e; ++i ){ - heuristic_builder.FillAtomProps(*i); - } - - EntityHandle de=CreateEntity(); - ChainHandle dc=de.EditXCS().InsertChain("A"); - ResidueHandle dile=make_defective_leu(dc); - HeuristicBuilder dheuristic_builder; - dheuristic_builder.SetBondFeasibilityCheck(false); - atoms = de.GetAtomList(); - for (AtomHandleList::const_iterator i = atoms.begin(), e = atoms.end(); i!=e; ++i ){ - dheuristic_builder.FillAtomProps(*i); - } - - BOOST_TEST_MESSAGE("running distance based checks on arginine"); - heuristic_builder.ConnectAtomsOfResidue(arg); - verify_connectivity(arg); - BOOST_TEST_MESSAGE("running distance based checks on leu"); - heuristic_builder.ConnectAtomsOfResidue(ile); - verify_connectivity(ile); - - BOOST_TEST_MESSAGE("running distance based checks on defective leu"); - dheuristic_builder.ConnectAtomsOfResidue(dile); - verify_connectivity(dile); -} - -BOOST_AUTO_TEST_CASE(test_assign_torsions){ - EntityHandle e=CreateEntity(); - ChainHandle c=e.EditXCS().InsertChain("A"); - ResidueHandle l1=make_leu(c); - ResidueHandle a2=make_arg(c); - ResidueHandle l3=make_leu(c); - l1.SetChemClass(ChemClass(ChemClass::L_PEPTIDE_LINKING)); - a2.SetChemClass(ChemClass(ChemClass::L_PEPTIDE_LINKING)); - l3.SetChemClass(ChemClass(ChemClass::L_PEPTIDE_LINKING)); - HeuristicBuilder heuristic_builder; - AtomHandleList atoms = e.GetAtomList(); - for (AtomHandleList::const_iterator i = atoms.begin(), e = atoms.end(); i!=e; ++i ){ - heuristic_builder.FillAtomProps(*i); - } - heuristic_builder.ConnectAtomsOfResidue(l1); - heuristic_builder.ConnectAtomsOfResidue(a2); - heuristic_builder.ConnectAtomsOfResidue(l3); - XCSEditor edi=e.EditXCS(); - edi.Connect(l1.FindAtom("C"), a2.FindAtom("N")); - edi.Connect(a2.FindAtom("C"), l3.FindAtom("N")); - heuristic_builder.AssignTorsions(c); - - BOOST_CHECK(a2.GetPhiTorsion().IsValid()); - BOOST_CHECK(l3.GetPhiTorsion().IsValid()); - - BOOST_CHECK(l1.GetPsiTorsion().IsValid()); - BOOST_CHECK(a2.GetPsiTorsion().IsValid()); -} - -BOOST_AUTO_TEST_SUITE_END( ); diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst index 41a6ed5f2e59c0c13e915d1bc527d2de5469b498..63bfd882298c4ef22dae31c1ef2d29919296863f 100644 --- a/modules/io/doc/mmcif.rst +++ b/modules/io/doc/mmcif.rst @@ -96,7 +96,8 @@ of the annotation available. .. attribute:: method - Stores the experimental method used to create the structure. + Stores the experimental method used to create the structure + (|exptl.method|_). Also available as :meth:`GetMethod`. May also be modified by :meth:`SetMethod`. @@ -1308,6 +1309,9 @@ of the annotation available. See :attr:`bond_order` +.. |exptl.method| replace:: ``exptl.method`` +.. _exptl.method: https://mmcif.wwpdb.org/dictionaries/mmcif_pdbx_v50.dic/Items/_exptl.method.html + .. LocalWords: cas isbn pubmed asu seqres conop ConnectAll casp COMPND OBSLTE .. LocalWords: SPRSDE pdb func autofunction exptl attr pdbx oper conf spr dif .. LocalWords: biounits biounit uniprot UNP seqs AddMMCifPDBChainTr cif asym diff --git a/modules/mol/alg/pymod/chain_mapping.py b/modules/mol/alg/pymod/chain_mapping.py index c9e9aec85a40f46929024d8510058a194b1197fd..c8bfa7c7789ca7440cdb84c55ce5ea6bf03709cb 100644 --- a/modules/mol/alg/pymod/chain_mapping.py +++ b/modules/mol/alg/pymod/chain_mapping.py @@ -723,7 +723,8 @@ class ChainMapper: def GetlDDTMapping(self, model, inclusion_radius=15.0, thresholds=[0.5, 1.0, 2.0, 4.0], strategy="naive", steep_opt_rate = None, full_n_mdl_chains = None, - block_seed_size = 5, block_blocks_per_chem_group = 5): + block_seed_size = 5, block_blocks_per_chem_group = 5, + chem_mapping_result = None): """ Identify chain mapping by optimizing lDDT score Maps *model* chain sequences to :attr:`~chem_groups` and find mapping @@ -789,6 +790,11 @@ class ChainMapper: are extended in an initial search for high scoring local solutions. :type block_blocks_per_chem_group: :class:`int` + :param chem_mapping_result: Pro param. The result of + :func:`~GetChemMapping` where you provided + *model*. If set, *model* parameter is not + used. + :type chem_mapping_result: :class:`tuple` :returns: A :class:`MappingResult` """ @@ -796,7 +802,10 @@ class ChainMapper: if strategy not in strategies: raise RuntimeError(f"Strategy must be in {strategies}") - chem_mapping, chem_group_alns, mdl = self.GetChemMapping(model) + if chem_mapping_result is None: + chem_mapping, chem_group_alns, mdl = self.GetChemMapping(model) + else: + chem_mapping, chem_group_alns, mdl = chem_mapping_result ref_mdl_alns = _GetRefMdlAlns(self.chem_groups, self.chem_group_alignments, @@ -854,7 +863,7 @@ class ChainMapper: def GetQSScoreMapping(self, model, contact_d = 12.0, strategy = "naive", full_n_mdl_chains = None, block_seed_size = 5, block_blocks_per_chem_group = 5, - steep_opt_rate = None): + steep_opt_rate = None, chem_mapping_result = None): """ Identify chain mapping based on QSScore Scoring is based on CA/C3' positions which are present in all chains of @@ -892,6 +901,11 @@ class ChainMapper: :type contact_d: :class:`float` :param strategy: Strategy for sampling, must be in ["naive"] :type strategy: :class:`str` + :param chem_mapping_result: Pro param. The result of + :func:`~GetChemMapping` where you provided + *model*. If set, *model* parameter is not + used. + :type chem_mapping_result: :class:`tuple` :returns: A :class:`MappingResult` """ @@ -899,7 +913,10 @@ class ChainMapper: if strategy not in strategies: raise RuntimeError(f"strategy must be {strategies}") - chem_mapping, chem_group_alns, mdl = self.GetChemMapping(model) + if chem_mapping_result is None: + chem_mapping, chem_group_alns, mdl = self.GetChemMapping(model) + else: + chem_mapping, chem_group_alns, mdl = chem_mapping_result ref_mdl_alns = _GetRefMdlAlns(self.chem_groups, self.chem_group_alignments, chem_mapping, @@ -952,7 +969,8 @@ class ChainMapper: def GetRigidMapping(self, model, strategy = "greedy_single_gdtts", single_chain_gdtts_thresh=0.4, subsampling=None, - first_complete=False, iterative_superposition=False): + first_complete=False, iterative_superposition=False, + chem_mapping_result = None): """Identify chain mapping based on rigid superposition Superposition and scoring is based on CA/C3' positions which are present @@ -1007,6 +1025,11 @@ class ChainMapper: as oposed to :func:`ost.mol.alg.SuperposeSVD` :type iterative_superposition: :class:`bool` + :param chem_mapping_result: Pro param. The result of + :func:`~GetChemMapping` where you provided + *model*. If set, *model* parameter is not + used. + :type chem_mapping_result: :class:`tuple` :returns: A :class:`MappingResult` """ @@ -1015,7 +1038,10 @@ class ChainMapper: if strategy not in strategies: raise RuntimeError(f"strategy must be {strategies}") - chem_mapping, chem_group_alns, mdl = self.GetChemMapping(model) + if chem_mapping_result is None: + chem_mapping, chem_group_alns, mdl = self.GetChemMapping(model) + else: + chem_mapping, chem_group_alns, mdl = chem_mapping_result ref_mdl_alns = _GetRefMdlAlns(self.chem_groups, self.chem_group_alignments, chem_mapping, @@ -1111,7 +1137,7 @@ class ChainMapper: def GetRepr(self, substructure, model, topn=1, inclusion_radius=15.0, thresholds=[0.5, 1.0, 2.0, 4.0], bb_only=False, - only_interchain=False): + only_interchain=False, chem_mapping_result = None): """ Identify *topn* representations of *substructure* in *model* *substructure* defines a subset of :attr:`~target` for which one @@ -1142,7 +1168,11 @@ class ChainMapper: :param only_interchain: Only score interchain contacts in lDDT. Useful if you want to identify interface patches. :type only_interchain: :class:`bool` - + :param chem_mapping_result: Pro param. The result of + :func:`~GetChemMapping` where you provided + *model*. If set, *model* parameter is not + used. + :type chem_mapping_result: :class:`tuple` :returns: :class:`list` of :class:`ReprResult` """ @@ -1186,7 +1216,10 @@ class ChainMapper: "a backbone atom named CA or C3\'") # perform mapping and alignments on full structures - chem_mapping, chem_group_alns, mdl = self.GetChemMapping(model) + if chem_mapping_result is None: + chem_mapping, chem_group_alns, mdl = self.GetChemMapping(model) + else: + chem_mapping, chem_group_alns, mdl = chem_mapping_result ref_mdl_alns = _GetRefMdlAlns(self.chem_groups, self.chem_group_alignments, chem_mapping, diff --git a/modules/mol/alg/pymod/qsscore.py b/modules/mol/alg/pymod/qsscore.py index 3d28456532e7eb94ee80a9ba5a2d88cf6d7bf485..db5079ef9fd8a3b4ddeb70bf3b0fa77d60db9182 100644 --- a/modules/mol/alg/pymod/qsscore.py +++ b/modules/mol/alg/pymod/qsscore.py @@ -396,6 +396,41 @@ class QSScorer: return self.FromFlatMapping(flat_mapping) + def ScoreInterface(self, trg_ch1, trg_ch2, mdl_ch1, mdl_ch2): + """ Computes QS-score only considering one interface + + This only works for interfaces that are computed in :func:`Score`, i.e. + interfaces for which the alignments are set up correctly. + + :param trg_ch1: Name of first interface chain in target + :type trg_ch1: :class:`str` + :param trg_ch2: Name of second interface chain in target + :type trg_ch2: :class:`str` + :param mdl_ch1: Name of first interface chain in model + :type mdl_ch1: :class:`str` + :param mdl_ch2: Name of second interface chain in model + :type mdl_ch2: :class:`str` + :returns: Result object of type :class:`QSScorerResult` + :raises: :class:`RuntimeError` if no aln for trg_ch1/mdl_ch1 or + trg_ch2/mdl_ch2 is available. + """ + if (trg_ch1, mdl_ch1) not in self.alns: + raise RuntimeError(f"No aln between trg_ch1 ({trg_ch1}) and " + f"mdl_ch1 ({mdl_ch1}) available. Did you " + f"construct the QSScorer object from a " + f"MappingResult and are trg_ch1 and mdl_ch1 " + f"mapped to each other?") + if (trg_ch2, mdl_ch2) not in self.alns: + raise RuntimeError(f"No aln between trg_ch1 ({trg_ch1}) and " + f"mdl_ch1 ({mdl_ch1}) available. Did you " + f"construct the QSScorer object from a " + f"MappingResult and are trg_ch1 and mdl_ch1 " + f"mapped to each other?") + trg_int = (trg_ch1, trg_ch2) + mdl_int = (mdl_ch1, mdl_ch2) + a, b, c, d = self._MappedInterfaceScores(trg_int, mdl_int) + return QSScorerResult(a, b, c, d) + def FromFlatMapping(self, flat_mapping): """ Same as :func:`Score` but with flat mapping diff --git a/modules/mol/alg/pymod/scoring.py b/modules/mol/alg/pymod/scoring.py index 6d5b345ec9bb012c6b262c43bb0b587ff096641d..70f2dd5b2560df259ae3ba5d0fd02b678bc47dc0 100644 --- a/modules/mol/alg/pymod/scoring.py +++ b/modules/mol/alg/pymod/scoring.py @@ -109,10 +109,11 @@ class Scorer: colored to True in :class:`ost.mol.alg.MolckSettings` constructor. :type molck_settings: :class:`ost.mol.alg.MolckSettings` - :param naive_chain_mapping_thresh: Chain mappings for targets up to that - number of chains will be fully enumerated - to optimize for QS-score. Everything - above is treated with a heuristic. + :param naive_chain_mapping_thresh: Chain mappings for targets/models up to + that number of chains will be fully + enumerated to optimize for QS-score. + Everything above is treated with a + heuristic. :type naive_chain_mapping_thresh: :class:`int` :param cad_score_exec: Explicit path to voronota-cadscore executable from voronota installation from @@ -204,12 +205,19 @@ class Scorer: self._qs_global = None self._qs_best = None - - self._dockq_interfaces = None - self._dockq_native_contacts = None + self._interface_qs_global = None + self._interface_qs_best = None + + self._interfaces = None + self._native_contacts = None + self._model_contacts = None + self._fnat = None + self._fnonnat = None + self._irmsd = None + self._lrmsd = None + self._nonmapped_interfaces = None + self._nonmapped_interfaces_contacts = None self._dockq_scores = None - self._dockq_nonmapped_interfaces = None - self._dockq_nonmapped_interfaces_counts = None self._dockq_ave = None self._dockq_wave = None self._dockq_ave_full = None @@ -356,15 +364,20 @@ class Scorer: """ if self._mapping is None: n_trg_chains = len(self.chain_mapper.target.chains) - if n_trg_chains <= self.naive_chain_mapping_thresh: + res = self.chain_mapper.GetChemMapping(self.model) + n_mdl_chains = len(res[2].chains) + thresh = self.naive_chain_mapping_thresh + if n_trg_chains <= thresh and n_mdl_chains <= thresh: m = self.chain_mapper.GetQSScoreMapping(self.model, - strategy="naive") + strategy="naive", + chem_mapping_result=res) else: m = self.chain_mapper.GetQSScoreMapping(self.model, strategy="greedy_block", steep_opt_rate=3, block_seed_size=5, - block_blocks_per_chem_group=6) + block_blocks_per_chem_group=6, + chem_mapping_result=res) self._mapping = m return self._mapping @@ -476,40 +489,130 @@ class Scorer: return self._qs_best @property - def dockq_interfaces(self): - """ Interfaces considered in DockQ (i.e. nonzero native contacts) - - DockQ is computed on interfaces as defined by :attr:`~mapping`. + def interfaces(self): + """ Interfaces with nonzero :attr:`native_contacts` :type: :class:`list` of :class:`tuple` with 4 elements each: (trg_ch1, trg_ch2, mdl_ch1, mdl_ch2) """ - if self._dockq_interfaces is None: - self._compute_dockq() - return self._dockq_interfaces + if self._interfaces is None: + self._compute_per_interface_scores() + return self._interfaces + + @property + def interface_qs_global(self): + """ QS-score for each interface in :attr:`interfaces` + + :type: :class:`list` of :class:`float` + """ + if self._interface_qs_global is None: + self._compute_per_interface_scores() + return self._interface_qs_global @property - def dockq_native_contacts(self): - """ N native contacts for interfaces in :attr:`~dockq_interfaces` + def interface_qs_best(self): + """ QS-score for each interface in :attr:`interfaces` + + Only computed on aligned residues + + :type: :class:`list` of :class:`float` + """ + if self._interface_qs_best is None: + self._compute_per_interface_scores() + return self._interface_qs_best + + @property + def native_contacts(self): + """ N native contacts for interfaces in :attr:`~interfaces` + + A contact is a pair or residues from distinct chains that have + a minimal heavy atom distance < 5A + + :type: :class:`list` of :class:`int` + """ + if self._native_contacts is None: + self._compute_per_interface_scores() + return self._native_contacts + + @property + def model_contacts(self): + """ N model contacts for interfaces in :attr:`~interfaces` + + A contact is a pair or residues from distinct chains that have + a minimal heavy atom distance < 5A :type: :class:`list` of :class:`int` """ - if self._dockq_native_contacts is None: - self._compute_dockq() - return self._dockq_native_contacts + if self._model_contacts is None: + self._compute_per_interface_scores() + return self._model_contacts @property def dockq_scores(self): - """ DockQ scores for interfaces in :attr:`~dockq_interfaces` + """ DockQ scores for interfaces in :attr:`~interfaces` :class:`list` of :class:`float` """ if self._dockq_scores is None: - self._compute_dockq() + self._compute_per_interface_scores() return self._dockq_scores @property - def dockq_nonmapped_interfaces(self): + def fnat(self): + """ fnat scores for interfaces in :attr:`~interfaces` + + fnat: Fraction of native contacts that are also present in model + + :class:`list` of :class:`float` + """ + if self._fnat is None: + self._compute_per_interface_scores() + return self._fnat + + @property + def fnonnat(self): + """ fnonnat scores for interfaces in :attr:`~interfaces` + + fnat: Fraction of model contacts that are not present in target + + :class:`list` of :class:`float` + """ + if self._fnonnat is None: + self._compute_per_interface_scores() + return self._fnonnat + + @property + def irmsd(self): + """ irmsd scores for interfaces in :attr:`~interfaces` + + irmsd: RMSD of interface (RMSD computed on N, CA, C, O atoms) which + consists of each residue that has at least one heavy atom within 10A of + other chain. + + :class:`list` of :class:`float` + """ + if self._irmsd is None: + self._compute_per_interface_scores() + return self._irmsd + + @property + def lrmsd(self): + """ lrmsd scores for interfaces in :attr:`~interfaces` + + lrmsd: The interfaces are superposed based on the receptor (rigid + min RMSD superposition) and RMSD for the ligand is reported. + Superposition and RMSD are based on N, CA, C and O positions, + receptor is the chain contributing to the interface with more + residues in total. + + :class:`list` of :class:`float` + """ + if self._lrmsd is None: + self._compute_per_interface_scores() + return self._lrmsd + + @property + def nonmapped_interfaces(self): """ Interfaces present in target that are not mapped At least one of the chains is not present in target @@ -517,19 +620,19 @@ class Scorer: :type: :class:`list` of :class:`tuple` with two elements each: (trg_ch1, trg_ch2) """ - if self._dockq_nonmapped_interfaces is None: - self._compute_dockq() - return self._dockq_nonmapped_interfaces + if self._nonmapped_interfaces is None: + self._compute_per_interface_scores() + return self._nonmapped_interfaces @property - def dockq_nonmapped_interfaces_counts(self): - """ Number of native contacts in :attr:`~dockq_nonmapped_interfaces` + def nonmapped_interfaces_contacts(self): + """ Number of native contacts in :attr:`~nonmapped_interfaces` :type: :class:`list` of :class:`int` """ - if self._dockq_nonmapped_interfaces_counts is None: - self._compute_dockq() - return self._dockq_nonmapped_interfaces_counts + if self._nonmapped_interfaces_contacts is None: + self._compute_per_interface_scores() + return self._nonmapped_interfaces_contacts @property def dockq_ave(self): @@ -542,42 +645,42 @@ class Scorer: :type: :class:`float` """ if self._dockq_ave is None: - self._compute_dockq() + self._compute_per_interface_scores() return self._dockq_ave @property def dockq_wave(self): - """ Same as :attr:`dockq_ave`, weighted by :attr:`dockq_native_contacts` + """ Same as :attr:`dockq_ave`, weighted by :attr:`native_contacts` :type: :class:`float` """ if self._dockq_wave is None: - self._compute_dockq() + self._compute_per_interface_scores() return self._dockq_wave @property def dockq_ave_full(self): """ Same as :attr:`~dockq_ave` but penalizing for missing interfaces - Interfaces in :attr:`dockq_nonmapped_interfaces` are added as 0.0 + Interfaces in :attr:`nonmapped_interfaces` are added as 0.0 in average computation. :type: :class:`float` """ if self._dockq_ave_full is None: - self._compute_dockq() + self._compute_per_interface_scores() return self._dockq_ave_full @property def dockq_wave_full(self): """ Same as :attr:`~dockq_ave_full`, but weighted - Interfaces in :attr:`dockq_nonmapped_interfaces` are added as 0.0 in + Interfaces in :attr:`nonmapped_interfaces` are added as 0.0 in average computations and the respective weights are derived from - :attr:`~dockq_nonmapped_interfaces_counts` + :attr:`~nonmapped_interfaces_contacts` """ if self._dockq_wave_full is None: - self._compute_dockq() + self._compute_per_interface_scores() return self._dockq_wave_full @property @@ -856,24 +959,25 @@ class Scorer: self._qs_global = qs_score_result.QS_global self._qs_best = qs_score_result.QS_best - def _compute_dockq(self): - if not self.resnum_alignments: - raise RuntimeError("DockQ computations rely on residue numbers " - "that are consistent between target and model " - "chains, i.e. only work if resnum_alignments " - "is True at Scorer construction.") - + def _compute_per_interface_scores(self): flat_mapping = self.mapping.GetFlatMapping() # list of [trg_ch1, trg_ch2, mdl_ch1, mdl_ch2] - self._dockq_interfaces = list() + self._interfaces = list() # lists with respective values for these interfaces - self._dockq_native_contacts = list() + self._native_contacts = list() + self._model_contacts = list() + self._interface_qs_global = list() + self._interface_qs_best = list() self._dockq_scores = list() + self._fnat = list() + self._fnonnat = list() + self._irmsd = list() + self._lrmsd = list() # list of interfaces which are present in target but not mapped, i.e. # not present in mdl - self._dockq_nonmapped_interfaces = list() - self._dockq_nonmapped_interfaces_counts = list() + self._nonmapped_interfaces = list() + self._nonmapped_interfaces_contacts = list() nonmapped_interface_counts = list() @@ -898,10 +1002,6 @@ class Scorer: s.AttachView(self.model.Select(f"cname={cname}")) mdl_seqs[ch.GetName()] = s - trg_pep_chains = [s.GetName() for s in self.chain_mapper.polypep_seqs] - trg_nuc_chains = [s.GetName() for s in self.chain_mapper.polynuc_seqs] - trg_pep_chains = set(trg_pep_chains) - trg_nuc_chains = set(trg_nuc_chains) dockq_alns = dict() for trg_ch, mdl_ch in flat_mapping.items(): if trg_ch in pep_seqs: @@ -922,10 +1022,19 @@ class Scorer: trg_ch1, trg_ch2, ch1_aln=aln1, ch2_aln=aln2) if res["nnat"] > 0: - self._dockq_interfaces.append((trg_ch1, trg_ch2, - mdl_ch1, mdl_ch2)) - self._dockq_native_contacts.append(res["nnat"]) + self._interfaces.append((trg_ch1, trg_ch2, + mdl_ch1, mdl_ch2)) + self._native_contacts.append(res["nnat"]) + self._model_contacts.append(res["nmdl"]) + self._fnat.append(res["fnat"]) + self._fnonnat.append(res["fnonnat"]) + self._irmsd.append(res["irmsd"]) + self._lrmsd.append(res["lrmsd"]) self._dockq_scores.append(res["DockQ"]) + qs_res = self.qs_scorer.ScoreInterface(trg_ch1, trg_ch2, + mdl_ch1, mdl_ch2) + self._interface_qs_best.append(qs_res.QS_best) + self._interface_qs_global.append(qs_res.QS_global) else: # interface which is not covered by mdl... let's run DockQ # with trg as trg/mdl in order to get the native contacts @@ -935,20 +1044,19 @@ class Scorer: trg_ch1, trg_ch2, trg_ch1, trg_ch2) nnat = res["nnat"] if nnat > 0: - self._dockq_nonmapped_interfaces.append((trg_ch1, - trg_ch2)) - self._dockq_nonmapped_interfaces_counts.append(nnat) + self._nonmapped_interfaces.append((trg_ch1, trg_ch2)) + self._nonmapped_interfaces_contacts.append(nnat) # there are 4 types of combined scores # - simple average # - average weighted by native_contacts # - the two above including nonmapped_interfaces => set DockQ to 0.0 scores = np.array(self._dockq_scores) - weights = np.array(self._dockq_native_contacts) + weights = np.array(self._native_contacts) self._dockq_ave = np.mean(scores) self._dockq_wave = np.sum(np.multiply(weights/np.sum(weights), scores)) - scores = np.append(scores, [0.0]*len(self._dockq_nonmapped_interfaces)) - weights = np.append(weights, self._dockq_nonmapped_interfaces_counts) + scores = np.append(scores, [0.0]*len(self._nonmapped_interfaces)) + weights = np.append(weights, self._nonmapped_interfaces_contacts) self._dockq_ave_full = np.mean(scores) self._dockq_wave_full = np.sum(np.multiply(weights/np.sum(weights), scores)) diff --git a/modules/mol/base/doc/editors.rst b/modules/mol/base/doc/editors.rst index 71577df3659a187de0de1d57683cf155a16ceb86..e2218db714d771cd1c8ed66c6659b0148ed0f719 100644 --- a/modules/mol/base/doc/editors.rst +++ b/modules/mol/base/doc/editors.rst @@ -69,15 +69,21 @@ The basic functionality of editors is implemented in the EditorBase class. :returns: :class:`ChainHandle` .. method:: AppendResidue(chain, residue_name, [res_num]) + AppendResidue(chain, residue_name, deep=False) Append residue to the end of the chain. If res_num is not given, the residue number will be set to the residue number of the last added residue plus one. The insertion code is the same. + By default, atoms and bonds are not added. If deep is `True`, atoms (but + not bonds) are added to the new residue, including alternative atoms. + :param chain: Must be a valid chain :type chain: :class:`ChainHandle` :param residue_name: 3-letter-code of the residue, e.g. ``GLY``. - :type residue_name: string + :type residue_name: :class:`string` + :param deep: If set to true, insert atoms as well. + :type deep: :class:`bool` :returns: :class:`ResidueHandle` .. method:: RenameResidue(residue, new_name) diff --git a/modules/mol/base/doc/entity.rst b/modules/mol/base/doc/entity.rst index 5e778d670030a26e19533f4a679c5fbcde9cd2d3..173ea4a9296c87a2f96345d1857aa9edf3b3189a 100644 --- a/modules/mol/base/doc/entity.rst +++ b/modules/mol/base/doc/entity.rst @@ -98,19 +98,28 @@ The Handle Classes :type: float + .. attribute:: center_of_atoms + + Center of atoms, that is the average atom position of the entity. + Use :attr:`center_of_mass` for the the mass-weighted center of the entity. + Also available as :meth:`GetCenterOfAtoms`. + + :type: :class:`~ost.geom.Vec3` + .. attribute:: center_of_mass - Center of mass. Also available as :meth:`GetCenterOfMass` - - :type: :class:`~ost.geom.Vec3` - - .. attribute:: center_of_atoms - - Center of atoms (not mass-weighted). Also available as - :meth:`GetCenterOfAtoms`. + Center of mass of the entity. + Also available as :meth:`GetCenterOfMass` :type: :class:`~ost.geom.Vec3` + .. attribute:: geometric_center + + Mid-point of the axis aligned bounding box of the entity. + Also available as :meth:`GetGeometricCenter` + + :type: Vec3 + .. attribute:: positions Equivalent to calling :meth:`GetPositions` with *sort_by_index = True*. This @@ -286,29 +295,21 @@ The Handle Classes alternative atom positions are not handled yet. + .. method:: GetMass() + + See :attr:`mass` + .. method:: GetCenterOfAtoms() - - Get center of atoms, that is the average atom position of the entity. Use - :meth:`GetCenterOfMass` to calculate the mass-weighted center of the entity. - - :returns: :class:`~ost.geom.Vec3` - + + See :attr:`center_of_atoms` + .. method:: GetCenterOfMass() - - Calculates the center of mass of the entity. Use :meth:`GetCenterOfAtoms` - to calculate the non-mass-weighted center of the entity. - - :returns: :class:`~ost.geom.Vec3` - + + See :attr:`center_of_mass` + .. method:: GetGeometricCenter() - - Calculates the mid-point of the axis aligned bounding box of the entity. - - :returns: :class:`~ost.geom.Vec3` - - .. method:: GetMass() - - See :attr:`mass` + + See :attr:`geometric_center` .. method:: GetPositions(sort_by_index=True) @@ -367,10 +368,17 @@ The Handle Classes .. attribute:: center_of_mass - Center of mass. Also available as :meth:`GetCenterOfMass` + Center of mass. Also available as :meth:`GetCenterOfMass`. :type: :class:`~ost.geom.Vec3` + .. attribute:: geometric_center + + Mid-point of the axis aligned bounding box of the chain. + Also available as :meth:`GetGeometricCenter` + + :type: Vec3 + .. attribute:: description Details about the chain. Not categorised, just text. @@ -567,9 +575,20 @@ The Handle Classes The residue name is usually a str of 3 characters, e.g. `GLY` for glycine or `ALA` for alanine, but may be shorter, e.g. `G` for guanosine, or longer for structures loaded from formats other than PDB. + Also available as :meth:`GetName`. This property is read-only. To change the name of the residue, use :meth:`~EditorBase.RenameResidue`. + + :type: str + + .. attribute:: qualified_name + + The qualified name consists of a residue identifier and chain name. + For a glycine with residue number 2 of chain A, the qualified name is + "A.GLY2". Also available as :meth:`GetQualifiedName`. + + :type: str .. attribute:: number @@ -605,6 +624,18 @@ The Handle Classes :type: :class:`AtomHandleList` (list of :class:`AtomHandle`) + .. attribute:: atom_count + + Number of atoms. Read-only. See :meth:`GetAtomCount`. + + :type: :class:`int` + + .. attribute:: bond_count + + Number of bonds. Read-only. See :meth:`GetBondCount`. + + :type: :class:`int` + .. attribute:: bounds Axis-aligned bounding box of the residue. Read-only. @@ -616,12 +647,6 @@ The Handle Classes The total mass of this residue in Dalton. Also available as :meth:`GetMass`. :type: float - - .. attribute:: center_of_mass - - Center of mass. Also available as :meth:`GetCenterOfMass` - - :type: :class:`~ost.geom.Vec3` .. attribute:: center_of_atoms @@ -630,6 +655,18 @@ The Handle Classes :type: :class:`~ost.geom.Vec3` + .. attribute:: center_of_mass + + Center of mass. Also available as :meth:`GetCenterOfMass` + + :type: :class:`~ost.geom.Vec3` + + .. attribute:: geometric_center + + Mid-point of the axis aligned bounding box of the residue. + + :type: Vec3 + .. attribute:: chain The chain this residue belongs to. Read-only. Also available as @@ -656,6 +693,15 @@ The Handle Classes torsion, the PSI torsion is an invalid handle. Read-only. Also available as :meth:`GetPsiTorsion` + + .. attribute:: omega_torsion + + The OMEGA dihedral angle between this residue and the previous. For residues + that are not amino acids, residues that do not have all atoms required or + residues that do not have bonds between the four atoms involved in the + torsion, the OMEGA torsion is an invalid handle. + + Read-only. Also available as :meth:`GetOmegaTorsion` :type: :class:`TorsionHandle` @@ -808,42 +854,98 @@ The Handle Classes :returns: Whether the switch was successful (e.g. False if no such group exists) + .. method:: GetName() + + See :attr:`name` + + .. method:: GetQualifiedName() + + See :attr:`qualified_name` + + .. method:: GetNumber() + + See :attr:`number` + + .. method:: GetOneLetterCode() + + See :attr:`one_letter_code` + .. method:: GetAtomList() See :attr:`atoms` - .. method:: IsPeptideLinking() + .. method:: GetAtomCount() - See :attr:`peptide_linking` + See :attr:`atom_count` - .. method:: IsNucleotideLinking() + .. method:: GetBondCount() + + See :attr:`bond_count` + + .. method:: GetBounds() + + See :attr:`bounds` + + .. method:: GetMass() + + See :attr:`mass` - See :attr:`nucleotide_linking` - - .. method:: GetChain() - - See :attr:`chain` - .. method:: GetCenterOfAtoms() - + See :attr:`center_of_atoms` - + .. method:: GetCenterOfMass() - + See :attr:`center_of_mass` - + + .. method:: GetGeometricCenter() + + See :attr:`geometric_center` + + .. method:: GetChain() + + See :attr:`chain` + .. method:: GetPhiTorsion() - + See :attr:`phi_torsion` - + .. method:: GetPsiTorsion() - + See :attr:`psi_torsion` - + + .. method:: GetOmegaTorsion() + + See :attr:`omega_torsion` + + .. method:: GetChemClass() + + See :attr:`chem_class` + .. method:: GetChemType() - + See :attr:`chem_type` + .. method:: GetSecStructure() + + See :attr:`sec_structure` + + .. method:: IsLigand() + + See :attr:`is_ligand` + + .. method:: IsProtein() + + See :attr:`is_protein` + + .. method:: IsPeptideLinking() + + See :attr:`peptide_linking` + + .. method:: IsNucleotideLinking() + + See :attr:`nucleotide_linking` + .. method:: GetIndex() See :attr:`index` @@ -861,10 +963,6 @@ The Handle Classes See :attr:`valid` - .. method:: IsLigand() - - See :attr:`is_ligand` - .. method:: SetIsLigand() Set the :meth:`IsLigand` flag explicitly. @@ -872,10 +970,6 @@ The Handle Classes :param ligand: Whether this residue is a ligand or not :type ligand: bool - .. method:: IsProtein() - - See :attr:`is_protein` - .. method:: SetIsProtein() Set the :meth:`IsProtein` flag explicitly. @@ -883,6 +977,14 @@ The Handle Classes :param protein: Whether this residue is a protein or not :type protein: bool + .. method:: GetNext() + + See :attr:`next` + + .. method:: GetPrev() + + See :attr:`next` + .. class:: AtomHandle @@ -900,7 +1002,7 @@ The Handle Classes .. attribute:: qualified_name - The qualified name consists of the atom name as well as a unique residue + The qualified name consists of the atom name as well as a residue identifier and chain name. For CA of a glycine with residue number 2 of chain A, the qualified name is "A.GLY2.CA". @@ -1230,6 +1332,13 @@ The View Classes An entity view represents a structural subset of an :class:`EntityHandle`. For an introduction ,see :doc:`../../intro-01`. + + .. attribute:: handle + + The underlying :class:`handle <EntityHandle>` of the entity view. Also + available as :meth:`GetHandle`. + + :type: :class:`EntityHandle` .. attribute:: chains @@ -1291,16 +1400,23 @@ The View Classes .. attribute:: bounds - Axis-aligned bounding box of the entity view. Read-only. - - :type: :class:`ost.geom.AlignedCuboid` + See :attr:`EntityHandle.bounds` - .. attribute:: handle - - The underlying :class:`handle <EntityHandle>` of the entity view. Also - available as :meth:`GetHandle`. - - :type: :class:`EntityHandle` + .. attribute:: mass + + See :attr:`EntityHandle.mass` + + .. attribute:: center_of_atoms + + See :attr:`EntityHandle.center_of_atoms` + + .. attribute:: center_of_mass + + See :attr:`EntityHandle.center_of_mass` + + .. attribute:: geometric_center + + See :attr:`EntityHandle.geometric_center` .. attribute:: valid @@ -1581,6 +1697,12 @@ The View Classes A view representation of a :class:`ChainHandle`. Mostly, the same functionality is provided as for the handle. + .. attribute:: handle + + The chain handle this view points to. Also available as :meth:`GetHandle`. + + :type: :class:`ChainHandle` + .. attribute:: name The chain name. The name uniquely identifies the chain in the entity. In @@ -1629,6 +1751,11 @@ The View Classes print(chain.residues) # [B.GLY1, B.GLY4, B.GLY3] print(chain.in_sequence) # prints false + Note that the value of `in_sequence` is independent from the value of + :attr:`ChainHandle.in_sequence`. + + :type: bool + .. attribute:: atoms Get list of all atoms of this chain. To access a single atom, use @@ -1650,38 +1777,17 @@ The View Classes :type: float - .. attribute:: center_of_mass - - Center of mass. Also available as :meth:`GetCenterOfMass` - - :type: :class:`~ost.geom.Vec3` - .. attribute:: center_of_atoms - - Center of atoms (not mass weighted). Also available as - :meth:`GetCenterOfAtoms`. - - :type: :class:`~ost.geom.Vec3` - .. attribute:: handle + See :attr:`ChainHandle.center_of_atoms` - The chain handle this view points to. Also available as :meth:`GetHandle`. - - :type: :class:`ChainHandle` - - .. attribute:: in_sequence - - Whether the residue numbers are in ascending order. Note that the value of - `in_sequence` is independent from the value of - :attr:`ChainHandle.in_sequence`. - - :type: bool + .. attribute:: center_of_mass - .. attribute:: geometric_center + See :attr:`ChainHandle.center_of_mass` - Mid-point of the axis aligned bounding box of the entity. + .. attribute:: geometric_center - :type: Vec3 + See :attr:`ChainHandle.geometric_center` .. attribute:: valid @@ -1822,63 +1928,47 @@ The View Classes :type: :class:`ResidueHandle` .. attribute:: name + qualified_name + number + one_letter_code + bounds + mass + center_of_atoms + center_of_mass + geometric_center + phi_torsion + psi_torsion + omega_torsion + chem_class + chem_type + sec_structure + is_ligand + is_protein + peptide_linking + nucleotide_linking + central_atom + central_normal + valid + next + prev + + See the respective attributes in :class:`ResidueHandle`. - The residue name is usually a str of 3 characters, e.g. `GLY` for - glycine or `ALA` for alanine, but may be shorter, e.g. `G` for guanosine, - or longer for structures loaded from formats other than PDB. - - This property is read-only. To change the name of the residue, use - :meth:`~EditorBase.RenameResidue`. - - .. attribute:: number - - The number of this residue. The residue number has a numeric part and an - insertion-code. This property is read-only. Also available as - :meth:`GetNumber`. - - :type: :class:`ResNum` - - .. attribute:: one_letter_code - - For amino acids, and nucleotides the `one_letter_code` is an alpha-numeric - character. For unknown or more *exotic* residues, the one letter code is set - to '?'. - - **Example** - - This code-snippet shows how to get the sequence string from a list of - residues. - - .. code-block:: python - - print(''.join([r.one_letter_code for r in chain.residues])) - - :type: str - - .. attribute:: bounds - - Axis-aligned bounding box of the residue view. Read-only - - :type: :class:`ost.geom.AlignedCuboid` - - .. attribute:: mass + .. attribute:: atoms - The total mass of this residue in Dalton. Also available as :meth:`GetMass`. + Get list of all atoms of this residue included in the view. + To access a single atom, use + :meth:`FindAtom`. - :type: float + This property is read-only. Also available as :meth:`GetAtomList` - .. attribute:: center_of_mass + :type: :class:`AtomViewList` (list of :class:`AtomView`) - Center of mass. Also available as :meth:`GetCenterOfMass` + .. attribute:: atom_count - :type: :class:`~ost.geom.Vec3` + Number of atoms included in the view. Read-only. See :meth:`GetAtomCount`. - .. attribute:: center_of_atoms - - Center of atoms (not mass weighted). Also available as - :meth:`GetCenterOfAtoms`. - - :type: :class:`~ost.geom.Vec3` + :type: :class:`int` .. attribute:: chain @@ -1887,21 +1977,6 @@ The View Classes :type: :class:`ChainView` - .. attribute:: handle - - The residue handle this view points to - - :type: :class:`ResidueHandle` - - .. attribute:: atoms - - Get list of all atoms of this residue. To access a single atom, use - :meth:`FindAtom`. - - This property is read-only. Also available as :meth:`GetAtomList` - - :type: :class:`AtomHandleList` (list of :class:`AtomHandle`) - .. attribute:: index Residue index (starting at 0) within chain view. @@ -1919,9 +1994,34 @@ The View Classes See :attr:`handle` - .. method:: GetMass() - - See :attr:`mass` + .. method:: GetName + GetQualifiedName + GetNumber + GetOneLetterCode + GetBounds + GetMass + GetCenterOfAtoms + GetCenterOfMass + GetGeometricCenter + GetPhiTorsion + GetPsiTorsion + GetOmegaTorsion + GetChemClass + GetChemType + GetSecStructure + IsLigand + SetIsLigand + IsProtein + IsPeptideLinking + IsNucleotideLinking + GetCentralAtom + SetCentralAtom + GetCentralNormal + IsValid + GetNext + GetPrev + + See the respective methods in :class:`ResidueHandle`. .. method:: GetChain() @@ -1936,14 +2036,6 @@ The View Classes :type atom_name: str :rtype: :class:`AtomView` - .. method:: GetIndex() - - See :attr:`index` - - .. method:: GetCenterOfMass() - - See :attr:`center_of_mass` - .. method:: IsAtomIncluded(atom_handle) Returns true if the given atom is part of the view, false if not. @@ -1952,10 +2044,6 @@ The View Classes :type atom_handle: :class:`AtomHandle` :rtype: bool - .. method:: GetGeometricCenter() - - See :attr:`geometric_center` - .. method:: AddAtom(atom_handle[, flags]) Add atom to the view. @@ -1966,13 +2054,17 @@ The View Classes :type flags: :class:`int` / :class:`ViewAddFlag` :rtype: :class:`AtomView` - .. method:: GetCenterOfAtoms() - - See :attr:`center_of_atoms` - .. method:: GetAtomList() See :attr:`atoms` + + .. method:: GetAtomCount() + + See :attr:`atom_count` + + .. method:: GetIndex() + + See :attr:`index` .. method:: Select(query, flags=0) diff --git a/modules/mol/base/pymod/export_residue.cc b/modules/mol/base/pymod/export_residue.cc index 8a6fbe99ece49ddfc6e5d2a5fb723239d69619e0..9016f9d02f209c2e3ac339be7cec631099af4b96 100644 --- a/modules/mol/base/pymod/export_residue.cc +++ b/modules/mol/base/pymod/export_residue.cc @@ -261,6 +261,7 @@ void export_Residue() .def("GetAtomCount", &ResidueHandle::GetAtomCount) .def("GetBondCount", &ResidueHandle::GetBondCount) .add_property("atom_count", &ResidueHandle::GetAtomCount) + .add_property("bond_count", &ResidueHandle::GetBondCount) .add_property("index", &ResidueHandle::GetIndex) .def("Select", select_string, arg("flags")=0) .def("Select", select_query, arg("flags")=0) diff --git a/modules/mol/base/pymod/export_residue_view.cc b/modules/mol/base/pymod/export_residue_view.cc index a3a7f16eaa232216a97b1091fd9048ff3a7e87c0..9d14320de594bb3220792085258551f9e1d82cbe 100644 --- a/modules/mol/base/pymod/export_residue_view.cc +++ b/modules/mol/base/pymod/export_residue_view.cc @@ -64,6 +64,7 @@ void export_ResidueView() .add_property("atoms", make_function(&ResidueView::GetAtomList, return_value_policy<copy_const_reference>())) + .add_property("atom_count", &ResidueView::GetAtomCount) .def("FindAtom", string_find_atom, args("atom_name")) .def("AddAtom", add_atom_handle, X_add_atom_overloads(args("atom_handle", "flags"))) .def("AddAtom", add_atom_view, X_add_atom_overloads(args("atom_view", "flags")))