diff --git a/modules/conop/pymod/CMakeLists.txt b/modules/conop/pymod/CMakeLists.txt
index b6db07509ddd80aff7049d6c411543fb8d0f9dee..9d38418097bcc8df02ffb148e96ffc9659483bb5 100644
--- a/modules/conop/pymod/CMakeLists.txt
+++ b/modules/conop/pymod/CMakeLists.txt
@@ -4,6 +4,7 @@ set(OST_CONOP_PYMOD_SOURCES
export_compound.cc
export_sanitizer.cc
export_conop.cc
+ export_ring_finder.cc
)
pymod(NAME conop CPP ${OST_CONOP_PYMOD_SOURCES} PY __init__.py)
\ No newline at end of file
diff --git a/modules/conop/pymod/export_ring_finder.cc b/modules/conop/pymod/export_ring_finder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5a02f498660998742e1e076661bd08aec2e478ae
--- /dev/null
+++ b/modules/conop/pymod/export_ring_finder.cc
@@ -0,0 +1,36 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2010 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 <boost/python.hpp>
+#include <boost/python/register_ptr_to_python.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+using namespace boost::python;
+#include <ost/conop/ring_finder.hh>
+#include <ost/mol/mol.hh>
+
+using namespace ost::conop;
+
+void export_RingFinder() {
+ class_<RingFinder, boost::noncopyable>("RingFinder", init<ost::mol::EntityHandle&>())
+ .def("PerceiveRings", &RingFinder::PerceiveRings)
+ .def("GetRings", &RingFinder::GetRings)
+ .def("GetRingAtomCount", &RingFinder::GetRingAtomCount)
+ .def("GetRingBondCount", &RingFinder::GetRingBondCount)
+ .def("RingsPerceived", &RingFinder::RingsPerceived)
+ ;
+}
diff --git a/modules/conop/pymod/wrap_conop.cc b/modules/conop/pymod/wrap_conop.cc
index 6dfad9d71c48440fae4d49db9e75800956b2a18f..cb7915c94b004355131618118a9b049b77e40817 100644
--- a/modules/conop/pymod/wrap_conop.cc
+++ b/modules/conop/pymod/wrap_conop.cc
@@ -23,10 +23,12 @@ void export_Builder();
void export_Compound();
void export_Sanitizer();
void export_Conop();
+void export_RingFinder();
BOOST_PYTHON_MODULE(_conop)
{
export_Builder();
export_Conop();
export_Compound();
export_Sanitizer();
+ export_RingFinder();
}
diff --git a/modules/conop/src/CMakeLists.txt b/modules/conop/src/CMakeLists.txt
index 038c51efa70f1ebfcb59784c3e16d4409a9d70a2..fbf0a48be9b3aa69946da25925ad0f702af9f533 100644
--- a/modules/conop/src/CMakeLists.txt
+++ b/modules/conop/src/CMakeLists.txt
@@ -8,6 +8,7 @@ sanitizer.hh
compound_lib.hh
module_config.hh
rule_based_builder.hh
+ring_finder.hh
)
set(OST_CONOP_SOURCES
@@ -18,6 +19,7 @@ compound.cc
sanitizer.cc
compound_lib.cc
rule_based_builder.cc
+ring_finder.cc
)
module(NAME conop SOURCES ${OST_CONOP_SOURCES}
diff --git a/modules/conop/src/ring_finder.cc b/modules/conop/src/ring_finder.cc
new file mode 100755
index 0000000000000000000000000000000000000000..144d140472a8b2813d841fa9da6cd169fd56c88a
--- /dev/null
+++ b/modules/conop/src/ring_finder.cc
@@ -0,0 +1,126 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2010 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 "ring_finder.hh"
+
+namespace ost { namespace conop {
+ RingFinder::RingFinder(mol::EntityHandle &eh) :
+ ent_(eh), rings_perceived_(false)
+ {}
+
+ void RingFinder::PerceiveRings()
+ {
+ mol::AtomHandleList ahl=ent_.GetAtomList();
+ for (mol::AtomHandleList::iterator i=ahl.begin();i!=ahl.end();++i) {
+ if (i->IsValid()) {
+ if (! i->HasGenericProperty("RFvisited")) {
+ // start ring search from each unvisited atom (e.g. if there are
+ // multiple unconnected fragments)
+ VisitNext((*i), (*i));
+ }
+ }
+ }
+ rings_perceived_=true;
+ }
+
+ int RingFinder::GetRingAtomCount()
+ {
+ if(!ring_view_.IsValid()) {
+ GetRings();
+ }
+ return ring_view_.GetAtomCount();
+ }
+
+ int RingFinder::GetRingBondCount()
+ {
+ if(!ring_view_.IsValid()) {
+ GetRings();
+ }
+ return ring_view_.GetBondCount();
+ }
+
+ bool RingFinder::RingsPerceived() {
+ return rings_perceived_;
+ }
+
+ mol::EntityView RingFinder::GetRings()
+ {
+ if (!rings_perceived_) {
+ PerceiveRings();
+ }
+ if (!ring_view_.IsValid()) {
+ mol::EntityView view=ent_.CreateEmptyView();
+ mol::AtomHandleList ahl=ent_.GetAtomList();
+ for (mol::AtomHandleList::iterator i=ahl.begin();i!=ahl.end();++i) {
+ if (i->HasGenericProperty("RFinring")) {
+ view.AddAtom(*i);
+ }
+ }
+ mol::BondHandleList bhl=ent_.GetBondList();
+ for (mol::BondHandeList::const_iterator j=bhl.begin();j!=bhl.end();++j) {
+ if (j->HasGenericProperty("RFinring")) {
+ view.AddBond(*j);
+ }
+ }
+ ring_view_=view;
+ }
+
+ return ring_view_;
+ }
+
+ std::map<long int,bool> RingFinder::VisitNext(mol::AtomHandle &curr,
+ mol::AtomHandle &prev)
+ {
+ std::map<long int,bool> ring_closings; // map for atom hashcode
+
+ curr.SetGenericBoolProperty("RFvisited",true);
+ mol::AtomHandleList bp=curr.GetBondPartners();
+ for (mol::AtomHandleList::iterator i=bp.begin(); i!=bp.end(); ++i) {
+ if ((*i)==prev) {
+ // do not visit last visited atom
+ continue;
+ }
+ mol::BondHandle b=curr.FindBondToAtom(*i);
+ if (b.HasGenericProperty("RFvisited")) {
+ // do not go along previously visited bonds
+ continue;
+ }
+ b.SetGenericBoolProperty("RFvisited", true);
+ if (i->HasGenericProperty("RFvisited")) {
+ // we have found a ring
+ ring_closings[i->GetHashCode()]=true;
+ b.SetGenericBoolProperty("RFinring", true);
+ } else {
+ // no ring yet - continue to next atom
+ std::map<long int,bool> next_ring_closings=VisitNext((*i),curr);
+ // back from the recursion
+ if (next_ring_closings.size()>0) {
+ b.SetGenericBoolProperty("RFinring", true);
+ ring_closings.insert(next_ring_closings.begin(),next_ring_closings.end());
+ }
+ }
+ }
+ if (ring_closings.size()>0) {
+ // if current atom is in the ring closing list, remove it
+ curr.SetGenericBoolProperty("RFinring", true);
+ ring_closings.erase(curr.GetHashCode());
+ }
+ return ring_closings;
+ }
+
+}}
diff --git a/modules/conop/src/ring_finder.hh b/modules/conop/src/ring_finder.hh
new file mode 100755
index 0000000000000000000000000000000000000000..309e5ff55510f6a40a7142b57b96a5fc0edd4b49
--- /dev/null
+++ b/modules/conop/src/ring_finder.hh
@@ -0,0 +1,76 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2010 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
+//------------------------------------------------------------------------------
+#ifndef OST_CONOP_RING_FINDER_HH
+#define OST_CONOP_RING_FINDER_HH
+
+/*
+ Author: Tobias Schmidt
+ */
+
+#include <ost/conop/module_config.hh>
+#include <ost/mol/mol.hh>
+#include <map>
+
+namespace ost { namespace conop {
+
+/// \brief Class for finding rings in an entity
+///
+/// This is an implementation of a depth first search based method to identify
+/// all atoms and bonds belonging to rings in an entity. The time complexity is
+/// linear. The search for rings is only carried out once and the ring
+/// information is stored in generic properties in the entity and it can be
+/// obtained as an EntityView.
+class DLLEXPORT_OST_CONOP RingFinder {
+public:
+ RingFinder(mol::EntityHandle &eh);
+public:
+
+ /// \brief Walk along the path of the entity in a depth first search and
+ /// identify atoms and bonds which are in rings
+ ///
+ /// For all atoms and bonds, belonging to a ring, the GenericBoolProperty
+ /// RFinring is set to true. The search for rings is only carried out once.
+ /// This method does not need to be called explicitly, it will be
+ /// automatically called if the rings have not yet been identified.
+ void PerceiveRings();
+
+ /// \brief Get an EntityView, containing all atoms and bonds belonging to
+ /// rings
+ mol::EntityView GetRings();
+
+ /// \brief Get number of atoms belonging to rings
+ int GetRingAtomCount();
+
+ /// \brief Get number of bonds belonging to rings
+ int GetRingBondCount();
+
+ /// \brief Check if rings have been perceived
+ bool RingsPerceived();
+
+private:
+ std::map<long int,bool> VisitNext(mol::AtomHandle &curr,
+ mol::AtomHandle &prev);
+ mol::EntityHandle ent_;
+ mol::EntityView ring_view_;
+ bool rings_perceived_;
+};
+
+}}
+
+#endif