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

# Content
1 /**********************************************************************
2 data.cpp - Global data and resource file parsers.
3
4 Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5 Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
6
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 #include "config.h"
25 #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 OBElementTable etab;
45 OBTypeTable ttab;
46 OBIsotopeTable isotab;
47 OBResidueData resdat;
48
49 /** \class OBElementTable
50 \brief Periodic Table of the Elements
51
52 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
66 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
79 OBElementTable::OBElementTable()
80 {
81 _init = false;
82 STR_DEFINE(_dir, FRC_PATH );
83 _envvar = "FORCE_PARAM_PATH";
84 _filename = "element.txt";
85 _subdir = "data";
86 _dataptr = ElementData;
87 }
88
89 OBElementTable::~OBElementTable()
90 {
91 vector<OBElement*>::iterator i;
92 for (i = _element.begin();i != _element.end();i++)
93 delete *i;
94 }
95
96 void OBElementTable::ParseLine(const char *buffer)
97 {
98 int num,maxbonds;
99 char symbol[5];
100 char name[256];
101 double Rcov,Rvdw,mass, elNeg, ionize, elAffin;
102 double red, green, blue;
103
104 if (buffer[0] != '#') // skip comment line (at the top)
105 {
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
121 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
127 unsigned int OBElementTable::GetNumberOfElements()
128 {
129 if (!_init)
130 Init();
131
132 return _element.size();
133 }
134
135 char *OBElementTable::GetSymbol(int atomicnum)
136 {
137 if (!_init)
138 Init();
139
140 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
141 return("\0");
142
143 return(_element[atomicnum]->GetSymbol());
144 }
145
146 int OBElementTable::GetMaxBonds(int atomicnum)
147 {
148 if (!_init)
149 Init();
150
151 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
152 return(0);
153
154 return(_element[atomicnum]->GetMaxBonds());
155 }
156
157 double OBElementTable::GetElectroNeg(int atomicnum)
158 {
159 if (!_init)
160 Init();
161
162 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
163 return(0.0);
164
165 return(_element[atomicnum]->GetElectroNeg());
166 }
167
168 double OBElementTable::GetIonization(int atomicnum)
169 {
170 if (!_init)
171 Init();
172
173 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
174 return(0.0);
175
176 return(_element[atomicnum]->GetIonization());
177 }
178
179
180 double OBElementTable::GetElectronAffinity(int atomicnum)
181 {
182 if (!_init)
183 Init();
184
185 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
186 return(0.0);
187
188 return(_element[atomicnum]->GetElectronAffinity());
189 }
190
191 vector<double> OBElementTable::GetRGB(int atomicnum)
192 {
193 if (!_init)
194 Init();
195
196 vector <double> colors;
197 colors.reserve(3);
198
199 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
200 {
201 colors.push_back(0.0f);
202 colors.push_back(0.0f);
203 colors.push_back(0.0f);
204 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 }
213
214 string OBElementTable::GetName(int atomicnum)
215 {
216 if (!_init)
217 Init();
218
219 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
220 return("Unknown");
221
222 return(_element[atomicnum]->GetName());
223 }
224
225 double OBElementTable::GetVdwRad(int atomicnum)
226 {
227 if (!_init)
228 Init();
229
230 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
231 return(0.0);
232
233 return(_element[atomicnum]->GetVdwRad());
234 }
235
236 double OBElementTable::CorrectedBondRad(int atomicnum, int hyb)
237 {
238 double rad;
239 if (!_init)
240 Init();
241
242 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
243 return(1.0);
244
245 rad = _element[atomicnum]->GetCovalentRad();
246
247 if (hyb == 2)
248 rad *= 0.95;
249 else if (hyb == 1)
250 rad *= 0.90;
251
252 return(rad);
253 }
254
255 double OBElementTable::CorrectedVdwRad(int atomicnum, int hyb)
256 {
257 double rad;
258 if (!_init)
259 Init();
260
261 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
262 return(1.95);
263
264 rad = _element[atomicnum]->GetVdwRad();
265
266 if (hyb == 2)
267 rad *= 0.95;
268 else if (hyb == 1)
269 rad *= 0.90;
270
271 return(rad);
272 }
273
274 double OBElementTable::GetCovalentRad(int atomicnum)
275 {
276 if (!_init)
277 Init();
278
279 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
280 return(0.0);
281
282 return(_element[atomicnum]->GetCovalentRad());
283 }
284
285 double OBElementTable::GetMass(int atomicnum)
286 {
287 if (!_init)
288 Init();
289
290 if (atomicnum < 0 || atomicnum > static_cast<int>(_element.size()))
291 return(0.0);
292
293 return(_element[atomicnum]->GetMass());
294 }
295
296 int OBElementTable::GetAtomicNum(const char *sym)
297 {
298 int temp;
299 return GetAtomicNum(sym, temp);
300 }
301
302 int OBElementTable::GetAtomicNum(const char *sym, int &iso)
303 {
304 if (!_init)
305 Init();
306
307 vector<OBElement*>::iterator i;
308 for (i = _element.begin();i != _element.end();i++)
309 if (!strncasecmp(sym,(*i)->GetSymbol(),2))
310 return((*i)->GetAtomicNum());
311 if (strcasecmp(sym, "D") == 0)
312 {
313 iso = 2;
314 return(1);
315 }
316 else if (strcasecmp(sym, "T") == 0)
317 {
318 iso = 3;
319 return(1);
320 }
321 else
322 iso = 0;
323 return(0);
324 }
325
326 /** \class OBIsotopeTable
327 \brief Table of atomic isotope masses
328
329 */
330
331 OBIsotopeTable::OBIsotopeTable()
332 {
333 _init = false;
334 STR_DEFINE(_dir, FRC_PATH );
335 _envvar = "FORCE_PARAM_PATH";
336 _filename = "isotope.txt";
337 _subdir = "data";
338 _dataptr = IsotopeData;
339 }
340
341 void OBIsotopeTable::ParseLine(const char *buffer)
342 {
343 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 {
352 tokenize(vs,buffer);
353 if (vs.size() > 3) // atomic number, 0, most abundant mass (...)
354 {
355 atomicNum = atoi(vs[0].c_str());
356 for (i = 1; i < vs.size() - 1; i += 2) // make sure i+1 still exists
357 {
358 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 }
362 _isotopes.push_back(row);
363 }
364 else
365 obErrorLog.ThrowError(__func__, " Could not parse line in isotope table isotope.txt", obInfo);
366 }
367 }
368
369 double OBIsotopeTable::GetExactMass(const unsigned int ele,
370 const unsigned int isotope)
371 {
372 if (!_init)
373 Init();
374
375 if (ele > _isotopes.size())
376 return 0.0;
377
378 unsigned int iso;
379 for (iso = 0; iso < _isotopes[ele].size(); iso++)
380 if (isotope == _isotopes[ele][iso].first)
381 return _isotopes[ele][iso].second;
382
383 return 0.0;
384 }
385
386 /** \class OBTypeTable
387 \brief Atom Type Translation Table
388
389 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
401 \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
415 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
435 OBTypeTable::OBTypeTable()
436 {
437 _init = false;
438 STR_DEFINE(_dir, FRC_PATH );
439 _envvar = "FORCE_PARAM_PATH";
440 _filename = "types.txt";
441 _subdir = "data";
442 _dataptr = TypesData;
443 _linecount = 0;
444 _from = _to = -1;
445 }
446
447 void OBTypeTable::ParseLine(const char *buffer)
448 {
449 if (buffer[0] == '#')
450 return; // just a comment line
451
452 if (_linecount == 0)
453 sscanf(buffer,"%d%d",&_nrows,&_ncols);
454 else if (_linecount == 1)
455 tokenize(_colnames,buffer);
456 else
457 {
458 vector<string> vc;
459 tokenize(vc,buffer);
460 if (vc.size() == (unsigned)_ncols)
461 _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 _linecount++;
471 }
472
473 bool OBTypeTable::SetFromType(const char* from)
474 {
475 if (!_init)
476 Init();
477
478 string tmp = from;
479
480 unsigned int i;
481 for (i = 0;i < _colnames.size();i++)
482 if (tmp == _colnames[i])
483 {
484 _from = i;
485 return(true);
486 }
487
488 obErrorLog.ThrowError(__func__, "Requested type column not found", obInfo);
489
490 return(false);
491 }
492
493 bool OBTypeTable::SetToType(const char* to)
494 {
495 if (!_init)
496 Init();
497
498 string tmp = to;
499
500 unsigned int i;
501 for (i = 0;i < _colnames.size();i++)
502 if (tmp == _colnames[i])
503 {
504 _to = i;
505 return(true);
506 }
507
508 obErrorLog.ThrowError(__func__, "Requested type column not found", obInfo);
509
510 return(false);
511 }
512
513 //! 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 if (!_init)
520 Init();
521
522 bool rval;
523 string sto,sfrom;
524 sfrom = from;
525 rval = Translate(sto,sfrom);
526 strncpy(to,(char*)sto.c_str(), sizeof(to) - 1);
527 to[sizeof(to) - 1] = '\0';
528
529 return(rval);
530 }
531
532 bool OBTypeTable::Translate(string &to, const string &from)
533 {
534 if (!_init)
535 Init();
536
537 if (from == "")
538 return(false);
539
540 if (_from >= 0 && _to >= 0 &&
541 _from < _table.size() && _to < _table.size())
542 {
543 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 }
551
552 // Throw an error, copy the string and return false
553 obErrorLog.ThrowError(__func__, "Cannot perform atom type translation: table cannot find requested types.", obWarning);
554 to = from;
555 return(false);
556 }
557
558 std::string OBTypeTable::GetFromType()
559 {
560 if (!_init)
561 Init();
562
563 if (_from > 0 && _from < _table.size())
564 return( _colnames[_from] );
565 else
566 return( _colnames[0] );
567 }
568
569 std::string OBTypeTable::GetToType()
570 {
571 if (!_init)
572 Init();
573
574 if (_to > 0 && _to < _table.size())
575 return( _colnames[_to] );
576 else
577 return( _colnames[0] );
578 }
579
580 void Toupper(string &s)
581 {
582 unsigned int i;
583 for (i = 0;i < s.size();i++)
584 s[i] = toupper(s[i]);
585 }
586
587 void Tolower(string &s)
588 {
589 unsigned int i;
590 for (i = 0;i < s.size();i++)
591 s[i] = tolower(s[i]);
592 }
593
594 ///////////////////////////////////////////////////////////////////////
595 OBResidueData::OBResidueData()
596 {
597 _init = false;
598 STR_DEFINE(_dir, FRC_PATH );
599 _envvar = "FORCE_PARAM_PATH";
600 _filename = "resdata.txt";
601 _subdir = "data";
602 _dataptr = ResidueData;
603 }
604
605 bool OBResidueData::AssignBonds(OBMol &mol,OBBitVec &bv)
606 {
607 if (!_init)
608 Init();
609
610 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 {
621 r1 = a1->GetResidue();
622 if (skipres && r1->GetNum() == skipres)
623 continue;
624
625 if (r1->GetName() != rname)
626 {
627 skipres = SetResName(r1->GetName()) ? 0 : r1->GetNum();
628 rname = r1->GetName();
629 }
630 //assign bonds for each atom
631 for (j=i,a2 = mol.NextAtom(j);a2;a2 = mol.NextAtom(j))
632 {
633 r2 = a2->GetResidue();
634 if (r1->GetNum() != r2->GetNum())
635 break;
636 if (r1->GetName() != r2->GetName())
637 break;
638
639 if ((bo = LookupBO(r1->GetAtomID(a1),r2->GetAtomID(a2))))
640 {
641 v = a1->GetVector() - a2->GetVector();
642 if (v.length_2() < 3.5) //check by distance
643 mol.AddBond(a1->GetIdx(),a2->GetIdx(),bo);
644 }
645 }
646 }
647
648 int hyb;
649 string type;
650
651 //types and hybridization
652 rname = ""; // name of current residue
653 skipres = 0; // don't skip any residues right now
654 for (a1 = mol.BeginAtom(i);a1;a1 = mol.NextAtom(i))
655 {
656 if (a1->IsOxygen() && !a1->GetValence())
657 {
658 a1->SetType("O3");
659 continue;
660 }
661 if (a1->IsHydrogen())
662 {
663 a1->SetType("H");
664 continue;
665 }
666
667 //***valence rule for O-
668 if (a1->IsOxygen() && a1->GetValence() == 1)
669 {
670 OBBond *bond;
671 bond = (OBBond*)*(a1->BeginBonds());
672 if (bond->GetBO() == 2)
673 {
674 a1->SetType("O2");
675 a1->SetHyb(2);
676 }
677 else if (bond->GetBO() == 1)
678 {
679 a1->SetType("O-");
680 a1->SetHyb(3);
681 a1->SetFormalCharge(-1);
682 }
683 continue;
684 }
685
686 r1 = a1->GetResidue();
687 if (skipres && r1->GetNum() == skipres)
688 continue;
689
690 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 return(true);
707 }
708
709 void OBResidueData::ParseLine(const char *buffer)
710 {
711 int bo;
712 string s;
713 vector<string> vs;
714
715 if (buffer[0] == '#')
716 return;
717
718 tokenize(vs,buffer);
719 if (!vs.empty())
720 {
721 if (vs[0] == "BOND")
722 {
723 s = (vs[1] < vs[2]) ? vs[1] + " " + vs[2] :
724 vs[2] + " " + vs[1];
725 bo = atoi(vs[3].c_str());
726 _vtmp.push_back(pair<string,int> (s,bo));
727 }
728
729 if (vs[0] == "ATOM" && vs.size() == 4)
730 {
731 _vatmtmp.push_back(vs[1]);
732 _vatmtmp.push_back(vs[2]);
733 _vatmtmp.push_back(vs[3]);
734 }
735
736 if (vs[0] == "RES")
737 _resname.push_back(vs[1]);
738
739 if (vs[0]== "END")
740 {
741 _resatoms.push_back(_vatmtmp);
742 _resbonds.push_back(_vtmp);
743 _vtmp.clear();
744 _vatmtmp.clear();
745 }
746 }
747 }
748
749 bool OBResidueData::SetResName(const string &s)
750 {
751 if (!_init)
752 Init();
753
754 unsigned int i;
755
756 for (i = 0;i < _resname.size();i++)
757 if (_resname[i] == s)
758 {
759 _resnum = i;
760 return(true);
761 }
762
763 _resnum = -1;
764 return(false);
765 }
766
767 int OBResidueData::LookupBO(const string &s)
768 {
769 if (_resnum == -1)
770 return(0);
771
772 unsigned int i;
773 for (i = 0;i < _resbonds[_resnum].size();i++)
774 if (_resbonds[_resnum][i].first == s)
775 return(_resbonds[_resnum][i].second);
776
777 return(0);
778 }
779
780 int OBResidueData::LookupBO(const string &s1, const string &s2)
781 {
782 if (_resnum == -1)
783 return(0);
784 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 if (_resbonds[_resnum][i].first == s)
791 return(_resbonds[_resnum][i].second);
792
793 return(0);
794 }
795
796 bool OBResidueData::LookupType(const string &atmid,string &type,int &hyb)
797 {
798 if (_resnum == -1)
799 return(false);
800
801 string s;
802 vector<string>::iterator i;
803
804 for (i = _resatoms[_resnum].begin();i != _resatoms[_resnum].end();i+=3)
805 if (atmid == *i)
806 {
807 i++;
808 type = *i;
809 i++;
810 hyb = atoi((*i).c_str());
811 return(true);
812 }
813
814 return(false);
815 }
816
817 void OBGlobalDataBase::Init()
818 {
819 if (_init)
820 return;
821 _init = true;
822
823 string buffer, subbuffer;
824 ifstream ifs1, ifs2, ifs3, ifs4, *ifsP;
825 // First, look for an environment variable
826 if (getenv(_envvar.c_str()) != NULL)
827 {
828 buffer = getenv(_envvar.c_str());
829 buffer += FILE_SEP_CHAR;
830
831 if (!_subdir.empty())
832 {
833 subbuffer = buffer;
834 subbuffer += _subdir;
835 subbuffer += FILE_SEP_CHAR;
836 }
837
838 buffer += _filename;
839 subbuffer += _filename;
840
841 ifs1.open(subbuffer.c_str());
842 ifsP= &ifs1;
843 if (!(*ifsP))
844 {
845 ifs2.open(buffer.c_str());
846 ifsP = &ifs2;
847 }
848 }
849 // Then, check the configured data directory
850 else // if (!(*ifsP))
851 {
852 buffer = _dir;
853 buffer += FILE_SEP_CHAR;
854
855 subbuffer = buffer;
856 subbuffer += BABEL_VERSION;
857 subbuffer += FILE_SEP_CHAR;
858
859 subbuffer += _filename;
860 buffer += _filename;
861
862 ifs3.open(subbuffer.c_str());
863 ifsP= &ifs3;
864 if (!(*ifsP))
865 {
866 ifs4.open(buffer.c_str());
867 ifsP = &ifs4;
868 }
869 }
870
871 char charBuffer[BUFF_SIZE];
872 if ((*ifsP))
873 {
874 while(ifsP->getline(charBuffer,BUFF_SIZE))
875 ParseLine(charBuffer);
876 }
877
878 else
879 // If all else fails, use the compiled in values
880 if (_dataptr)
881 {
882 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 }
892 else
893 {
894 string s = "Unable to open data file '";
895 s += _filename;
896 s += "'";
897 obErrorLog.ThrowError(__func__, s, obWarning);
898 }
899
900 if (ifs1)
901 ifs1.close();
902 if (ifs2)
903 ifs2.close();
904 if (ifs3)
905 ifs3.close();
906 if (ifs4)
907 ifs4.close();
908
909 if (GetSize() == 0)
910 {
911 string s = "Cannot initialize database '";
912 s += _filename;
913 s += "' which may cause further errors.";
914 obErrorLog.ThrowError(__func__, "Cannot initialize database", obWarning);
915 }
916
917 }
918
919 } // end namespace OpenBabel
920
921 //! \file data.cpp
922 //! \brief Global data and resource file parsers.