36
35
using namespace std;
37
//! Global namespace for all Open Babel code
40
41
bool OBGraphBase::Match(OBGraphBase &g,bool singleMatch)
42
SetFinishedMatch(false);
43
SetSingleMatch(singleMatch);
49
OBNodeBase *seed = GetFirstSeed();
50
vector<OBNodeBase*>::iterator i;
52
for (node = g.Begin(i);node;node = g.Next(i))
53
if (!node->Visit && seed->Eval(node))
57
Match(g,BgnMatch(),BgnMatch()->second.begin());
58
seed->SetMatch((OBNodeBase*)NULL);
60
if (SingleMatch() && FinishedMatch()) break;
63
g.SetVisitLock(false);
65
return(FinishedMatch());
43
SetFinishedMatch(false);
44
SetSingleMatch(singleMatch);
50
OBNodeBase *seed = GetFirstSeed();
51
vector<OBNodeBase*>::iterator i;
53
for (node = g.Begin(i);node;node = g.Next(i))
54
if (!node->Visit && seed->Eval(node))
58
Match(g,BgnMatch(),BgnMatch()->second.begin());
59
seed->SetMatch((OBNodeBase*)NULL);
61
if (SingleMatch() && FinishedMatch())
65
g.SetVisitLock(false);
67
return(FinishedMatch());
68
70
bool OBGraphBase::Match(OBGraphBase &g,
69
vector<pair<OBNodeBase*,vector<OBEdgeBase*> > >::iterator i,
70
vector<OBEdgeBase*>::iterator j)
71
vector<pair<OBNodeBase*,vector<OBEdgeBase*> > >::iterator i,
72
vector<OBEdgeBase*>::iterator j)
72
//bail if only one match has been requested
73
if (SingleMatch() && FinishedMatch()) return(true);
75
//full match completed
76
if (i == EndMatch() || (j == i->second.end() && (i+1) == EndMatch()))
78
SetFinishedMatch(true);
80
vector<OBNodeBase*> vn;
81
vector<OBNodeBase*>::iterator i;
82
for (node = Begin(i);node;node = Next(i))
83
vn.push_back(node->GetMatch());
89
//handle next seed of disconnected pattern
90
if (j == i->second.end())
94
OBNodeBase *seed = i->first;
95
vector<OBNodeBase*>::iterator k;
96
for (node = g.Begin(k);node;node = g.Next(k))
97
if (!node->Visit && seed->Eval(node))
100
seed->SetMatch(node);
101
Match(g,i,i->second.begin());
102
seed->SetMatch((OBNodeBase*)NULL);
104
if (SingleMatch() && FinishedMatch()) break;
109
OBEdgeBase *edge = *j++;
110
if (edge->IsClosure()) //check to see if matched atoms are bonded
112
if (edge->GetBgn()->GetMatch()->IsConnected(edge->GetEnd()->GetMatch()))
115
else //bond hasn't been covered yet
118
OBNodeBase *curr = edge->GetBgn();
119
OBNodeBase *next = edge->GetEnd();
120
OBNodeBase *match = curr->GetMatch();
121
vector<OBEdgeBase*>::iterator k;
123
for (nbr = match->BeginNbr(k);nbr;nbr = match->NextNbr(k))
124
if (!nbr->Visit && next->Eval(nbr) && edge->Eval(*k))
129
next->SetMatch(NULL);
74
//bail if only one match has been requested
75
if (SingleMatch() && FinishedMatch())
78
//full match completed
79
if (i == EndMatch() || (j == i->second.end() && (i+1) == EndMatch()))
81
SetFinishedMatch(true);
83
vector<OBNodeBase*> vn;
84
vector<OBNodeBase*>::iterator i;
85
for (node = Begin(i);node;node = Next(i))
86
vn.push_back(node->GetMatch());
92
//handle next seed of disconnected pattern
93
if (j == i->second.end())
97
OBNodeBase *seed = i->first;
98
vector<OBNodeBase*>::iterator k;
99
for (node = g.Begin(k);node;node = g.Next(k))
100
if (!node->Visit && seed->Eval(node))
103
seed->SetMatch(node);
104
Match(g,i,i->second.begin());
105
seed->SetMatch((OBNodeBase*)NULL);
107
if (SingleMatch() && FinishedMatch())
113
OBEdgeBase *edge = *j++;
114
if (edge->IsClosure()) //check to see if matched atoms are bonded
116
if (edge->GetBgn()->GetMatch()->IsConnected(edge->GetEnd()->GetMatch()))
119
else //bond hasn't been covered yet
122
OBNodeBase *curr = edge->GetBgn();
123
OBNodeBase *next = edge->GetEnd();
124
OBNodeBase *match = curr->GetMatch();
125
vector<OBEdgeBase*>::iterator k;
127
for (nbr = match->BeginNbr(k);nbr;nbr = match->NextNbr(k))
128
if (!nbr->Visit && next->Eval(nbr) && edge->Eval(*k))
133
next->SetMatch(NULL);
137
141
OBNodeBase *OBGraphBase::Begin(vector<OBNodeBase*>::iterator &i)
140
return((i != _vatom.end()) ? *i : NULL);
144
return((i != _vatom.end()) ? *i : NULL);
143
147
OBNodeBase *OBGraphBase::Next(vector<OBNodeBase*>::iterator &i)
146
return((i != _vatom.end()) ? *i : NULL);
150
return((i != _vatom.end()) ? *i : NULL);
149
OBEdgeBase *OBGraphBase::Begin(vector<OBEdgeBase*>::iterator &i)
153
OBEdgeBase *OBGraphBase::Begin(vector<OBEdgeBase*>::iterator &i)
152
return((i != _vbond.end()) ? *i : NULL);
156
return((i != _vbond.end()) ? *i : NULL);
155
159
OBEdgeBase *OBGraphBase::Next(vector<OBEdgeBase*>::iterator &i)
158
return((i != _vbond.end()) ? *i : NULL);
162
return((i != _vbond.end()) ? *i : NULL);
161
165
OBNodeBase *OBNodeBase::BeginNbr(vector<OBEdgeBase*>::iterator &i)
165
if (i == _vbond.end()) return(NULL);
166
return((this == (*i)->GetBgn()) ? (*i)->GetEnd() : (*i)->GetBgn());
169
if (i == _vbond.end())
171
return((this == (*i)->GetBgn()) ? (*i)->GetEnd() : (*i)->GetBgn());
169
174
OBNodeBase *OBNodeBase::NextNbr(vector<OBEdgeBase*>::iterator &i)
172
if (i == _vbond.end()) return(NULL);
173
return((this == (*i)->GetBgn()) ? (*i)->GetEnd() : (*i)->GetBgn());
177
if (i == _vbond.end())
179
return((this == (*i)->GetBgn()) ? (*i)->GetEnd() : (*i)->GetBgn());
176
182
void OBNodeBase::SetParent(OBGraphBase *p)
181
187
void OBEdgeBase::SetParent(OBGraphBase *p)
186
192
bool OBNodeBase::IsConnected(OBNodeBase *nb)
188
vector<OBEdgeBase*>::iterator i;
189
for (i = _vbond.begin();i != _vbond.end();i++)
190
if (nb == (*i)->GetBgn() || nb == (*i)->GetEnd())
194
vector<OBEdgeBase*>::iterator i;
195
for (i = _vbond.begin();i != _vbond.end();i++)
196
if (nb == (*i)->GetBgn() || nb == (*i)->GetEnd())
196
202
void OBGraphBase::ResetVisitFlags()
199
vector<OBNodeBase*>::iterator i;
200
for (nb = Begin(i);nb;nb = Next(i)) nb->Visit = false;
205
vector<OBNodeBase*>::iterator i;
206
for (nb = Begin(i);nb;nb = Next(i))
203
vector<OBEdgeBase*>::iterator j;
204
for (eb = Begin(j);eb;eb = Next(j)) eb->Visit = false;
210
vector<OBEdgeBase*>::iterator j;
211
for (eb = Begin(j);eb;eb = Next(j))
207
215
bool OBGraphBase::SetVisitLock(bool v)
209
if (v && _vlock) return(false);
215
\section intro Introduction
217
(portions adapted from the OELib primer, written by Matt Stahl, Open
218
Eye Scientific Software, Inc.)
220
It is fair to say that Open Babel (and before it, OELib) is a direct
221
result of the original Babel. Programmers have long known that
222
application development is facilitated by building software on top of
223
libraries rich in functionality. Babel was the first experience for
224
Matt Stahl in designing a molecule library. In addition to developing
225
Babel, Pat Walters and Matt developed `OBabel' at Vertex
226
Pharmaceuticals. OBabel was the first attempt at developing an
227
object oriented molecule library. Although OBabel was a successful
228
project, Matt's departure from Vertex Pharmaceuticals provided a great
229
opportunity to include much of what I had learned in previous projects
230
into a new molecule class library. OELib was then designed to be flexible,
231
extensible, portable, and efficient class library for processing small
225
\section intro Introduction and History
227
It is fair to say that Open Babel is a direct result of the original Babel.
228
Application development is facilitated
229
by building software on top of libraries rich in functionality. Babel
230
was the first experience for Matt Stahl in designing a molecule
231
library. In addition to developing Babel, Pat Walters and Matt
232
developed `OBabel' at Vertex Pharmaceuticals, a first
233
attempt at developing an object oriented molecule library.
234
Matt later designed a new molecule class library, OELib -- designed
235
to be flexible, extensible, portable, and efficient.
234
237
OELib was released under the GNU General Public License (GPL) by Matt Stahl
235
238
and Open Eye Scientific Software, Inc. to take advantage of many of
236
the "great minds writing chemical software." Eventually Open Eye
237
decided to write a next-generation class library as proprietary
238
software. The result was that Open Babel took up where OELib left off,
239
using the existing GPL version of OELib, and has continued to evolve
242
There are several advantages to having the source code to Open Babel
243
available. First, development time can be shortened by basing projects
244
on Open Babel. Many chemical and molecular concepts and code are
245
already implemented. The fewer people who have to reinvent the wheel
246
(or the function), the better. Second, as free software, hopefully
247
other programmers will contribute to the project.
239
the "great minds writing chemical software." Open Babel took up where
240
OELib and Babel left off, starting from the existing GPL version of
241
OELib, and has continued to evolve and improve into a separate
242
high-quality chemistry class library and tool. Open Babel is now a
243
separate project and library and has changed considerably from the OELib days.
249
245
Thanks to all who have helped with Babel, OBabel, OELib and Open Babel.
250
246
The list is long and growing.
252
248
\section pointers Key Modules
254
250
The heart of Open Babel lies in the \link OpenBabel::OBMol OBMol\endlink,
255
251
\link OpenBabel::OBAtom OBAtom\endlink, and
256
252
\link OpenBabel::OBBond OBBond\endlink classes,
259
255
designed to store the basic information
260
256
in a molecule and to perceive information about a molecule.
263
transformations and automatic perception of properties is performed in a
264
"lazy" manner. That is, until you call for partial atomic charges, no
265
charges are calculated. This ensures faster transformations of chemical data
258
One of the key philosophies in the code is that transformations and
259
automatic perception of properties are performed in a <a href="http://en.wikipedia.org/wiki/Lazy_evaluation">"lazy"</a>
260
manner. That is, until you call for partial atomic charges, no
261
charges are calculated. This ensures faster transformations of
262
chemical data -- properties that are not needed for your code will
263
typically not be calculated. When such data is needed, appropriate
264
routines are called, and a "flag" is set (e.g., via OBMol::SetFlag
265
or OBAtom::SetFlag etc.) so that the code is only run once.
267
Arbitrary custom data and text descriptors can be stored in any atom,
268
bond, molecule, or residue using the \link OpenBabel::OBGenericData
269
OBGenericData\endlink or \link OpenBabel::OBPairData
270
OBPairData\endlink classes.
272
Conversion between various chemical file formats is accomplished through
273
the \link OpenBabel::OBConversion OBConversion\endlink and \link
274
OpenBabel::OBFormat OBFormat\endlink classes, often through use of the \link
275
OpenBabel::OBMoleculeFormat OBMoleculeFormat\endlink subclass which is designed
276
for easy read/write access to one or more \link OpenBabel::OBMol OBMol\endlink
277
objects. The philosophy of the file format codes is to parse as much
278
chemical information from a given file as possible (no data left
279
behind) and ideally any perception or transformations will occur when
280
writing to some other format later.
270
284
} // namespace OpenBabel
287
//! \brief Implementation of base classes.