From 1c0a6a7404f833fce6f0e8d08c8515b7e93b9995 Mon Sep 17 00:00:00 2001 From: Stefan Bienert <stefan.bienert@unibas.ch> Date: Thu, 12 May 2011 15:19:51 +0200 Subject: [PATCH] Fixed bug BZDNG-212 (RenameResidue(ResidueHandle, new_name) is missing in EditorBase), added documentation for Rename[Atom|Chain|Residue] functions as well as unit tests. Made some tests compatible with Python 2.4. --- modules/bindings/tests/test_blast.py | 4 +- modules/bindings/tests/test_clustalw.py | 4 +- modules/doc/newmodule.rst | 2 +- modules/mol/base/doc/editors.rst | 55 +++++++++++++++++++----- modules/mol/base/pymod/export_editors.cc | 2 + modules/mol/base/src/editor_base.cc | 6 +++ modules/mol/base/src/editor_base.hh | 2 + modules/mol/base/tests/test_chain.cc | 11 ++++- modules/mol/base/tests/test_entity.cc | 10 +++++ modules/mol/base/tests/test_residue.cc | 10 +++++ modules/seq/alg/tests/test_renumber.py | 4 +- 11 files changed, 91 insertions(+), 19 deletions(-) diff --git a/modules/bindings/tests/test_blast.py b/modules/bindings/tests/test_blast.py index 2b42bfd18..e8e151a4e 100644 --- a/modules/bindings/tests/test_blast.py +++ b/modules/bindings/tests/test_blast.py @@ -43,8 +43,8 @@ if __name__ == "__main__": blastpath=settings.Locate('blastall') except(settings.FileNotFound): print "Could not find blastall executable: ignoring unit tests" - exit(0) + sys.exit(0) try: unittest.main() except Exception, e: - print e \ No newline at end of file + print e diff --git a/modules/bindings/tests/test_clustalw.py b/modules/bindings/tests/test_clustalw.py index 0536df8f7..0fdb040db 100644 --- a/modules/bindings/tests/test_clustalw.py +++ b/modules/bindings/tests/test_clustalw.py @@ -67,8 +67,8 @@ if __name__ == "__main__": clustalw_path=settings.Locate(('clustalw', 'clustalw2')) except(settings.FileNotFound): print "Could not find clustalw executable: ignoring unit tests" - exit(0) + sys.exit(0) try: unittest.main() except Exception, e: - print e \ No newline at end of file + print e diff --git a/modules/doc/newmodule.rst b/modules/doc/newmodule.rst index beca4c215..7a1ad3f32 100644 --- a/modules/doc/newmodule.rst +++ b/modules/doc/newmodule.rst @@ -200,7 +200,7 @@ The definition of the actual unit tests is done in separate .cc files. Create th BOOST_AUTO_TEST_SUITE_END() -We again have to define the BOOST_TEST_DYN_LINK macro before including the bosot unit test headers. This will tell the boost unit test libraries that we intend to use dynamic linking. Then we include the functions and classes we would like to write unit tests for. In this file, all the normal Boost Test Library macros and functions can be used. (For example `BOOST_CHECK`, `BOOST_FAIL`, etc.) +We again have to define the BOOST_TEST_DYN_LINK macro before including the boost unit test headers. This will tell the boost unit test libraries that we intend to use dynamic linking. Then we include the functions and classes we would like to write unit tests for. In this file, all the normal Boost Test Library macros and functions can be used. (For example `BOOST_CHECK`, `BOOST_FAIL`, etc.) Here is finally the build script skeleton that needs to be put into `mod/tests/`: diff --git a/modules/mol/base/doc/editors.rst b/modules/mol/base/doc/editors.rst index c9b78b26b..02a97514e 100644 --- a/modules/mol/base/doc/editors.rst +++ b/modules/mol/base/doc/editors.rst @@ -22,12 +22,12 @@ following happens: explicitly. -The editors follow the RIAA (resource allocation is initialisation) principle: +The editors follow the RIAA (resource allocation is initialization) principle: Whenever an editor is requested an internal reference counter is incremented. In the destructor, this reference count is decremented. When the count drops to -zero, the dependent infomation is updated. +zero, the dependent information is updated. -In Python, one can not rely on the destructors being called. It is adviced to +In Python, one can not rely on the destructors being called. It is advised to always put a call to :meth:`XCSEditor.UpdateICS` or :meth:`ICSEditor.UpdateXCS` when the editing is finished. Alternatively, starting from Python version 2.6, one can use the \ @@ -66,7 +66,30 @@ The basic functionality of editors is implemented in the EditorBase class. :param residue_name: 3-letter-code of the residue, e.g. ``GLY``. :type residue_name: string :returns: :class:`ResidueHandle` - + + .. method:: RenameResidue(residue, new_name) + + Change the name of residue to new_name. Just overwrites the 3-letter-code + without changing anything else. Be aware that the sequence/ 1-letter-code + will not change automatically. + + :param residue: Must be a valid residue + :type residue: :class:`ResidueHandle` + :param new_name: is the new name. Free to choose and not verified to be a + valid identifier. + :type new_name: string + + .. method:: RenameChain(chain, new_name) + + Change the name of a chain to new_name while avoiding duplicated + identifiers. If new_name is already in use by any chain, an exception will + be generated. + + :param chain: Must be a valid chain + :type residue: :class:`ChainHandle` + :param new_name: is the new name + :type new_name: string + .. method:: InsertAtom(residue, atom_name, pos, element="", occupancy=1.0, b_factor=0.0, is_hetatm=False) @@ -81,7 +104,7 @@ The basic functionality of editors is implemented in the EditorBase class. :param residue: is the parent residue and must be valid :type residue: :class:`ResidueHandle` :param atom_name: is the atom name. While free to choose a name, it is - adviced to properly name the atoms according to IUPAC + advised to properly name the atoms according to IUPAC rules as several algorithms as well as most :class:`builders <conop.Builder>` in the :mod:`conop` module rely on proper naming. @@ -168,14 +191,24 @@ The basic functionality of editors is implemented in the EditorBase class. :param chain: `A valid chain` :type chain: :class:`ChainHandle` - + + .. method:: RenameAtom(atom, new_name) + + Change the name of atom to new_name without changing anything else. + + :param residue: Must be a valid atom + :type residue: :class:`AtomHandle` + :param new_name: is the new name. Free to choose and not verified to be a + valid atom identifier. + :type new_name: string + Editor for the External Coordinate System -------------------------------------------------------------------------------- The XCSEditor defines the interface for manipulating the external coordinate system. The external coordinate system directly operates on atom positions in -euclidian space. +Euclidian space. .. class:: XCSEditor @@ -209,7 +242,7 @@ euclidian space. .. method:: SetOriginalAtomPos(atom, pos) - Set the origininal (untransformed) position of the atom. This method will + Set the original (untransformed) position of the atom. This method will also update the transformed position by applying the entity transform to the original pos. @@ -231,7 +264,7 @@ using an :class:`ICSEditor` is undefined and vice versa. .. note:: - For speed reasons, the internal coordinate system is not initialised until the + For speed reasons, the internal coordinate system is not initialized until the first call to :meth:`EntityHandle.EditICS`. This involves the build-up of a directed-graph for the bond network as well as calculating the internal coordinate matrices. @@ -277,7 +310,7 @@ using an :class:`ICSEditor` is undefined and vice versa. :type bond: :class:`BondHandle` - :param length: The bond length in Angstroem. + :param length: The bond length in Angstrom. :type length: :class:`float` @@ -304,4 +337,4 @@ using an :class:`ICSEditor` is undefined and vice versa. :param angle: The angle in radians :raises: :exc:`RuntimeError` when one of the atoms is invalid or there is no - bond between atom1 and atom2 or atom2 and atom3. \ No newline at end of file + bond between atom1 and atom2 or atom2 and atom3. diff --git a/modules/mol/base/pymod/export_editors.cc b/modules/mol/base/pymod/export_editors.cc index 9976b0d8f..0b469fec3 100644 --- a/modules/mol/base/pymod/export_editors.cc +++ b/modules/mol/base/pymod/export_editors.cc @@ -76,6 +76,8 @@ void export_Editors() .def("Connect", connect_c) .def("Connect", connect_d) .def("RenameChain", &EditorBase::RenameChain) + .def("RenameResidue", &EditorBase::RenameResidue) + .def("RenameAtom", &EditorBase::RenameAtom) .def("AddTorsion", &EditorBase::AddTorsion) .def("ReorderResidues",&EditorBase::ReorderResidues) .def("ReorderAllResidues",&EditorBase::ReorderAllResidues) diff --git a/modules/mol/base/src/editor_base.cc b/modules/mol/base/src/editor_base.cc index 01eaf549d..c5eed6d60 100644 --- a/modules/mol/base/src/editor_base.cc +++ b/modules/mol/base/src/editor_base.cc @@ -70,6 +70,12 @@ ResidueHandle EditorBase::InsertResidueAfter(ChainHandle chain, int index, return ResidueHandle(chain.Impl()->InsertResidueAfter(index, num, k)); } +void EditorBase::RenameResidue(ResidueHandle res, const String& new_name) +{ + CheckHandleValidity(res); + res.Impl()->SetKey(new_name); +} + void EditorBase::RenameChain(ChainHandle chain, const String& new_name) { CheckHandleValidity(chain); diff --git a/modules/mol/base/src/editor_base.hh b/modules/mol/base/src/editor_base.hh index fd6c63d2a..e9409ecd3 100644 --- a/modules/mol/base/src/editor_base.hh +++ b/modules/mol/base/src/editor_base.hh @@ -152,6 +152,8 @@ public: Real len, Real theta, Real phi, unsigned char bond_order); + void RenameResidue(ResidueHandle res, const String& new_name); + void RenameChain(ChainHandle chain, const String& new_name); /// \brief Delete all atoms of residue /// diff --git a/modules/mol/base/tests/test_chain.cc b/modules/mol/base/tests/test_chain.cc index 2b1d7a932..a0fd47ba3 100644 --- a/modules/mol/base/tests/test_chain.cc +++ b/modules/mol/base/tests/test_chain.cc @@ -187,4 +187,13 @@ BOOST_AUTO_TEST_CASE(prev_next) BOOST_CHECK(!ch1.GetNext(ResidueHandle()).IsValid()); } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_CASE(rename_chain) +{ + EntityHandle eh=CreateEntity(); + XCSEditor e=eh.EditXCS(); + ChainHandle ch1=e.InsertChain("A"); + e.RenameChain(ch1, "B"); + BOOST_CHECK_EQUAL(ch1.GetName(), "B"); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/mol/base/tests/test_entity.cc b/modules/mol/base/tests/test_entity.cc index 1113e23f1..944dd6809 100644 --- a/modules/mol/base/tests/test_entity.cc +++ b/modules/mol/base/tests/test_entity.cc @@ -401,5 +401,15 @@ BOOST_AUTO_TEST_CASE(copy_atom_props) BOOST_CHECK_EQUAL(atom2.GetRadius(), Real(500.0)); } +BOOST_AUTO_TEST_CASE(rename_atom) +{ + EntityHandle ent=CreateEntity(); + XCSEditor edi=ent.EditXCS(); + ChainHandle ch1=edi.InsertChain("A"); + ResidueHandle res = edi.AppendResidue(ch1, "A"); + AtomHandle atom=edi.InsertAtom(res, "A", geom::Vec3(1,2,3), "C"); + edi.RenameAtom(atom, "B"); + BOOST_CHECK_EQUAL(atom.GetName(), "B"); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/mol/base/tests/test_residue.cc b/modules/mol/base/tests/test_residue.cc index 351723b1c..6cc900c62 100644 --- a/modules/mol/base/tests/test_residue.cc +++ b/modules/mol/base/tests/test_residue.cc @@ -114,4 +114,14 @@ BOOST_AUTO_TEST_CASE(test_res_index) BOOST_CHECK_EQUAL(rvC.GetIndex(),cv1.GetResidueIndex(rvC.GetNumber())); } +BOOST_AUTO_TEST_CASE(rename_res) +{ + EntityHandle eh=CreateEntity(); + XCSEditor e=eh.EditXCS(); + ChainHandle ch1=e.InsertChain("A"); + ResidueHandle rA2B = e.AppendResidue(ch1, "A"); + e.RenameResidue(rA2B, "B"); + BOOST_CHECK_EQUAL(rA2B.GetName(), "B"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/seq/alg/tests/test_renumber.py b/modules/seq/alg/tests/test_renumber.py index 6d365a9b7..76a9bf1d1 100644 --- a/modules/seq/alg/tests/test_renumber.py +++ b/modules/seq/alg/tests/test_renumber.py @@ -117,8 +117,8 @@ if __name__ == "__main__": clustalw_path=settings.Locate(('clustalw', 'clustalw2')) except(settings.FileNotFound): print "Could not find clustalw executable: ignoring unit tests" - exit(0) + sys.exit(0) try: unittest.main() except Exception, e: - print e \ No newline at end of file + print e -- GitLab