1 /**********************************************************************
2 Copyright (C) 2004 by Chris Morley
3 
4 This file is part of the Open Babel project.
5 For more information, see <http://openbabel.org/>
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation version 2 of the License.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 ***********************************************************************/
16 #include <openbabel/babelconfig.h>
17 
18 #include <openbabel/obmolecformat.h>
19 #include <openbabel/mol.h>
20 #include <openbabel/atom.h>
21 #include <openbabel/bond.h>
22 #include <openbabel/obiter.h>
23 #include <openbabel/elements.h>
24 
25 
26 const double AAU = 0.5291772108;  // �ngstr�m per bohr (CODATA 2002)
27 
28 using namespace std;
29 namespace OpenBabel
30 {
31 
32 class TurbomoleFormat : public OBMoleculeFormat
33 {
34 public:
35     //Register this format type ID
TurbomoleFormat()36     TurbomoleFormat()
37     {
38       OBConversion::RegisterFormat("tmol",this);
39       OBConversion::RegisterOptionParam("a", this, OBConversion::INOPTIONS);
40     }
41 
Description()42   virtual const char* Description() //required
43   {
44     return
45       "TurboMole Coordinate format\n"
46       "Write options e.g.-xa\n"
47       " a  Output Angstroms\n\n"
48       "Read Options e.g. -as\n"
49       " s  Output single bonds only\n"
50       " b  Disable bonding entirely\n"
51       " a  Input in Angstroms\n\n" ;
52   };
53 
SpecificationURL()54   virtual const char* SpecificationURL()
55   {return "http://www.cosmologic.de/QuantumChemistry/main_qChemistry.html";};
56 
57     //Flags() can return be any the following combined by | or be omitted if none apply
58     // NOTREADABLE  READONEONLY  NOTWRITABLE  WRITEONEONLY
Flags()59     virtual unsigned int Flags()
60     {
61         return READONEONLY | WRITEONEONLY;
62     };
63 
64     //*** This section identical for most OBMol conversions ***
65     ////////////////////////////////////////////////////
66     /// The "API" interface functions
67     virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
68     virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
69 };
70 //***
71 
72 //Make an instance of the format class
73 TurbomoleFormat theTurbomoleFormat;
74 
75 /////////////////////////////////////////////////////////////////
ReadMolecule(OBBase * pOb,OBConversion * pConv)76 bool TurbomoleFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
77 {
78     OBMol* pmol = pOb->CastAndClear<OBMol>();
79     if (pmol == nullptr)
80         return false;
81 
82     //Define some references so we can use the old parameter names
83     istream &ifs = *pConv->GetInStream();
84     OBMol &mol = *pmol;
85     double UnitConv=AAU;
86     if(pConv->IsOption("a", OBConversion::INOPTIONS))
87       UnitConv=1;
88 
89 
90     char buffer[BUFF_SIZE];
91     do
92     {
93         ifs.getline(buffer,BUFF_SIZE);
94 	if (ifs.peek() == EOF || !ifs.good())
95 	  return false;
96     }
97     while(strncmp(buffer,"$coord",6));
98 
99     mol.BeginModify();
100     OBAtom atom;
101     while(!(!ifs))
102     {
103         ifs.getline(buffer,BUFF_SIZE);
104         if(*buffer=='$')
105             break;
106         if(*buffer=='#')
107             continue;
108         float x,y,z;
109         char atomtype[8];
110         if(sscanf(buffer,"%f %f %f %7s",&x,&y,&z,atomtype)!=4)
111             return false;
112 
113         atom.SetVector(x*UnitConv, y*UnitConv, z*UnitConv);
114         atom.SetAtomicNum(OBElements::GetAtomicNum(atomtype));
115         atom.SetType(atomtype);
116 
117         if(!mol.AddAtom(atom))
118             return false;
119         atom.Clear();
120     }
121     while(!(!ifs) && strncmp(buffer,"$end",4))
122         ifs.getline(buffer,BUFF_SIZE);
123 
124     if (!pConv->IsOption("b",OBConversion::INOPTIONS))
125       mol.ConnectTheDots();
126     if (!pConv->IsOption("s",OBConversion::INOPTIONS) && !pConv->IsOption("b",OBConversion::INOPTIONS))
127       mol.PerceiveBondOrders();
128 
129     // clean out remaining blank lines
130     std::streampos ipos;
131     do
132     {
133       ipos = ifs.tellg();
134       ifs.getline(buffer,BUFF_SIZE);
135     }
136     while(strlen(buffer) == 0 && !ifs.eof() );
137     ifs.seekg(ipos);
138 
139     mol.EndModify();
140     return true;
141 }
142 
143 ////////////////////////////////////////////////////////////////
144 
strlwr(char * s)145 char *strlwr(char *s)
146 {
147     if (s != nullptr)
148       {
149         char *p;
150         for (p = s; *p; ++p)
151             *p = tolower(*p);
152       }
153     return s;
154 }
155 
156 
WriteMolecule(OBBase * pOb,OBConversion * pConv)157 bool TurbomoleFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
158 {
159     OBMol* pmol = dynamic_cast<OBMol*>(pOb);
160     if (pmol == nullptr)
161         return false;
162 
163     //Define some references so we can use the old parameter names
164     ostream &ofs = *pConv->GetOutStream();
165     OBMol &mol = *pmol;
166     double UnitConv=AAU;
167     if(pConv->IsOption("a"))
168       UnitConv=1;
169 
170     ofs << "$coord" <<endl;
171 
172     char buffer[BUFF_SIZE];
173     OBAtom *atom;
174     vector<OBAtom*>::iterator i;
175     for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
176     {
177       char symb[8];
178       strcpy(symb,OBElements::GetSymbol(atom->GetAtomicNum()));
179         snprintf(buffer, BUFF_SIZE, "%20.14f  %20.14f  %20.14f      %s",
180                 atom->GetX()/UnitConv,
181                 atom->GetY()/UnitConv,
182                 atom->GetZ()/UnitConv,
183                 strlwr(symb) );
184         ofs << buffer << endl;
185     }
186     ofs << "$end" << endl;
187 
188     return true;
189 }
190 
191 } //namespace OpenBabel
192