ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/openbabel/xyzformat.cpp
Revision: 2440
Committed: Wed Nov 16 19:42:11 2005 UTC (18 years, 9 months ago) by tim
File size: 8514 byte(s)
Log Message:
adding openbabel

File Contents

# Content
1 /**********************************************************************
2 Copyright (C) 2000 by OpenEye Scientific Software, Inc.
3 Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
4 Some portions Copyright (C) 2004 by Chris Morley
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 2 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 ***********************************************************************/
15
16 #include "mol.hpp"
17 #include "obconversion.hpp"
18 #include "obmolecformat.hpp"
19
20 #ifdef HAVE_SSTREAM
21 #include <sstream>
22 #else
23 #include <strstream>
24 #endif
25
26 using namespace std;
27 namespace OpenBabel
28 {
29
30 class XYZFormat : public OBMoleculeFormat
31 {
32 public:
33 //Register this format type ID
34 XYZFormat()
35 {
36 OBConversion::RegisterFormat("xyz", this, "chemical/x-xyz");
37 }
38
39 virtual const char* Description() //required
40 {
41 return
42 "XYZ cartesian coordinates format\n \
43 Read Options e.g. -as\n\
44 s Output single bonds only\n\
45 b Disable bonding entirely\n\n";
46 };
47
48 virtual const char* SpecificationURL()
49 {return "http://openbabel.sourceforge.net/formats/xyz.shtml";}; //optional
50
51 virtual const char* GetMIMEType()
52 { return "chemical/x-xyz"; };
53
54 //*** This section identical for most OBMol conversions ***
55 ////////////////////////////////////////////////////
56 /// The "API" interface functions
57 virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
58 virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
59 };
60 //***
61
62 //Make an instance of the format class
63 XYZFormat theXYZFormat;
64
65 /////////////////////////////////////////////////////////////////
66 bool XYZFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
67 {
68 OBMol* pmol = dynamic_cast<OBMol*>(pOb);
69 if(pmol==NULL)
70 return false;
71
72 //Define some references so we can use the old parameter names
73 istream &ifs = *pConv->GetInStream();
74 OBMol &mol = *pmol;
75 const char* title = pConv->GetTitle();
76 char buffer[BUFF_SIZE];
77
78 #ifdef HAVE_SSTREAM
79 stringstream errorMsg;
80 #else
81 strstream errorMsg;
82 #endif
83
84 unsigned int natoms; // [ejk] assumed natoms could not be -ve
85
86 if (!ifs.getline(buffer,BUFF_SIZE))
87 {
88 obErrorLog.ThrowError(__FUNCTION__,
89 "Problems reading an XYZ file: Cannot read the first line.", obWarning);
90 return(false);
91 }
92
93 if (sscanf(buffer, "%d", &natoms) == 0 || !natoms)
94 {
95 obErrorLog.ThrowError(__FUNCTION__,
96 "Problems reading an XYZ file: The first line must contain the number of atoms.", obWarning);
97 return(false);
98 }
99
100 mol.ReserveAtoms(natoms);
101
102 // The next line contains a title string for the molecule. Use this
103 // as the title for the molecule if the line is not
104 // empty. Otherwise, use the title given by the calling function.
105 if (!ifs.getline(buffer,BUFF_SIZE))
106 {
107 obErrorLog.ThrowError(__FUNCTION__,
108 "Problems reading an XYZ file: Could not read the second line (title/comments).", obWarning);
109 return(false);
110 }
111 if (strlen(buffer) != 0)
112 mol.SetTitle(buffer);
113 else
114 mol.SetTitle(title);
115
116 mol.BeginModify();
117
118 // The next lines contain four items each, separated by white
119 // spaces: the atom type, and the coordinates of the atom
120 vector<string> vs;
121 for (unsigned int i = 1; i <= natoms; i ++)
122 {
123 if (!ifs.getline(buffer,BUFF_SIZE))
124 {
125 errorMsg << "Problems reading an XYZ file: "
126 << "Could not read line #" << i+2 << ", file error." << endl
127 << " According to line one, there should be " << natoms
128 << " atoms, and therefore " << natoms+2 << " lines in the file.";
129
130 obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obWarning);
131 return(false);
132 }
133 tokenize(vs,buffer);
134 if (vs.size() != 4)
135 {
136 errorMsg << "Problems reading an XYZ file: "
137 << "Could not read line #" << i+2 << "." << endl
138 << "OpenBabel found the line '" << buffer << "'" << endl
139 << "According to the specifications, this line should contain exactly 4 entries, separated by white space." << endl
140 << "However, OpenBabel found " << vs.size() << " items.";
141
142 obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obWarning);
143 return(false);
144 }
145
146 // Atom Type: get the atomic number from the element table, using
147 // the first entry in the currently read line. If the entry makes
148 // sense, set the atomic number and leave the atomic type open
149 // (the type is then later faulted in when atom->GetType() is
150 // called). If the entry does not make sense to use, set the atom
151 // type manually, assuming that the author of the xyz-file had
152 // something "special" in mind.
153 OBAtom *atom = mol.NewAtom();
154 int atomicNum = etab.GetAtomicNum(vs[0].c_str());
155 atom->SetAtomicNum(atomicNum); //set atomic number, or '0' if the atom type is not recognized
156 if (atomicNum == 0)
157 atom->SetType(vs[0]);
158
159 // Read the atom coordinates
160 char *endptr;
161 double x = strtod((char*)vs[1].c_str(),&endptr);
162 if (endptr == (char*)vs[1].c_str())
163 {
164 errorMsg << "Problems reading an XYZ file: "
165 << "Could not read line #" << i+2 << "." << endl
166 << "OpenBabel found the line '" << buffer << "'" << endl
167 << "According to the specifications, this line should contain exactly 4 entries, separated by white space." << endl
168 << "OpenBabel could not interpret item #1 as a number.";
169
170 obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obWarning);
171 return(false);
172 }
173 double y = strtod((char*)vs[2].c_str(),&endptr);
174 if (endptr == (char*)vs[2].c_str())
175 {
176 errorMsg << "Problems reading an XYZ file: "
177 << "Could not read line #" << i+2 << "." << endl
178 << "OpenBabel found the line '" << buffer << "'" << endl
179 << "According to the specifications, this line should contain exactly 4 entries, separated by white space." << endl
180 << "OpenBabel could not interpret item #2 as a number.";
181
182 obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obWarning);
183 return(false);
184 }
185 double z = strtod((char*)vs[3].c_str(),&endptr);
186 if (endptr == (char*)vs[3].c_str())
187 {
188 errorMsg << "Problems reading an XYZ file: "
189 << "Could not read line #" << i+2 << "." << endl
190 << "OpenBabel found the line '" << buffer << "'" << endl
191 << "According to the specifications, this line should contain exactly 4 entries, separated by white space." << endl
192 << "OpenBabel could not interpret item #3 as a number.";
193
194 obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obWarning);
195 return(false);
196 }
197 atom->SetVector(x,y,z); //set coordinates
198 }
199
200 // clean out any remaining blank lines
201 while(ifs.peek() != EOF && ifs.good() &&
202 (ifs.peek() == '\n' || ifs.peek() == '\r'))
203 ifs.getline(buffer,BUFF_SIZE);
204
205 if (!pConv->IsOption("b",OBConversion::INOPTIONS))
206 mol.ConnectTheDots();
207 if (!pConv->IsOption("s",OBConversion::INOPTIONS) && !pConv->IsOption("b",OBConversion::INOPTIONS))
208 mol.PerceiveBondOrders();
209
210 mol.EndModify();
211
212 return(true);
213 }
214
215 ////////////////////////////////////////////////////////////////
216
217 bool XYZFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
218 {
219 OBMol* pmol = dynamic_cast<OBMol*>(pOb);
220 if(pmol==NULL)
221 return false;
222
223 //Define some references so we can use the old parameter names
224 ostream &ofs = *pConv->GetOutStream();
225 OBMol &mol = *pmol;
226
227 unsigned int i;
228 char buffer[BUFF_SIZE];
229
230 sprintf(buffer,"%d", mol.NumAtoms());
231 ofs << buffer << endl;
232 sprintf(buffer,"%s\tEnergy: %15.7f", mol.GetTitle(), mol.GetEnergy());
233 ofs << buffer << endl;
234
235 OBAtom *atom;
236 string str,str1;
237 for(i = 1;i <= mol.NumAtoms(); i++)
238 {
239 atom = mol.GetAtom(i);
240 sprintf(buffer,"%3s%15.5f%15.5f%15.5f",
241 etab.GetSymbol(atom->GetAtomicNum()),
242 atom->GetX(),
243 atom->GetY(),
244 atom->GetZ());
245 ofs << buffer << endl;
246 }
247
248 return(true);
249 }
250
251 } //namespace OpenBabel