ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/openbabel/data.cpp
Revision: 1081
Committed: Thu Oct 19 20:49:05 2006 UTC (18 years, 6 months ago) by gezelter
File size: 22207 byte(s)
Log Message:
updated OpenBabel to version 2.0.2

File Contents

# User Rev Content
1 tim 741 /**********************************************************************
2     data.cpp - Global data and resource file parsers.
3    
4     Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5 gezelter 1081 Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
6 tim 741
7     This file is part of the Open Babel project.
8     For more information, see <http://openbabel.sourceforge.net/>
9    
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation version 2 of the License.
13    
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17     GNU General Public License for more details.
18     ***********************************************************************/
19    
20     #ifdef WIN32
21     #pragma warning (disable : 4786)
22     #endif
23    
24 gezelter 751 #include "config.h"
25 tim 741 #include "data.hpp"
26     #include "mol.hpp"
27    
28     // data headers
29     #include "element.hpp"
30     #include "types.hpp"
31     #include "isotope.hpp"
32     #include "resdata.hpp"
33    
34    
35     #if !HAVE_STRNCASECMP
36     extern "C" int strncasecmp(const char *s1, const char *s2, size_t n);
37     #endif
38    
39     using namespace std;
40    
41     namespace OpenBabel
42     {
43    
44 gezelter 1081 OBElementTable etab;
45     OBTypeTable ttab;
46     OBIsotopeTable isotab;
47     OBResidueData resdat;
48 tim 741
49 gezelter 1081 /** \class OBElementTable
50     \brief Periodic Table of the Elements
51 tim 741
52 gezelter 1081 Translating element data is a common task given that many file
53     formats give either element symbol or atomic number information, but
54     not both. The OBElementTable class facilitates conversion between
55     textual and numeric element information. An instance of the
56     OBElementTable class (etab) is declared as external in data.cpp. Source
57     files that include the header file mol.h automatically have an extern
58     definition to etab. The following code sample demonstrates the use
59     of the OBElementTable class:
60     \code
61     cout << "The symbol for element 6 is " << etab.GetSymbol(6) << endl;
62     cout << "The atomic number for Sulfur is " << etab.GetAtomicNum(16) << endl;
63     cout << "The van der Waal radius for Nitrogen is " << etab.GetVdwRad(7);
64     \endcode
65 tim 741
66 gezelter 1081 Stored information in the OBElementTable includes elemental:
67     - symbols
68     - covalent radii
69     - van der Waal radii
70     - expected maximum bonding valence
71     - molar mass (by IUPAC recommended atomic masses)
72     - electronegativity
73     - ionization potential
74     - electron affinity
75     - RGB colors for visualization programs
76     - names (by IUPAC recommendation)
77     */
78 tim 741
79 gezelter 1081 OBElementTable::OBElementTable()
80     {
81 tim 741 _init = false;
82 gezelter 1081 STR_DEFINE(_dir, FRC_PATH );
83 gezelter 751 _envvar = "FORCE_PARAM_PATH";
84 tim 741 _filename = "element.txt";
85     _subdir = "data";
86     _dataptr = ElementData;
87 gezelter 1081 }
88 tim 741
89 gezelter 1081 OBElementTable::~OBElementTable()
90     {
91 tim 741 vector<OBElement*>::iterator i;
92     for (i = _element.begin();i != _element.end();i++)
93 gezelter 1081 delete *i;
94     }
95 tim 741
96 gezelter 1081 void OBElementTable::ParseLine(const char *buffer)
97     {
98 tim 741 int num,maxbonds;
99     char symbol[5];
100 gezelter 1081 char name[256];
101 tim 741 double Rcov,Rvdw,mass, elNeg, ionize, elAffin;
102     double red, green, blue;
103    
104     if (buffer[0] != '#') // skip comment line (at the top)
105 gezelter 1081 {
106     sscanf(buffer,"%d %5s %lf %*f %lf %d %lf %lf %lf %lf %lf %lf %lf %255s",
107     &num,
108     symbol,
109     &Rcov,
110     &Rvdw,
111     &maxbonds,
112     &mass,
113     &elNeg,
114     &ionize,
115     &elAffin,
116     &red,
117     &green,
118     &blue,
119     name);
120 tim 741
121 gezelter 1081 OBElement *ele = new OBElement(num,symbol,Rcov,Rvdw,maxbonds,mass,elNeg,
122     ionize, elAffin, red, green, blue, name);
123     _element.push_back(ele);
124     }
125     }
126 tim 741
127 gezelter 1081 unsigned int OBElementTable::GetNumberOfElements()
128     {
129 tim 741 if (!_init)
130 gezelter 1081 Init();
131 tim 741
132     return _element.size();
133 gezelter 1081 }
134 tim 741
135 gezelter 1081 char *OBElementTable::GetSymbol(int atomicnum)
136     {
137 tim 741 if (!_init)
138 gezelter 1081 Init();
139 tim 741
140     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
141 gezelter 1081 return("\0");
142 tim 741
143     return(_element[atomicnum]->GetSymbol());
144 gezelter 1081 }
145 tim 741
146 gezelter 1081 int OBElementTable::GetMaxBonds(int atomicnum)
147     {
148 tim 741 if (!_init)
149 gezelter 1081 Init();
150 tim 741
151     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
152 gezelter 1081 return(0);
153 tim 741
154     return(_element[atomicnum]->GetMaxBonds());
155 gezelter 1081 }
156 tim 741
157 gezelter 1081 double OBElementTable::GetElectroNeg(int atomicnum)
158     {
159 tim 741 if (!_init)
160 gezelter 1081 Init();
161 tim 741
162     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
163 gezelter 1081 return(0.0);
164 tim 741
165     return(_element[atomicnum]->GetElectroNeg());
166 gezelter 1081 }
167 tim 741
168 gezelter 1081 double OBElementTable::GetIonization(int atomicnum)
169     {
170 tim 741 if (!_init)
171 gezelter 1081 Init();
172 tim 741
173     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
174 gezelter 1081 return(0.0);
175 tim 741
176     return(_element[atomicnum]->GetIonization());
177 gezelter 1081 }
178 tim 741
179    
180 gezelter 1081 double OBElementTable::GetElectronAffinity(int atomicnum)
181     {
182 tim 741 if (!_init)
183 gezelter 1081 Init();
184 tim 741
185     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
186 gezelter 1081 return(0.0);
187 tim 741
188     return(_element[atomicnum]->GetElectronAffinity());
189 gezelter 1081 }
190 tim 741
191 gezelter 1081 vector<double> OBElementTable::GetRGB(int atomicnum)
192     {
193 tim 741 if (!_init)
194 gezelter 1081 Init();
195 tim 741
196     vector <double> colors;
197     colors.reserve(3);
198    
199     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
200     {
201 gezelter 1081 colors.push_back(0.0f);
202     colors.push_back(0.0f);
203     colors.push_back(0.0f);
204 tim 741 return(colors);
205     }
206    
207     colors.push_back(_element[atomicnum]->GetRed());
208     colors.push_back(_element[atomicnum]->GetGreen());
209     colors.push_back(_element[atomicnum]->GetBlue());
210    
211     return (colors);
212 gezelter 1081 }
213 tim 741
214 gezelter 1081 string OBElementTable::GetName(int atomicnum)
215     {
216 tim 741 if (!_init)
217 gezelter 1081 Init();
218 tim 741
219     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
220 gezelter 1081 return("Unknown");
221 tim 741
222     return(_element[atomicnum]->GetName());
223 gezelter 1081 }
224 tim 741
225 gezelter 1081 double OBElementTable::GetVdwRad(int atomicnum)
226     {
227 tim 741 if (!_init)
228 gezelter 1081 Init();
229 tim 741
230     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
231 gezelter 1081 return(0.0);
232 tim 741
233     return(_element[atomicnum]->GetVdwRad());
234 gezelter 1081 }
235 tim 741
236 gezelter 1081 double OBElementTable::CorrectedBondRad(int atomicnum, int hyb)
237     {
238 tim 741 double rad;
239     if (!_init)
240 gezelter 1081 Init();
241 tim 741
242     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
243 gezelter 1081 return(1.0);
244 tim 741
245     rad = _element[atomicnum]->GetCovalentRad();
246    
247     if (hyb == 2)
248 gezelter 1081 rad *= 0.95;
249 tim 741 else if (hyb == 1)
250 gezelter 1081 rad *= 0.90;
251 tim 741
252     return(rad);
253 gezelter 1081 }
254 tim 741
255 gezelter 1081 double OBElementTable::CorrectedVdwRad(int atomicnum, int hyb)
256     {
257 tim 741 double rad;
258     if (!_init)
259 gezelter 1081 Init();
260 tim 741
261     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
262 gezelter 1081 return(1.95);
263 tim 741
264     rad = _element[atomicnum]->GetVdwRad();
265    
266     if (hyb == 2)
267 gezelter 1081 rad *= 0.95;
268 tim 741 else if (hyb == 1)
269 gezelter 1081 rad *= 0.90;
270 tim 741
271     return(rad);
272 gezelter 1081 }
273 tim 741
274 gezelter 1081 double OBElementTable::GetCovalentRad(int atomicnum)
275     {
276 tim 741 if (!_init)
277 gezelter 1081 Init();
278 tim 741
279     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
280 gezelter 1081 return(0.0);
281 tim 741
282     return(_element[atomicnum]->GetCovalentRad());
283 gezelter 1081 }
284 tim 741
285 gezelter 1081 double OBElementTable::GetMass(int atomicnum)
286     {
287 tim 741 if (!_init)
288 gezelter 1081 Init();
289 tim 741
290     if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
291 gezelter 1081 return(0.0);
292 tim 741
293     return(_element[atomicnum]->GetMass());
294 gezelter 1081 }
295 tim 741
296 gezelter 1081 int OBElementTable::GetAtomicNum(const char *sym)
297     {
298     int temp;
299     return GetAtomicNum(sym, temp);
300     }
301 tim 741
302 gezelter 1081 int OBElementTable::GetAtomicNum(const char *sym, int &iso)
303     {
304 tim 741 if (!_init)
305 gezelter 1081 Init();
306 tim 741
307     vector<OBElement*>::iterator i;
308     for (i = _element.begin();i != _element.end();i++)
309 gezelter 1081 if (!strncasecmp(sym,(*i)->GetSymbol(),2))
310     return((*i)->GetAtomicNum());
311 tim 741 if (strcasecmp(sym, "D") == 0)
312 gezelter 1081 {
313 tim 741 iso = 2;
314     return(1);
315 gezelter 1081 }
316 tim 741 else if (strcasecmp(sym, "T") == 0)
317 gezelter 1081 {
318 tim 741 iso = 3;
319     return(1);
320 gezelter 1081 }
321     else
322     iso = 0;
323 tim 741 return(0);
324 gezelter 1081 }
325 tim 741
326 gezelter 1081 /** \class OBIsotopeTable
327     \brief Table of atomic isotope masses
328 tim 741
329 gezelter 1081 */
330 tim 741
331 gezelter 1081 OBIsotopeTable::OBIsotopeTable()
332     {
333 tim 741 _init = false;
334 gezelter 1081 STR_DEFINE(_dir, FRC_PATH );
335 gezelter 751 _envvar = "FORCE_PARAM_PATH";
336 tim 741 _filename = "isotope.txt";
337     _subdir = "data";
338     _dataptr = IsotopeData;
339 gezelter 1081 }
340 tim 741
341 gezelter 1081 void OBIsotopeTable::ParseLine(const char *buffer)
342     {
343 tim 741 unsigned int atomicNum;
344     unsigned int i;
345     vector<string> vs;
346    
347     pair <unsigned int, double> entry;
348     vector <pair <unsigned int, double> > row;
349    
350     if (buffer[0] != '#') // skip comment line (at the top)
351 gezelter 1081 {
352 tim 741 tokenize(vs,buffer);
353     if (vs.size() > 3) // atomic number, 0, most abundant mass (...)
354 gezelter 1081 {
355 tim 741 atomicNum = atoi(vs[0].c_str());
356     for (i = 1; i < vs.size() - 1; i += 2) // make sure i+1 still exists
357 gezelter 1081 {
358 tim 741 entry.first = atoi(vs[i].c_str()); // isotope
359     entry.second = atof(vs[i + 1].c_str()); // exact mass
360     row.push_back(entry);
361 gezelter 1081 }
362 tim 741 _isotopes.push_back(row);
363 gezelter 1081 }
364     else
365     obErrorLog.ThrowError(__func__, " Could not parse line in isotope table isotope.txt", obInfo);
366     }
367     }
368 tim 741
369 gezelter 1081 double OBIsotopeTable::GetExactMass(const unsigned int ele,
370     const unsigned int isotope)
371     {
372 tim 741 if (!_init)
373 gezelter 1081 Init();
374 tim 741
375     if (ele > _isotopes.size())
376 gezelter 1081 return 0.0;
377 tim 741
378     unsigned int iso;
379     for (iso = 0; iso < _isotopes[ele].size(); iso++)
380 gezelter 1081 if (isotope == _isotopes[ele][iso].first)
381     return _isotopes[ele][iso].second;
382 tim 741
383     return 0.0;
384 gezelter 1081 }
385 tim 741
386 gezelter 1081 /** \class OBTypeTable
387     \brief Atom Type Translation Table
388 tim 741
389 gezelter 1081 Molecular file formats frequently store information about atoms in an
390     atom type field. Some formats store only the element for each atom,
391     while others include hybridization and local environments, such as the
392     Sybyl mol2 atom type field. The OBTypeTable class acts as a translation
393     table to convert atom types between a number of different molecular
394     file formats. The constructor for OBTypeTable automatically reads the
395     text file types.txt. Just as OBElementTable, an instance of
396     OBTypeTable (ttab) is declared external in data.cpp and is referenced as
397     extern OBTypeTable ttab in mol.h. The following code demonstrates how
398     to use the OBTypeTable class to translate the internal representation
399     of atom types in an OBMol Internal to Sybyl Mol2 atom types.
400 tim 741
401 gezelter 1081 \code
402     ttab.SetFromType("INT");
403     ttab.SetToType("SYB");
404     OBAtom *atom;
405     vector<OBAtom*>::iterator i;
406     string src,dst;
407     for (atom = mol.BeginAtom(i);atom;atom = mol.EndAtom(i))
408     {
409     src = atom->GetType();
410     ttab.Translate(dst,src);
411     cout << "atom number " << atom->GetIdx() << "has mol2 type " << dst << endl;
412     }
413     \endcode
414 tim 741
415 gezelter 1081 Current atom types include (defined in the top line of the data file types.txt):
416     - INT (Open Babel internal codes)
417     - ATN (atomic numbers)
418     - HYB (hybridization)
419     - MMD
420     - MM2 (MM2 force field)
421     - XYZ (element symbols from XYZ file format)
422     - ALC (Alchemy file)
423     - HAD
424     - MCML
425     - C3D (Chem3D)
426     - SYB (Sybyl mol2)
427     - MOL
428     - MAP
429     - DRE
430     - XED (XED format)
431     - DOK (Dock)
432     - M3D
433     */
434 tim 741
435 gezelter 1081 OBTypeTable::OBTypeTable()
436     {
437 tim 741 _init = false;
438 gezelter 1081 STR_DEFINE(_dir, FRC_PATH );
439 gezelter 751 _envvar = "FORCE_PARAM_PATH";
440 tim 741 _filename = "types.txt";
441     _subdir = "data";
442     _dataptr = TypesData;
443     _linecount = 0;
444     _from = _to = -1;
445 gezelter 1081 }
446 tim 741
447 gezelter 1081 void OBTypeTable::ParseLine(const char *buffer)
448     {
449 tim 741 if (buffer[0] == '#')
450 gezelter 1081 return; // just a comment line
451 tim 741
452     if (_linecount == 0)
453 gezelter 1081 sscanf(buffer,"%d%d",&_nrows,&_ncols);
454 tim 741 else if (_linecount == 1)
455 gezelter 1081 tokenize(_colnames,buffer);
456 tim 741 else
457 gezelter 1081 {
458 tim 741 vector<string> vc;
459     tokenize(vc,buffer);
460     if (vc.size() == (unsigned)_ncols)
461 gezelter 1081 _table.push_back(vc);
462     else
463     {
464     stringstream errorMsg;
465     errorMsg << " Could not parse line in type translation table types.txt -- incorect number of columns";
466     errorMsg << " found " << vc.size() << " expected " << _ncols << ".";
467     obErrorLog.ThrowError(__func__, errorMsg.str(), obInfo);
468     }
469     }
470 tim 741 _linecount++;
471 gezelter 1081 }
472 tim 741
473 gezelter 1081 bool OBTypeTable::SetFromType(const char* from)
474     {
475 tim 741 if (!_init)
476 gezelter 1081 Init();
477 tim 741
478     string tmp = from;
479    
480     unsigned int i;
481     for (i = 0;i < _colnames.size();i++)
482 gezelter 1081 if (tmp == _colnames[i])
483 tim 741 {
484 gezelter 1081 _from = i;
485     return(true);
486 tim 741 }
487    
488 tim 819 obErrorLog.ThrowError(__func__, "Requested type column not found", obInfo);
489 tim 741
490     return(false);
491 gezelter 1081 }
492 tim 741
493 gezelter 1081 bool OBTypeTable::SetToType(const char* to)
494     {
495 tim 741 if (!_init)
496 gezelter 1081 Init();
497 tim 741
498     string tmp = to;
499    
500     unsigned int i;
501     for (i = 0;i < _colnames.size();i++)
502 gezelter 1081 if (tmp == _colnames[i])
503 tim 741 {
504 gezelter 1081 _to = i;
505     return(true);
506 tim 741 }
507    
508 tim 819 obErrorLog.ThrowError(__func__, "Requested type column not found", obInfo);
509 tim 741
510     return(false);
511 gezelter 1081 }
512 tim 741
513 gezelter 1081 //! Translates atom types (to, from), checking for size of destination
514     //! string and null-terminating as needed
515     //! \deprecated Because there is no guarantee on the length of an atom type
516     //! you should consider using std::string instead
517     bool OBTypeTable::Translate(char *to, const char *from)
518     {
519 tim 741 if (!_init)
520 gezelter 1081 Init();
521 tim 741
522     bool rval;
523     string sto,sfrom;
524     sfrom = from;
525     rval = Translate(sto,sfrom);
526 gezelter 1081 strncpy(to,(char*)sto.c_str(), sizeof(to) - 1);
527     to[sizeof(to) - 1] = '\0';
528 tim 741
529     return(rval);
530 gezelter 1081 }
531 tim 741
532 gezelter 1081 bool OBTypeTable::Translate(string &to, const string &from)
533     {
534 tim 741 if (!_init)
535 gezelter 1081 Init();
536 tim 741
537     if (from == "")
538 gezelter 1081 return(false);
539 tim 741
540     if (_from >= 0 && _to >= 0 &&
541 gezelter 1081 _from < _table.size() && _to < _table.size())
542 tim 741 {
543 gezelter 1081 vector<vector<string> >::iterator i;
544     for (i = _table.begin();i != _table.end();i++)
545     if ((signed)(*i).size() > _from && (*i)[_from] == from)
546     {
547     to = (*i)[_to];
548     return(true);
549     }
550 tim 741 }
551    
552     // Throw an error, copy the string and return false
553 tim 819 obErrorLog.ThrowError(__func__, "Cannot perform atom type translation: table cannot find requested types.", obWarning);
554 tim 741 to = from;
555     return(false);
556 gezelter 1081 }
557 tim 741
558 gezelter 1081 std::string OBTypeTable::GetFromType()
559     {
560 tim 741 if (!_init)
561 gezelter 1081 Init();
562 tim 741
563     if (_from > 0 && _from < _table.size())
564     return( _colnames[_from] );
565     else
566     return( _colnames[0] );
567 gezelter 1081 }
568 tim 741
569 gezelter 1081 std::string OBTypeTable::GetToType()
570     {
571 tim 741 if (!_init)
572 gezelter 1081 Init();
573 tim 741
574     if (_to > 0 && _to < _table.size())
575     return( _colnames[_to] );
576     else
577     return( _colnames[0] );
578 gezelter 1081 }
579 tim 741
580 gezelter 1081 void Toupper(string &s)
581     {
582 tim 741 unsigned int i;
583     for (i = 0;i < s.size();i++)
584 gezelter 1081 s[i] = toupper(s[i]);
585     }
586 tim 741
587 gezelter 1081 void Tolower(string &s)
588     {
589 tim 741 unsigned int i;
590     for (i = 0;i < s.size();i++)
591 gezelter 1081 s[i] = tolower(s[i]);
592     }
593 tim 741
594 gezelter 1081 ///////////////////////////////////////////////////////////////////////
595     OBResidueData::OBResidueData()
596     {
597 tim 741 _init = false;
598 gezelter 1081 STR_DEFINE(_dir, FRC_PATH );
599 gezelter 751 _envvar = "FORCE_PARAM_PATH";
600 tim 741 _filename = "resdata.txt";
601     _subdir = "data";
602     _dataptr = ResidueData;
603 gezelter 1081 }
604 tim 741
605 gezelter 1081 bool OBResidueData::AssignBonds(OBMol &mol,OBBitVec &bv)
606     {
607     if (!_init)
608     Init();
609    
610 tim 741 OBAtom *a1,*a2;
611     OBResidue *r1,*r2;
612     vector<OBNodeBase*>::iterator i,j;
613     vector3 v;
614    
615     int bo;
616     unsigned int skipres=0;
617     string rname = "";
618     //assign residue bonds
619     for (a1 = mol.BeginAtom(i);a1;a1 = mol.NextAtom(i))
620 gezelter 1081 {
621 tim 741 r1 = a1->GetResidue();
622     if (skipres && r1->GetNum() == skipres)
623 gezelter 1081 continue;
624 tim 741
625     if (r1->GetName() != rname)
626 gezelter 1081 {
627 tim 741 skipres = SetResName(r1->GetName()) ? 0 : r1->GetNum();
628     rname = r1->GetName();
629 gezelter 1081 }
630 tim 741 //assign bonds for each atom
631     for (j=i,a2 = mol.NextAtom(j);a2;a2 = mol.NextAtom(j))
632 gezelter 1081 {
633 tim 741 r2 = a2->GetResidue();
634     if (r1->GetNum() != r2->GetNum())
635 gezelter 1081 break;
636 tim 741 if (r1->GetName() != r2->GetName())
637 gezelter 1081 break;
638 tim 741
639     if ((bo = LookupBO(r1->GetAtomID(a1),r2->GetAtomID(a2))))
640 gezelter 1081 {
641 tim 741 v = a1->GetVector() - a2->GetVector();
642     if (v.length_2() < 3.5) //check by distance
643 gezelter 1081 mol.AddBond(a1->GetIdx(),a2->GetIdx(),bo);
644     }
645     }
646     }
647 tim 741
648     int hyb;
649     string type;
650    
651     //types and hybridization
652 gezelter 1081 rname = ""; // name of current residue
653     skipres = 0; // don't skip any residues right now
654 tim 741 for (a1 = mol.BeginAtom(i);a1;a1 = mol.NextAtom(i))
655 gezelter 1081 {
656 tim 741 if (a1->IsOxygen() && !a1->GetValence())
657 gezelter 1081 {
658 tim 741 a1->SetType("O3");
659     continue;
660 gezelter 1081 }
661 tim 741 if (a1->IsHydrogen())
662 gezelter 1081 {
663 tim 741 a1->SetType("H");
664     continue;
665 gezelter 1081 }
666 tim 741
667     //***valence rule for O-
668     if (a1->IsOxygen() && a1->GetValence() == 1)
669 gezelter 1081 {
670 tim 741 OBBond *bond;
671     bond = (OBBond*)*(a1->BeginBonds());
672     if (bond->GetBO() == 2)
673 gezelter 1081 {
674 tim 741 a1->SetType("O2");
675     a1->SetHyb(2);
676 gezelter 1081 }
677     else if (bond->GetBO() == 1)
678     {
679 tim 741 a1->SetType("O-");
680     a1->SetHyb(3);
681     a1->SetFormalCharge(-1);
682 gezelter 1081 }
683     continue;
684     }
685    
686     r1 = a1->GetResidue();
687     if (skipres && r1->GetNum() == skipres)
688     continue;
689 tim 741
690 gezelter 1081 if (r1->GetName() != rname)
691     {
692     // if SetResName fails, skip this residue
693     skipres = SetResName(r1->GetName()) ? 0 : r1->GetNum();
694     rname = r1->GetName();
695     }
696    
697     if (LookupType(r1->GetAtomID(a1),type,hyb))
698     {
699     a1->SetType(type);
700     a1->SetHyb(hyb);
701     }
702     else // try to figure it out by bond order ???
703     {}
704     }
705    
706 tim 741 return(true);
707 gezelter 1081 }
708 tim 741
709 gezelter 1081 void OBResidueData::ParseLine(const char *buffer)
710     {
711 tim 741 int bo;
712     string s;
713     vector<string> vs;
714    
715     if (buffer[0] == '#')
716 gezelter 1081 return;
717 tim 741
718     tokenize(vs,buffer);
719     if (!vs.empty())
720 gezelter 1081 {
721 tim 741 if (vs[0] == "BOND")
722 gezelter 1081 {
723 tim 741 s = (vs[1] < vs[2]) ? vs[1] + " " + vs[2] :
724 gezelter 1081 vs[2] + " " + vs[1];
725 tim 741 bo = atoi(vs[3].c_str());
726     _vtmp.push_back(pair<string,int> (s,bo));
727 gezelter 1081 }
728 tim 741
729     if (vs[0] == "ATOM" && vs.size() == 4)
730 gezelter 1081 {
731 tim 741 _vatmtmp.push_back(vs[1]);
732     _vatmtmp.push_back(vs[2]);
733     _vatmtmp.push_back(vs[3]);
734 gezelter 1081 }
735 tim 741
736     if (vs[0] == "RES")
737 gezelter 1081 _resname.push_back(vs[1]);
738 tim 741
739     if (vs[0]== "END")
740 gezelter 1081 {
741 tim 741 _resatoms.push_back(_vatmtmp);
742     _resbonds.push_back(_vtmp);
743     _vtmp.clear();
744     _vatmtmp.clear();
745 gezelter 1081 }
746     }
747     }
748 tim 741
749 gezelter 1081 bool OBResidueData::SetResName(const string &s)
750     {
751     if (!_init)
752     Init();
753    
754 tim 741 unsigned int i;
755 gezelter 1081
756 tim 741 for (i = 0;i < _resname.size();i++)
757 gezelter 1081 if (_resname[i] == s)
758 tim 741 {
759 gezelter 1081 _resnum = i;
760     return(true);
761 tim 741 }
762    
763     _resnum = -1;
764     return(false);
765 gezelter 1081 }
766 tim 741
767 gezelter 1081 int OBResidueData::LookupBO(const string &s)
768     {
769 tim 741 if (_resnum == -1)
770 gezelter 1081 return(0);
771 tim 741
772     unsigned int i;
773     for (i = 0;i < _resbonds[_resnum].size();i++)
774 gezelter 1081 if (_resbonds[_resnum][i].first == s)
775     return(_resbonds[_resnum][i].second);
776 tim 741
777     return(0);
778 gezelter 1081 }
779 tim 741
780 gezelter 1081 int OBResidueData::LookupBO(const string &s1, const string &s2)
781     {
782 tim 741 if (_resnum == -1)
783 gezelter 1081 return(0);
784 tim 741 string s;
785    
786     s = (s1 < s2) ? s1 + " " + s2 : s2 + " " + s1;
787    
788     unsigned int i;
789     for (i = 0;i < _resbonds[_resnum].size();i++)
790 gezelter 1081 if (_resbonds[_resnum][i].first == s)
791     return(_resbonds[_resnum][i].second);
792 tim 741
793     return(0);
794 gezelter 1081 }
795 tim 741
796 gezelter 1081 bool OBResidueData::LookupType(const string &atmid,string &type,int &hyb)
797     {
798 tim 741 if (_resnum == -1)
799 gezelter 1081 return(false);
800 tim 741
801     string s;
802     vector<string>::iterator i;
803    
804     for (i = _resatoms[_resnum].begin();i != _resatoms[_resnum].end();i+=3)
805 gezelter 1081 if (atmid == *i)
806 tim 741 {
807 gezelter 1081 i++;
808     type = *i;
809     i++;
810     hyb = atoi((*i).c_str());
811     return(true);
812 tim 741 }
813    
814     return(false);
815 gezelter 1081 }
816 tim 741
817 gezelter 1081 void OBGlobalDataBase::Init()
818     {
819 tim 741 if (_init)
820 gezelter 1081 return;
821 tim 741 _init = true;
822    
823 gezelter 1081 string buffer, subbuffer;
824 tim 741 ifstream ifs1, ifs2, ifs3, ifs4, *ifsP;
825     // First, look for an environment variable
826     if (getenv(_envvar.c_str()) != NULL)
827 gezelter 1081 {
828     buffer = getenv(_envvar.c_str());
829     buffer += FILE_SEP_CHAR;
830 tim 741
831     if (!_subdir.empty())
832 gezelter 1081 {
833     subbuffer = buffer;
834     subbuffer += _subdir;
835     subbuffer += FILE_SEP_CHAR;
836     }
837 tim 741
838 gezelter 1081 buffer += _filename;
839     subbuffer += _filename;
840 tim 741
841 gezelter 1081 ifs1.open(subbuffer.c_str());
842 tim 741 ifsP= &ifs1;
843     if (!(*ifsP))
844 gezelter 1081 {
845     ifs2.open(buffer.c_str());
846 tim 741 ifsP = &ifs2;
847 gezelter 1081 }
848     }
849 tim 741 // Then, check the configured data directory
850     else // if (!(*ifsP))
851 gezelter 1081 {
852     buffer = _dir;
853     buffer += FILE_SEP_CHAR;
854 tim 741
855 gezelter 1081 subbuffer = buffer;
856     subbuffer += BABEL_VERSION;
857     subbuffer += FILE_SEP_CHAR;
858 tim 741
859 gezelter 1081 subbuffer += _filename;
860     buffer += _filename;
861 tim 741
862 gezelter 1081 ifs3.open(subbuffer.c_str());
863 tim 741 ifsP= &ifs3;
864     if (!(*ifsP))
865 gezelter 1081 {
866     ifs4.open(buffer.c_str());
867 tim 741 ifsP = &ifs4;
868 gezelter 1081 }
869     }
870 tim 741
871 gezelter 1081 char charBuffer[BUFF_SIZE];
872 tim 741 if ((*ifsP))
873 gezelter 1081 {
874     while(ifsP->getline(charBuffer,BUFF_SIZE))
875     ParseLine(charBuffer);
876     }
877 tim 741
878     else
879 gezelter 1081 // If all else fails, use the compiled in values
880     if (_dataptr)
881 tim 741 {
882 gezelter 1081 const char *p1,*p2;
883     for (p1 = p2 = _dataptr;*p2 != '\0';p2++)
884     if (*p2 == '\n')
885     {
886     strncpy(charBuffer, p1, (p2 - p1));
887     charBuffer[(p2 - p1)] = '\0';
888     ParseLine(charBuffer);
889     p1 = ++p2;
890     }
891 tim 741 }
892 gezelter 1081 else
893 tim 741 {
894 gezelter 1081 string s = "Unable to open data file '";
895     s += _filename;
896     s += "'";
897     obErrorLog.ThrowError(__func__, s, obWarning);
898 tim 741 }
899    
900     if (ifs1)
901 gezelter 1081 ifs1.close();
902 tim 741 if (ifs2)
903 gezelter 1081 ifs2.close();
904 tim 741 if (ifs3)
905 gezelter 1081 ifs3.close();
906 tim 741 if (ifs4)
907 gezelter 1081 ifs4.close();
908 tim 741
909     if (GetSize() == 0)
910     {
911 gezelter 1081 string s = "Cannot initialize database '";
912     s += _filename;
913     s += "' which may cause further errors.";
914     obErrorLog.ThrowError(__func__, "Cannot initialize database", obWarning);
915 tim 741 }
916    
917 gezelter 1081 }
918 tim 741
919     } // end namespace OpenBabel
920    
921     //! \file data.cpp
922     //! \brief Global data and resource file parsers.