From 2f14bd9732ebdef18712ae85e8c63d87239716df Mon Sep 17 00:00:00 2001 From: Gabriel Studer <gabriel.studer@unibas.ch> Date: Mon, 27 May 2019 11:54:04 +0200 Subject: [PATCH] Editor functionality to delete residues/chains that don't contain any atoms --- modules/mol/base/doc/editors.rst | 4 ++ modules/mol/base/pymod/export_editors.cc | 1 + modules/mol/base/src/editor_base.cc | 16 +++++++ modules/mol/base/src/editor_base.hh | 5 +++ modules/mol/base/tests/test_entity.cc | 53 ++++++++++++++++++++++++ 5 files changed, 79 insertions(+) diff --git a/modules/mol/base/doc/editors.rst b/modules/mol/base/doc/editors.rst index a5f31e8be..cc3846a71 100644 --- a/modules/mol/base/doc/editors.rst +++ b/modules/mol/base/doc/editors.rst @@ -360,6 +360,10 @@ The basic functionality of editors is implemented in the EditorBase class. :type atom2: :class:`AtomHandle` :param bond_order: bond order (e.g. 1=single, 2=double, 3=triple) :type bond_order: :class:`int` + + .. method:: Prune() + + Removes residues and chains that don't contain any atoms. Editor for the External Coordinate System diff --git a/modules/mol/base/pymod/export_editors.cc b/modules/mol/base/pymod/export_editors.cc index cd7b326fd..4bb64bd8a 100644 --- a/modules/mol/base/pymod/export_editors.cc +++ b/modules/mol/base/pymod/export_editors.cc @@ -267,6 +267,7 @@ void export_Editors() .def("RenumberAllResidues",&EditorBase::RenumberAllResidues) .def("RenumberChain",renumber_chain_a) .def("RenumberChain",renumber_chain_b) + .def("Prune", &EditorBase::Prune) ; void (XCSEditor::*apply_transform1)(const geom::Mat4&) = &XCSEditor::ApplyTransform; diff --git a/modules/mol/base/src/editor_base.cc b/modules/mol/base/src/editor_base.cc index 364ea0be0..fcc5bd330 100644 --- a/modules/mol/base/src/editor_base.cc +++ b/modules/mol/base/src/editor_base.cc @@ -298,6 +298,22 @@ TorsionHandle EditorBase::AddTorsion(const String& name, const AtomHandle& a1, a3.Impl(), a4.Impl())); } +void EditorBase::Prune() { + ost::mol::ResidueHandleList res_list = ent_.GetResidueList(); + for(ost::mol::ResidueHandleList::iterator it = res_list.begin(); + it != res_list.end(); ++it) { + if(it->GetAtomCount() == 0) { + this->DeleteResidue(*it); + } + } + ost::mol::ChainHandleList chain_list = ent_.GetChainList(); + for(ost::mol::ChainHandleList::iterator it = chain_list.begin(); + it != chain_list.end(); ++it) { + if(it->GetResidueCount() == 0) { + this->DeleteChain(*it); + } + } +} void EditorBase::UpdateTrace() { diff --git a/modules/mol/base/src/editor_base.hh b/modules/mol/base/src/editor_base.hh index c45036072..22ca4a561 100644 --- a/modules/mol/base/src/editor_base.hh +++ b/modules/mol/base/src/editor_base.hh @@ -328,6 +328,11 @@ public: /// \brief change the name of the atom to the new name void RenameAtom(AtomHandle atom, const String& new_name); + + /// \brief Removes all residues and chains in the attached entity that don't + /// contain any atoms + void Prune(); + protected: EditorBase(const EntityHandle& ent, EditMode mode); void UpdateTrace(); diff --git a/modules/mol/base/tests/test_entity.cc b/modules/mol/base/tests/test_entity.cc index 89b6349be..cab0efe69 100644 --- a/modules/mol/base/tests/test_entity.cc +++ b/modules/mol/base/tests/test_entity.cc @@ -441,4 +441,57 @@ BOOST_AUTO_TEST_CASE(minmax) BOOST_CHECK_EQUAL(minmax.second, 7.0); } +BOOST_AUTO_TEST_CASE(prune) { + EntityHandle ent=mol::CreateEntity(); + XCSEditor edi = ent.EditXCS(); + + ChainHandle ch1 = edi.InsertChain("A"); + ChainHandle ch2 = edi.InsertChain("B"); + + ResidueHandle res1_1 = edi.AppendResidue(ch1, "DUMMY"); + ResidueHandle res1_2 = edi.AppendResidue(ch1, "DUMMY"); + AtomHandle atom1_1_1 = edi.InsertAtom(res1_1, "X", geom::Vec3(1,2,3), "C"); + AtomHandle atom1_2_1 = edi.InsertAtom(res1_2, "X", geom::Vec3(1,2,3), "C"); + + ResidueHandle res2_1 = edi.AppendResidue(ch2, "DUMMY"); + ResidueHandle res2_2 = edi.AppendResidue(ch2, "DUMMY"); + AtomHandle atom2_1_1 = edi.InsertAtom(res2_1, "X", geom::Vec3(1,2,3), "C"); + AtomHandle atom2_2_1 = edi.InsertAtom(res2_2, "X", geom::Vec3(1,2,3), "C"); + + BOOST_CHECK_EQUAL(ent.GetChainCount(), 2); + BOOST_CHECK_EQUAL(ent.GetResidueCount(), 4); + BOOST_CHECK_EQUAL(ent.GetAtomCount(), 4); + + // shouldn't do anything + edi.Prune(); + BOOST_CHECK_EQUAL(ent.GetChainCount(), 2); + BOOST_CHECK_EQUAL(ent.GetResidueCount(), 4); + BOOST_CHECK_EQUAL(ent.GetAtomCount(), 4); + + // remove one atom, the subsequent prune call should then remove the + // according residue but the number of chains should remain the same + edi.DeleteAtom(atom1_1_1); + edi.Prune(); + BOOST_CHECK_EQUAL(ent.GetChainCount(), 2); + BOOST_CHECK_EQUAL(ent.GetResidueCount(), 3); + BOOST_CHECK_EQUAL(ent.GetAtomCount(), 3); + + // remove the second atom from the first chain, the whole chain should then + // be removed by Prune + edi.DeleteAtom(atom1_2_1); + edi.Prune(); + BOOST_CHECK_EQUAL(ent.GetChainCount(), 1); + BOOST_CHECK_EQUAL(ent.GetResidueCount(), 2); + BOOST_CHECK_EQUAL(ent.GetAtomCount(), 2); + + // remove both residues from the second chain. The entity should be empty + // afterwards + edi.DeleteResidue(res2_1); + edi.DeleteResidue(res2_2); + edi.Prune(); + BOOST_CHECK_EQUAL(ent.GetChainCount(), 0); + BOOST_CHECK_EQUAL(ent.GetResidueCount(), 0); + BOOST_CHECK_EQUAL(ent.GetAtomCount(), 0); +} + BOOST_AUTO_TEST_SUITE_END(); -- GitLab