ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/atom2md/oopseformat.cpp
Revision: 1277
Committed: Mon Jul 14 12:35:58 2008 UTC (16 years, 9 months ago) by gezelter
File size: 12216 byte(s)
Log Message:
Changes for implementing Amber force field:  Added Inversions and
worked on BaseAtomTypes so that they'd function with the fortran side.

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 Some portions Copyright (C) 2008 by J. Daniel Gezelter
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
17 #include <openbabel/babelconfig.h>
18 #include <openbabel/obmolecformat.h>
19 #include <openbabel/obiter.h>
20 #include <openbabel/mol.h>
21 #include <openbabel/chains.h>
22 #include <fstream>
23
24 #include "utils/StringUtils.hpp"
25
26 using namespace std;
27 namespace OpenBabel
28 {
29
30 class OOPSEFormat : public OBMoleculeFormat
31 {
32 public:
33 //Register this format type ID
34 OOPSEFormat()
35 {
36 OBConversion::RegisterFormat("md",this);
37 }
38
39 virtual const char* Description() //required
40 {
41 return
42 "OOPSE combined meta-data / cartesian coordinates format\nNo comments yet\n";
43 };
44
45 virtual const char* SpecificationURL()
46 {return "http://www.oopse.org";}; //optional
47
48 virtual const char* GetMIMEType()
49 {return "chemical/x-md"; };
50
51 virtual unsigned int Flags()
52 {
53 return NOTREADABLE | WRITEONEONLY;
54 }
55
56 virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
57
58 private:
59 bool AreSameFragments(OBMol& mol, vector<int>& frag1, vector<int>& frag2);
60 OBMol* createMolFromFragment(OBMol& mol, vector<int>& fragment);
61 void WriteMDFile(vector<OBMol*> mols, vector<int> numMols, ostream& os,
62 OBMol& mol, vector<int>& indices);
63 void CalcBoundingBox(OBMol &mol,
64 double &min_x, double &max_x,
65 double &min_y, double &max_y,
66 double &min_z, double &max_z);
67
68 };
69
70 //Make an instance of the format class
71 OOPSEFormat theOOPSEFormat;
72
73 bool OOPSEFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) {
74 OBMol* pmol = dynamic_cast<OBMol*>(pOb);
75 if(pmol==NULL)
76 return false;
77
78 vector<vector<int> > fragmentLists;
79 pmol->ContigFragList(fragmentLists);
80 OBBitVec unused;
81 vector<bool> used(fragmentLists.size(), 0);
82 vector<vector<int> > molecules;
83 vector<int> indices;
84 for(int i =0; i < used.size(); ++i) {
85 if (used[i])
86 continue;
87
88 used[i] = true;
89 vector<int> sameMolTypes;
90 sameMolTypes.push_back(i);
91 indices.insert(indices.end(), fragmentLists[i].begin(),
92 fragmentLists[i].end());
93 for (int j = i + 1;j < used.size(); ++j) {
94 if (used[j])
95 continue;
96
97 if (AreSameFragments(*pmol, fragmentLists[i], fragmentLists[j])) {
98 sameMolTypes.push_back(j);
99 indices.insert(indices.end(), fragmentLists[j].begin(),
100 fragmentLists[j].end());
101 used[j]=true;
102 }
103 }
104 molecules.push_back(sameMolTypes);
105 }
106
107 vector<OBMol*> mdMols;
108 vector<int> numMols;
109 for(vector<vector<int> >::iterator i = molecules.begin();
110 i != molecules.end(); ++i) {
111
112 mdMols.push_back(createMolFromFragment(*pmol,
113 fragmentLists[i->front()]));
114 numMols.push_back((*i).size());
115 }
116
117 string OutputFileName = pConv->GetInFilename();
118 size_t pos = OutputFileName.rfind(".");
119 if(pos!=string::npos)
120 OutputFileName = OutputFileName.substr(0, pos) + ".md";
121 else
122 OutputFileName += ".md";
123
124 ofstream ofs(OutputFileName.c_str());
125 if(!ofs) {
126 cerr << "Cannot write to " << OutputFileName <<endl;
127 return false;
128 }
129
130 WriteMDFile(mdMols, numMols, ofs, *pmol, indices);
131
132 for(vector<OBMol*>::iterator i = mdMols.begin(); i != mdMols.end(); ++i) {
133 delete *i;
134 }
135
136 return(true);
137 }
138
139 bool OOPSEFormat::AreSameFragments(OBMol& mol, vector<int>& frag1,
140 vector<int>& frag2) {
141 if (frag1.size() != frag2.size())
142 return false;
143
144 // Exact graph matching is an NP complete problem.
145 // This just matches all of the atom atomic numbers and may falsely
146 // detect identical fragments which aren't really identical.
147 // @todo using sparse matrix to store the connectivities
148
149 for (unsigned int i =0 ; i < frag1.size(); ++i) {
150 OBAtom* atom1 = mol.GetAtom(frag1[i]);
151 OBAtom* atom2 = mol.GetAtom(frag2[i]);
152
153 if (atom1->GetAtomicNum() != atom2->GetAtomicNum())
154 return false;
155
156 }
157 return true;
158 }
159
160 struct SameAngle {
161 bool operator()(const triple<OBAtom*,OBAtom*,OBAtom*> t1,
162 const triple<OBAtom*,OBAtom*,OBAtom*> t2) const {
163 return (t1.second == t2.second) && ( (t1.first == t2.first && t1.third == t2.third) || (t1.first == t2.third && t1.third == t2.first));
164 }
165 };
166
167
168 OBMol* OOPSEFormat::createMolFromFragment(OBMol& mol,
169 vector<int>& fragment) {
170
171 OBMol* newMol = new OBMol();
172 newMol->ReserveAtoms(fragment.size());
173 newMol->BeginModify();
174 for(vector<int>::iterator i = fragment.begin(); i != fragment.end(); ++i) {
175 OBAtom* newAtom = newMol->NewAtom();
176 *newAtom = *mol.GetAtom(*i);
177 }
178
179 newMol->EndModify();
180 newMol->ConnectTheDots();
181 newMol->PerceiveBondOrders();
182
183 return newMol;
184 }
185
186 void OOPSEFormat::WriteMDFile(vector<OBMol*> mols, vector<int> numMols,
187 ostream& os, OBMol& mol,
188 vector<int>& indices) {
189
190 std::string molPrefix("MolName");
191 std::string resName;
192 unsigned int i;
193 const int BUFFLEN = 1024;
194 char buffer[BUFFLEN];
195 string str, str1;
196 OBAtom *a, *b, *c, *d;
197 bool molIsWater = false;
198 OBResidue *r;
199 int resKey;
200 char type_name[10];
201 char *element_name;
202 int res_num;
203 OBChainsParser* chainParser = new OBChainsParser();
204 double min_x, max_x, min_y, max_y, min_z, max_z; /* Edges of bounding box */
205
206 os << "<OOPSE version=4>" << endl;
207 os << " <MetaData>" << endl << endl;
208
209 for(i = 0; i < mols.size(); ++i) {
210 OBMol* pmol = mols[i];
211 map<OBAtom*, int> atomMap;
212
213 chainParser->PerceiveChains(*pmol, false);
214 molIsWater = false;
215 FOR_RESIDUES_OF_MOL(residue, *pmol) {
216 std::cerr << "residue = " << residue->GetName() << "\n";
217 if (residue->GetName().compare("HOH") == 0) {
218 molIsWater = true;
219 }
220 }
221
222 if (molIsWater) {
223 // water include files define all of the known water types
224 os << "#include \"water.md\";\n";
225 pmol->SetTitle("HOH");
226 } else {
227
228 os << "molecule {\n";
229 sprintf(buffer, "%d", i);
230 os << " name = \"" << molPrefix << buffer << "\";\n";
231
232 int ai = 0;
233 FOR_ATOMS_OF_MOL(atom, *pmol ) {
234 str = atom->GetType();
235 r = atom->GetResidue();
236
237 if (r == NULL)
238 resName = "NULL";
239 else
240 resName = r->GetName();
241
242 if (resName.compare("NULL") ==0 ||
243 resName.compare("LIG") == 0 ||
244 resName.compare("UNK") == 0) {
245 // Either couldn't find a residue at all or couldn't find a
246 // reasonable residue name to use. We'll punt and use
247 // OpenBabel's internal atom typing:
248 ttab.SetFromType("INT");
249 ttab.SetToType("INT");
250 ttab.Translate(str1, str);
251 } else {
252
253 // If we know what residue we've got, the specific atom name can
254 // be used to help specify partial charges.
255
256 str = r->GetAtomID(&*atom);
257 size_t startpos = str.find_first_not_of(" ");
258 size_t endpos = str.find_last_not_of(" ");
259 str = str.substr( startpos, endpos-startpos+1 );
260 str1 = resName + "-" + str;
261 }
262 os << " atom[" << ai << "] { ";
263 os << "type = " << "\"" << str1 << "\"" << "; ";
264 os << "}\n";
265 atomMap[&(*atom)] = ai++;
266 }
267 os << "\n";
268
269 //bond
270
271 int b1, b2;
272 FOR_BONDS_OF_MOL(bond, *pmol ) {
273 b1 = atomMap[bond->GetBeginAtom()];
274 b2 = atomMap[bond->GetEndAtom()];
275
276 os << " bond { ";
277
278 if (b1 < b2)
279 os << "members(" << b1 << ", " << b2 << "); ";
280 else
281 os << "members(" << b2 << ", " << b1 << "); ";
282
283 os << "}" << endl;
284 }
285
286 os << endl;
287
288 os << "}" << endl;
289 os << endl;
290 }
291 }
292
293 os << endl;
294
295 for(i=0; i < mols.size(); ++i) {
296 OBMol* pmol = mols[i];
297 os << "component{" << endl;
298 if (std::string(pmol->GetTitle()).compare("HOH") == 0) {
299 os << " type = " << "HOH" << ";" << endl;
300 } else {
301 sprintf(buffer, "%d", i);
302 os << " type = " << molPrefix << buffer << ";" << endl;
303 }
304 os << " nMol = " << numMols[i]<< ";" << endl;
305 os << "}" << endl;
306 }
307
308 os << " </MetaData>" << endl;
309 os << " <Snapshot>" << endl;
310 os << " <FrameData>" << endl;
311
312 sprintf(buffer, " Time: %.10g", 0.0);
313
314 os << buffer << endl;
315
316 CalcBoundingBox(mol, min_x, max_x, min_y, max_y, min_z, max_z);
317
318 // still to do: should compute a bounding box here
319 sprintf(buffer, " Hmat: {{ %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }}",
320 max_x - min_x, 0.0, 0.0, 0.0, max_y - min_y, 0.0, 0.0, 0.0, max_z - min_z);
321
322 os << buffer << endl;
323 os << " </FrameData>" << endl;
324 os << " <StuntDoubles>" << endl;
325
326 OBAtom *atom;
327
328 // still to do: intercept waters and recompute pvqj lines
329
330 for(vector<int>::iterator i = indices.begin();i != indices.end(); ++i) {
331 atom = mol.GetAtom(*i);
332 sprintf(buffer, "%10d %7s %18.10g %18.10g %18.10g %13e %13e %13e", *i - 1,
333 "pv", atom->GetX(), atom->GetY(), atom->GetZ(), 0.0, 0.0, 0.0);
334 os << buffer << endl;
335 }
336 os << " </StuntDoubles>" << endl;
337 os << " </Snapshot>" << endl;
338 os << "</OOPSE>" << endl;
339 }
340
341 void OOPSEFormat::CalcBoundingBox(OBMol &mol,
342 double &min_x, double &max_x,
343 double &min_y, double &max_y,
344 double &min_z, double &max_z
345 )
346 {
347 /* ---- Init bounding-box variables ---- */
348 min_x = (double) 0.0;
349 max_x = (double) 0.0;
350 min_y = (double) 0.0;
351 max_y = (double) 0.0;
352 min_z = (double) 0.0;
353 max_z = (double) 0.0;
354
355 /* ---- Check all atoms ---- */
356 for(unsigned int i = 1; i <= mol.NumAtoms(); ++i)
357 {
358
359 /* ---- Get a pointer to ith atom ---- */
360 OBAtom *atom = mol.GetAtom(i);
361
362 /* ---- Check for minimal/maximal x-position ---- */
363 if (atom -> GetX() < min_x)
364 min_x = atom -> GetX();
365 if (atom -> GetX() > max_x)
366 max_x = atom -> GetX();
367
368 /* ---- Check for minimal/maximal y-position ---- */
369 if (atom -> GetY() < min_y)
370 min_y = atom -> GetY();
371 if (atom -> GetY() > max_y)
372 max_y = atom -> GetY();
373
374 /* ---- Check for minimal/maximal z-position ---- */
375 if (atom -> GetZ() < min_z)
376 min_z = atom -> GetZ();
377 if (atom -> GetZ() > max_z)
378 max_z = atom -> GetZ();
379
380 }
381 }
382 } //namespace OpenBabel
383