/src/openbabel/src/formats/chem3dformat.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc. |
3 | | Some portions Copyright (C) 2001-2006 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 | | #include <openbabel/babelconfig.h> |
16 | | |
17 | | #include <openbabel/math/matrix3x3.h> |
18 | | #include <openbabel/obmolecformat.h> |
19 | | #include <openbabel/mol.h> |
20 | | #include <openbabel/atom.h> |
21 | | #include <openbabel/elements.h> |
22 | | #include <openbabel/data.h> |
23 | | #include <cstdlib> |
24 | | |
25 | | |
26 | | using namespace std; |
27 | | namespace OpenBabel |
28 | | { |
29 | | |
30 | | class CHEM3D1Format : public OBMoleculeFormat |
31 | | { |
32 | | public: |
33 | | //Register this format type ID |
34 | | CHEM3D1Format() |
35 | 6 | { |
36 | 6 | OBConversion::RegisterFormat("c3d1",this); |
37 | 6 | } |
38 | | |
39 | | const char* Description() override // required |
40 | 0 | { |
41 | 0 | return |
42 | 0 | "Chem3D Cartesian 1 format\n" |
43 | 0 | "No comments yet\n"; |
44 | 0 | } |
45 | | |
46 | | const char* SpecificationURL() override |
47 | 0 | { return ""; } // optional |
48 | | |
49 | | //Flags() can return be any the following combined by | or be omitted if none apply |
50 | | // NOTREADABLE READONEONLY NOTWRITABLE WRITEONEONLY |
51 | | unsigned int Flags() override |
52 | 7 | { |
53 | 7 | return READONEONLY; |
54 | 7 | } |
55 | | |
56 | | //*** This section identical for most OBMol conversions *** |
57 | | //////////////////////////////////////////////////// |
58 | | /// The "API" interface functions |
59 | | bool ReadMolecule(OBBase* pOb, OBConversion* pConv) override; |
60 | | bool WriteMolecule(OBBase* pOb, OBConversion* pConv) override; |
61 | | |
62 | | static bool ReadChem3d(istream &ifs,OBMol &mol,bool mmads,const char *type_key); |
63 | | static bool WriteChem3d(ostream &ofs,OBMol &mol, const char *mol_typ); |
64 | | |
65 | | }; |
66 | | //*** |
67 | | |
68 | | //Make an instance of the format class |
69 | | CHEM3D1Format theCHEM3D1Format; |
70 | | |
71 | | ///////////////////////////////////////////////////////////////// |
72 | | bool CHEM3D1Format::ReadMolecule(OBBase* pOb, OBConversion* pConv) |
73 | 0 | { |
74 | |
|
75 | 0 | OBMol* pmol = pOb->CastAndClear<OBMol>(); |
76 | 0 | if (pmol == nullptr) |
77 | 0 | return false; |
78 | | |
79 | | //Define some references so we can use the old parameter names |
80 | 0 | istream &ifs = *pConv->GetInStream(); |
81 | 0 | OBMol &mol = *pmol; |
82 | 0 | mol.SetTitle( pConv->GetTitle()); //default title is the filename |
83 | |
|
84 | 0 | return(ReadChem3d(ifs,mol,false,"MM2")); |
85 | 0 | } |
86 | | |
87 | | //////////////////////////////////////////////////////////////// |
88 | | |
89 | | bool CHEM3D1Format::WriteMolecule(OBBase* pOb, OBConversion* pConv) |
90 | 0 | { |
91 | 0 | OBMol* pmol = dynamic_cast<OBMol*>(pOb); |
92 | 0 | if (pmol == nullptr) |
93 | 0 | return false; |
94 | | |
95 | | //Define some references so we can use the old parameter names |
96 | 0 | ostream &ofs = *pConv->GetOutStream(); |
97 | 0 | OBMol &mol = *pmol; |
98 | |
|
99 | 0 | return(WriteChem3d(ofs,mol,"MM2")); |
100 | 0 | } |
101 | | |
102 | | //*********************************************************** |
103 | | class CHEM3D2Format : public OBMoleculeFormat |
104 | | { |
105 | | public: |
106 | | //Register this format type ID |
107 | | CHEM3D2Format() |
108 | 6 | { |
109 | 6 | OBConversion::RegisterFormat("c3d2",this); |
110 | 6 | } |
111 | | |
112 | | const char* Description() override // required |
113 | 0 | { |
114 | 0 | return |
115 | 0 | "Chem3D Cartesian 2 format\n" |
116 | 0 | "No comments yet\n"; |
117 | 0 | } |
118 | | |
119 | | const char* SpecificationURL() override |
120 | 0 | { return ""; } // optional |
121 | | |
122 | | //Flags() can return be any the following combined by | or be omitted if none apply |
123 | | // NOTREADABLE READONEONLY NOTWRITABLE WRITEONEONLY |
124 | | unsigned int Flags() override |
125 | 6 | { |
126 | 6 | return READONEONLY; |
127 | 6 | } |
128 | | |
129 | | //*** This section identical for most OBMol conversions *** |
130 | | //////////////////////////////////////////////////// |
131 | | /// The "API" interface functions |
132 | | bool ReadMolecule(OBBase* pOb, OBConversion* pConv) override; |
133 | | bool WriteMolecule(OBBase* pOb, OBConversion* pConv) override; |
134 | | }; |
135 | | //*** |
136 | | |
137 | | //Make an instance of the format class |
138 | | CHEM3D2Format theCHEM3D2Format; |
139 | | |
140 | | ///////////////////////////////////////////////////////////////// |
141 | | bool CHEM3D2Format::ReadMolecule(OBBase* pOb, OBConversion* pConv) |
142 | 0 | { |
143 | |
|
144 | 0 | OBMol* pmol = pOb->CastAndClear<OBMol>(); |
145 | 0 | if (pmol == nullptr) |
146 | 0 | return false; |
147 | | |
148 | | //Define some references so we can use the old parameter names |
149 | 0 | istream &ifs = *pConv->GetInStream(); |
150 | 0 | OBMol &mol = *pmol; |
151 | 0 | mol.SetTitle( pConv->GetTitle()); //default title is the filename |
152 | |
|
153 | 0 | return(CHEM3D1Format::ReadChem3d(ifs,mol,false,"C3D")); |
154 | 0 | } |
155 | | |
156 | | //////////////////////////////////////////////////////////////// |
157 | | |
158 | | bool CHEM3D2Format::WriteMolecule(OBBase* pOb, OBConversion* pConv) |
159 | 0 | { |
160 | 0 | OBMol* pmol = dynamic_cast<OBMol*>(pOb); |
161 | 0 | if (pmol == nullptr) |
162 | 0 | return false; |
163 | | |
164 | | //Define some references so we can use the old parameter names |
165 | 0 | ostream &ofs = *pConv->GetOutStream(); |
166 | 0 | OBMol &mol = *pmol; |
167 | |
|
168 | 0 | return(CHEM3D1Format::WriteChem3d(ofs,mol,"C3D")); |
169 | 0 | } |
170 | | |
171 | | //**************************************************************** |
172 | | |
173 | | bool CHEM3D1Format::ReadChem3d(istream &ifs,OBMol &mol,bool mmads,const char *type_key) |
174 | 0 | { |
175 | 0 | char buffer[BUFF_SIZE]; |
176 | 0 | int natoms,i; |
177 | 0 | char tmp[16],tmp1[16]; |
178 | 0 | char atomic_type[16]; |
179 | 0 | double exponent = 0.0; |
180 | 0 | double divisor = 1.0; |
181 | 0 | double Alpha,Beta,Gamma,A,B,C; |
182 | 0 | bool has_fractional = false, has_divisor = false; |
183 | 0 | matrix3x3 m; |
184 | |
|
185 | 0 | vector<string> vs; |
186 | 0 | ifs.getline(buffer,BUFF_SIZE); |
187 | 0 | tokenize(vs,buffer); |
188 | |
|
189 | 0 | if (mmads) |
190 | 0 | { |
191 | 0 | if (vs.empty()) |
192 | 0 | return(false); |
193 | 0 | natoms = atoi((char*)vs[0].c_str()); |
194 | 0 | if (vs.size() == 2) |
195 | 0 | mol.SetTitle(vs[1]); |
196 | 0 | } |
197 | 0 | else |
198 | 0 | { |
199 | 0 | switch(vs.size()) |
200 | 0 | { |
201 | 0 | case 7 : |
202 | 0 | sscanf(buffer,"%d%lf%lf%lf%lf%lf%lf", |
203 | 0 | &natoms,&Alpha,&Beta,&Gamma,&A,&B,&C); |
204 | 0 | m.FillOrth(Alpha,Beta,Gamma,A,B,C); |
205 | 0 | has_fractional = true; |
206 | 0 | break; |
207 | 0 | case 8 : |
208 | 0 | sscanf(buffer,"%d%lf%lf%lf%lf%lf%lf%lf", |
209 | 0 | &natoms,&Alpha,&Beta,&Gamma,&A,&B,&C,&exponent); |
210 | 0 | m.FillOrth(Alpha,Beta,Gamma,A,B,C); |
211 | 0 | has_fractional = true; |
212 | 0 | has_divisor = true; |
213 | 0 | break; |
214 | 0 | default : |
215 | 0 | sscanf(buffer,"%d",&natoms); |
216 | 0 | break; |
217 | 0 | } |
218 | 0 | } |
219 | | |
220 | 0 | if (!natoms) |
221 | 0 | return(false); |
222 | 0 | divisor = pow(10.0,exponent); |
223 | 0 | mol.ReserveAtoms(natoms); |
224 | |
|
225 | 0 | ttab.SetToType("INT"); |
226 | 0 | ttab.SetFromType(type_key); |
227 | |
|
228 | 0 | OBAtom *atom; |
229 | 0 | double x,y,z; |
230 | 0 | vector3 v; |
231 | |
|
232 | 0 | unsigned int k; |
233 | 0 | for (i = 1; i <= natoms; i++) |
234 | 0 | { |
235 | 0 | ifs.getline(buffer,BUFF_SIZE); |
236 | 0 | sscanf(buffer,"%15s%*d%lf%lf%lf%15s", |
237 | 0 | atomic_type, |
238 | 0 | &x, |
239 | 0 | &y, |
240 | 0 | &z, |
241 | 0 | tmp); |
242 | 0 | v.Set(x,y,z); |
243 | 0 | if (has_fractional) |
244 | 0 | v *= m; |
245 | 0 | if (has_divisor) |
246 | 0 | v/= divisor; |
247 | |
|
248 | 0 | tokenize(vs,buffer); |
249 | 0 | if (vs.empty()) |
250 | 0 | return(false); |
251 | | |
252 | 0 | atom = mol.NewAtom(); |
253 | 0 | ttab.Translate(tmp1,tmp); |
254 | 0 | atom->SetType(tmp1); |
255 | 0 | atom->SetVector(v); |
256 | 0 | atom->SetAtomicNum(OBElements::GetAtomicNum(atomic_type)); |
257 | |
|
258 | 0 | for (k = 6;k < vs.size(); k++) |
259 | 0 | mol.AddBond(atom->GetIdx(),atoi((char*)vs[k].c_str()),1); |
260 | 0 | } |
261 | | |
262 | | // clean out remaining blank lines |
263 | 0 | std::streampos ipos; |
264 | 0 | do |
265 | 0 | { |
266 | 0 | ipos = ifs.tellg(); |
267 | 0 | ifs.getline(buffer,BUFF_SIZE); |
268 | 0 | } |
269 | 0 | while(strlen(buffer) == 0 && !ifs.eof() ); |
270 | 0 | ifs.seekg(ipos); |
271 | |
|
272 | 0 | mol.PerceiveBondOrders(); |
273 | |
|
274 | 0 | return(true); |
275 | 0 | } |
276 | | |
277 | | bool CHEM3D1Format::WriteChem3d(ostream &ofs,OBMol &mol, const char *mol_typ) |
278 | 0 | { |
279 | 0 | int atnum; |
280 | 0 | int type_num; |
281 | 0 | char buffer[BUFF_SIZE],type_name[16],ele_type[16]; |
282 | |
|
283 | 0 | ofs << mol.NumAtoms(); |
284 | 0 | if (EQ(mol_typ,"MMADS")) |
285 | 0 | { |
286 | 0 | ofs << " " << mol.GetTitle(); |
287 | 0 | ttab.SetToType("MM2"); |
288 | 0 | } |
289 | 0 | else |
290 | 0 | ttab.SetToType(mol_typ); |
291 | 0 | ofs << endl; |
292 | |
|
293 | 0 | ttab.SetFromType("INT"); |
294 | |
|
295 | 0 | OBAtom *atom,*nbr; |
296 | 0 | vector<OBAtom*>::iterator i; |
297 | 0 | vector<OBBond*>::iterator j; |
298 | |
|
299 | 0 | for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) |
300 | 0 | { |
301 | 0 | if (!ttab.Translate(type_name,atom->GetType())) |
302 | 0 | { |
303 | 0 | snprintf(buffer, BUFF_SIZE, |
304 | 0 | "Unable to assign %s type to atom %d type = %s\n", |
305 | 0 | mol_typ,atom->GetIdx(),atom->GetType()); |
306 | 0 | obErrorLog.ThrowError(__FUNCTION__, buffer, obInfo); |
307 | 0 | atnum = atom->GetAtomicNum(); |
308 | 0 | type_num = atnum * 10 + atom->GetExplicitDegree(); |
309 | 0 | snprintf(type_name, sizeof(type_num), "%d",type_num); |
310 | 0 | } |
311 | 0 | strncpy(ele_type, OBElements::GetSymbol(atom->GetAtomicNum()), sizeof(ele_type)); |
312 | 0 | ele_type[sizeof(ele_type) - 1] = '\0'; |
313 | 0 | snprintf(buffer, BUFF_SIZE, "%-3s %-5d %8.4f %8.4f %8.4f %5s", |
314 | 0 | ele_type, |
315 | 0 | atom->GetIdx(), |
316 | 0 | atom->x(), |
317 | 0 | atom->y(), |
318 | 0 | atom->z(), |
319 | 0 | type_name); |
320 | 0 | ofs << buffer; |
321 | |
|
322 | 0 | for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j)) |
323 | 0 | { |
324 | 0 | snprintf(buffer, BUFF_SIZE, "%6d",nbr->GetIdx()); |
325 | 0 | ofs << buffer; |
326 | 0 | } |
327 | 0 | ofs << endl; |
328 | 0 | } |
329 | 0 | return(true); |
330 | 0 | } |
331 | | |
332 | | } //namespace OpenBabel |