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
This file is part of the documentation for Open Babel, version 2.3.
1.7.2.