Open Babel: mol_graph.h Source File

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Examples

- File List
- File Members

# mol_graph.h

Go to the documentation of this file.

    00001 /**********************************************************************
    00002 mol_graph.h - interface with Boost Graph Library.
    00003
    00004 Copyright (C) 2007 by Gerde Menche
    00005
    00006 This file is part of the Open Babel project.
    00007 For more information, see <http://openbabel.org/>
    00008
    00009 This program is free software; you can redistribute it and/or modify
    00010 it under the terms of the GNU General Public License as published by
    00011 the Free Software Foundation version 2 of the License.
    00012
    00013 This program is distributed in the hope that it will be useful,
    00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00016 GNU General Public License for more details.
    00017 ***********************************************************************/
    00018
    00019 #ifndef MOL_GRAPH_H
    00020 #define MOL_GRAPH_H
    00021
    00022 #include <boost/graph/graph_traits.hpp>
    00023 #include <boost/shared_ptr.hpp> // OBAtomMap, OBBondMap
    00024 #include <boost/property_map.hpp> // OBAtomMap, OBBondMap
    00025 #include <boost/graph/visitors.hpp> // functor_caller, recorder
    00026
    00027 #include"openbabel/mol.h"
    00028
    00029 namespace boost // cannot specialize boost::graph_traits outside namespace
    00030 {
    00031    //  There is a bunch of functions in the BGL modifying the structure
    00032    //  of the graph -- like inserting or deleting vertices or edges. None of
    00033    //  these will be implemented here.
    00034
    00035   struct obmol_traversal_tag :
    00036
    00037    //  For the purpose of the "tag classes" and the ideas behind design
    00038    //  and implementation of the Boost Graph Library see
    00039    //  The Boost Graph Library User and Reference Manual (TBGL)
    00040    //  by Siek, Lee and Lumsdaine or
    00041    //  www.boost.org/libs/graph/doc/table_of_contents.html
    00042
    00043     public virtual incidence_graph_tag,
    00044     public virtual edge_list_graph_tag,
    00045     public virtual vertex_list_graph_tag {};
    00046
    00047   template<>
    00048   struct graph_traits< OpenBabel::OBMol >
    00049   {
    00050
    00051     typedef obmol_traversal_tag  traversal_category;
    00052     typedef undirected_tag       directed_category;
    00053     typedef disallow_parallel_edge_tag edge_parallel_category;
    00054     typedef OpenBabel::OBAtom*   vertex_descriptor;
    00055
    00056     typedef int   vertices_size_type;
    00057     typedef int   edges_size_type;
    00058     typedef int   degree_size_type;
    00059     typedef OpenBabel::OBAtomIterator  vertex_iterator;
    00060     typedef OpenBabel::OBBondIterator  edge_iterator;
    00061
    00062     class edge_descriptor
    00063     {
    00064         OpenBabel::OBBond* bond;
    00065         bool begin_is_source; // a dereferenced out_edge_iterator
    00066                               // is required to know its source and target
    00067                               // vertex, so we keep track in a bool variable
    00068       public:
    00069         edge_descriptor( OpenBabel::OBBond* a = 0, bool b = true )
    00070         :  bond(a), begin_is_source(b) {}
    00071         OpenBabel::OBBond* operator->() { return bond; }
    00072         OpenBabel::OBBond& operator*()  { return *bond; }
    00073         vertex_descriptor source()
    00074         {
    00075             if ( begin_is_source ) return bond->GetBeginAtom();
    00076             return bond->GetEndAtom();
    00077         }
    00078         vertex_descriptor target()
    00079         {
    00080             if ( begin_is_source ) return bond->GetEndAtom();
    00081             return bond->GetBeginAtom();
    00082         }
    00083         // this function is to hide the edge_descriptor class
    00084         // from users of the obmol BGL interface
    00085         operator OpenBabel::OBBond*()  { return bond; }
    00086     };
    00087
    00088     class adjacent_iterator
    00089     {
    00090         OpenBabel::OBBondIterator ip_bond;
    00091         OpenBabel::OBAtom* p_atom;
    00092       public :
    00093         typedef std::forward_iterator_tag iterator_category;
    00094         typedef OpenBabel::OBAtom*  value_type;
    00095         typedef OpenBabel::OBAtom** pointer;
    00096         typedef OpenBabel::OBBondIterator::difference_type difference_type;
    00097         typedef OpenBabel::OBBondIterator::reference       reference;
    00098
    00099         adjacent_iterator () {};
    00100         adjacent_iterator( OpenBabel::OBBondIterator i, OpenBabel::OBAtom* a ) :
    00101             ip_bond(i), p_atom(a) {}
    00102         adjacent_iterator( const adjacent_iterator& i ) :
    00103             ip_bond(i.ip_bond), p_atom(i.p_atom) {}
    00104         adjacent_iterator& operator++() { ++ip_bond; return *this; }
    00105         adjacent_iterator  operator++(int)
    00106                { adjacent_iterator tmp(ip_bond,p_atom); ++ip_bond; return tmp; }
    00107         bool operator==( const adjacent_iterator& rhs )
    00108             { return ip_bond == rhs.ip_bond; }
    00109         bool operator!=( const adjacent_iterator& rhs ) { return !(*this == rhs); }
    00110         vertex_descriptor operator*() { return (*ip_bond)->GetNbrAtom(p_atom); }
    00111     };
    00112
    00113     class out_edge_iterator
    00114     {
    00115         OpenBabel::OBBondIterator ip_bond;
    00116         OpenBabel::OBAtom* p_atom; // source OBAtom*
    00117       public :
    00118         typedef std::forward_iterator_tag iterator_category;
    00119         typedef edge_descriptor value_type;
    00120         typedef edge_descriptor* pointer;
    00121         typedef OpenBabel::OBBondIterator::difference_type difference_type;
    00122         typedef OpenBabel::OBBondIterator::reference       reference;
    00123
    00124         out_edge_iterator () {};
    00125         out_edge_iterator( const out_edge_iterator& i ) :
    00126             ip_bond(i.ip_bond), p_atom(i.p_atom) {}
    00127         out_edge_iterator( OpenBabel::OBBondIterator i, OpenBabel::OBAtom* a ) :
    00128             ip_bond(i), p_atom(a) {}
    00129         out_edge_iterator& operator++() { ++ip_bond; return *this; }
    00130         out_edge_iterator  operator++(int)
    00131                    { out_edge_iterator tmp(ip_bond,p_atom); ++ip_bond; return tmp; }
    00132         bool operator==( const out_edge_iterator& rhs )
    00133             { return ip_bond == rhs.ip_bond; }
    00134         bool operator!=( const out_edge_iterator& rhs ) { return !(*this == rhs); }
    00135         edge_descriptor operator*()
    00136         {
    00137             // this is why we need to keep track of the source atom
    00138             return edge_descriptor(*ip_bond,(*ip_bond)->GetBeginAtom() == p_atom);
    00139         }
    00140     };
    00141
    00142   };
    00143
    00144   std::pair < graph_traits< OpenBabel::OBMol >::edge_iterator,
    00145               graph_traits< OpenBabel::OBMol >::edge_iterator >
    00146   edges( const OpenBabel::OBMol& m )
    00147   {
    00148       // Now that cast is ugly: but m.BeginBonds() violates
    00149       // the const qualifier of the argument
    00150       // and this is the signature imposed by BGL.
    00151       // A better solution would be very welcome
    00152       // propably a ConstOBBondIterator
    00153       OpenBabel::OBMol* mol = const_cast< OpenBabel::OBMol* >(&m);
    00154       return std::make_pair(mol->BeginBonds(),mol->EndBonds());
    00155   }
    00156
    00157   std::pair < graph_traits< OpenBabel::OBMol >::vertex_iterator,
    00158               graph_traits< OpenBabel::OBMol >::vertex_iterator >
    00159   vertices( const OpenBabel::OBMol& m )
    00160   {
    00161       // Now that cast is ugly: but m.BeginAtoms() violates
    00162       // the const qualifier of the argument
    00163       // and this is the signature imposed by BGL.
    00164       // A better solution would be very welcome
    00165       // propably a ConstOBAtomIterator
    00166       OpenBabel::OBMol* mol = const_cast< OpenBabel::OBMol* >(&m);
    00167       return std::make_pair(mol->BeginAtoms(),mol->EndAtoms());
    00168   }
    00169
    00170   std::pair < graph_traits< OpenBabel::OBMol >::adjacent_iterator,
    00171               graph_traits< OpenBabel::OBMol >::adjacent_iterator >
    00172   adjacent_vertices ( graph_traits< OpenBabel::OBMol >::vertex_descriptor& v,
    00173                       const OpenBabel::OBMol& )
    00174   {
    00175       return std::make_pair(
    00176       graph_traits< OpenBabel::OBMol >::adjacent_iterator(v->BeginBonds(),v),
    00177       graph_traits< OpenBabel::OBMol >::adjacent_iterator(v->EndBonds()  ,v) );
    00178   }
    00179
    00180   graph_traits< OpenBabel::OBMol >::vertex_descriptor
    00181   source( graph_traits< OpenBabel::OBMol >::edge_descriptor& e,
    00182           const OpenBabel::OBMol& )
    00183   {
    00184       return e.source();
    00185   }
    00186
    00187   graph_traits< OpenBabel::OBMol >::vertex_descriptor
    00188   target( graph_traits< OpenBabel::OBMol >::edge_descriptor e,
    00189           const OpenBabel::OBMol& )
    00190   {
    00191       return e.target();
    00192   }
    00193
    00194   std::pair < graph_traits< OpenBabel::OBMol >::out_edge_iterator,
    00195               graph_traits< OpenBabel::OBMol >::out_edge_iterator >
    00196   out_edges ( graph_traits< OpenBabel::OBMol >::vertex_descriptor v,
    00197               const OpenBabel::OBMol& )
    00198   {
    00199       return std::make_pair(
    00200       graph_traits< OpenBabel::OBMol >::out_edge_iterator(v->BeginBonds(),v),
    00201       graph_traits< OpenBabel::OBMol >::out_edge_iterator(v->EndBonds()  ,v) );
    00202   }
    00203
    00204   int out_degree( graph_traits< OpenBabel::OBMol >::vertex_descriptor v,
    00205                   const OpenBabel::OBMol& )
    00206   {
    00207       return v->EndBonds() - v->BeginBonds();
    00208   }
    00209
    00210   int num_vertices( const OpenBabel::OBMol& m )
    00211   {
    00212       return m.NumAtoms();
    00213   }
    00214
    00215   int num_edges( const OpenBabel::OBMol& m )
    00216   {
    00217       return m.NumBonds();
    00218   }
    00219
    00220 } // namespace
    00221
    00222 // When putting these classes inside the OpenBabel namespace
    00223 // the put and get functions will not work with the BGL algorithms.
    00224 // Don't know why.
    00225
    00226 template< class value >
    00227 class OBAtomMap
    00228 {
    00229   public :
    00230
    00231     typedef value value_type;
    00232     typedef OpenBabel::OBAtom* key_type;
    00233     typedef value_type& reference;
    00234     typedef boost::read_write_property_map_tag category;
    00235
    00236     OBAtomMap( const OpenBabel::OBMol& m ) :
    00237         _values( new std::vector< value >( m.NumAtoms() ) )
    00238     {}
    00239     OBAtomMap( const OpenBabel::OBMol& m, const value v ) :
    00240         _values( new std::vector< value >( m.NumAtoms(),v ) )
    00241     {}
    00242
    00243     reference operator[]( OpenBabel::OBAtom* a )
    00244         { return (*_values)[ a->GetIdx()-1 ]; }
    00245
    00246   private :
    00247
    00248     boost::shared_ptr< std::vector< value_type > > _values;
    00249
    00250 };
    00251
    00252 template< class value >
    00253 class OBBondMap
    00254 {
    00255   public :
    00256
    00257     typedef value value_type;
    00258     typedef OpenBabel::OBBond* key_type;
    00259     typedef value_type& reference;
    00260     typedef boost::read_write_property_map_tag category;
    00261
    00262     OBBondMap( const OpenBabel::OBMol& m ) :
    00263         _values( new std::vector< value >( m.NumBonds() ) )
    00264     {}
    00265     OBBondMap( const OpenBabel::OBMol& m, const value v ) :
    00266         _values( new std::vector< value >( m.NumBonds(),v ) )
    00267     {}
    00268
    00269     reference operator[]( OpenBabel::OBBond* b )
    00270         { return (*_values)[ b->GetIdx() ]; }
    00271
    00272   private :
    00273
    00274     boost::shared_ptr< std::vector< value_type > > _values;
    00275 };
    00276
    00277 template< class map_t >
    00278 void put( map_t& map, typename map_t::key_type key,  typename map_t::value_type value )
    00279     { map[key] = value; }
    00280
    00281 template< class map_t >
    00282 typename map_t::value_type get( map_t& map, typename map_t::key_type key )
    00283     { return map[key]; }
    00284
    00285 namespace boost {
    00286
    00287 template <class functor, class Tag >
    00288 struct functor_caller
    00289     : public base_visitor< functor_caller < functor, Tag> >
    00290 {
    00291     typedef Tag event_filter;
    00292     functor_caller(functor f) : m_func(f) { }
    00293     template <class T, class Graph>
    00294     void operator()(T t, const Graph& g) {
    00295       m_func.operator()(t);
    00296     }
    00297     functor m_func;
    00298 };
    00299
    00300 template < class functor, class Tag >
    00301 functor_caller< functor, Tag >
    00302 call_functor(functor func, Tag) {
    00303     return functor_caller< functor, Tag > (func);
    00304 }
    00305
    00306 template <class output_iterator, class Tag >
    00307 struct recorder
    00308     : public base_visitor< recorder < output_iterator, Tag> >
    00309 {
    00310     typedef Tag event_filter;
    00311     recorder(output_iterator o) : m_output(o) { }
    00312     template <class T, class Graph>
    00313     void operator()(T t, const Graph& g) {
    00314       m_output = t;
    00315     }
    00316     output_iterator m_output;
    00317 };
    00318
    00319 template <class output_iterator, class Tag >
    00320 recorder< output_iterator, Tag > record(output_iterator out, Tag) {
    00321     return recorder< output_iterator, Tag > (out);
    00322 }
    00323
    00324 } // namespace
    00325
    00326 #endif // MOL_GRAPH_H

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

This file is part of the documentation for Open Babel, version 2.3.

Documentation copyright © 1998-2007, the Open Babel Developers.
Open Babel is hosted by:
Generated on Fri Oct 22 2010 14:36:01 by 1.7.2.