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

# User Rev Content
1 gezelter 1210 /**********************************************************************
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 gezelter 1269 #include <openbabel/obiter.h>
20     #include <openbabel/mol.h>
21     #include <openbabel/chains.h>
22 gezelter 1210 #include <fstream>
23    
24 gezelter 1269 #include "utils/StringUtils.hpp"
25    
26 gezelter 1210 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 gezelter 1274 void WriteMDFile(vector<OBMol*> mols, vector<int> numMols, ostream& os,
62     OBMol& mol, vector<int>& indices);
63 gezelter 1277 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 gezelter 1210 };
69 gezelter 1274
70 gezelter 1210 //Make an instance of the format class
71     OOPSEFormat theOOPSEFormat;
72 gezelter 1274
73     bool OOPSEFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) {
74 gezelter 1210 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 gezelter 1274 if (used[i])
86     continue;
87    
88 gezelter 1210 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 gezelter 1274 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 gezelter 1210 }
103 gezelter 1274 }
104     molecules.push_back(sameMolTypes);
105 gezelter 1210 }
106    
107     vector<OBMol*> mdMols;
108     vector<int> numMols;
109     for(vector<vector<int> >::iterator i = molecules.begin();
110 gezelter 1274 i != molecules.end(); ++i) {
111    
112     mdMols.push_back(createMolFromFragment(*pmol,
113     fragmentLists[i->front()]));
114     numMols.push_back((*i).size());
115     }
116 gezelter 1210
117     string OutputFileName = pConv->GetInFilename();
118 gezelter 1269 size_t pos = OutputFileName.rfind(".");
119     if(pos!=string::npos)
120     OutputFileName = OutputFileName.substr(0, pos) + ".md";
121     else
122 gezelter 1210 OutputFileName += ".md";
123 gezelter 1274
124 gezelter 1210 ofstream ofs(OutputFileName.c_str());
125 gezelter 1274 if(!ofs) {
126 gezelter 1210 cerr << "Cannot write to " << OutputFileName <<endl;
127     return false;
128 gezelter 1274 }
129 gezelter 1210
130     WriteMDFile(mdMols, numMols, ofs, *pmol, indices);
131    
132 gezelter 1274 for(vector<OBMol*>::iterator i = mdMols.begin(); i != mdMols.end(); ++i) {
133     delete *i;
134     }
135 gezelter 1210
136     return(true);
137     }
138    
139     bool OOPSEFormat::AreSameFragments(OBMol& mol, vector<int>& frag1,
140 gezelter 1274 vector<int>& frag2) {
141 gezelter 1210 if (frag1.size() != frag2.size())
142 gezelter 1274 return false;
143 gezelter 1210
144 gezelter 1274 // 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 gezelter 1210 OBAtom* atom1 = mol.GetAtom(frag1[i]);
151     OBAtom* atom2 = mol.GetAtom(frag2[i]);
152    
153 gezelter 1274 if (atom1->GetAtomicNum() != atom2->GetAtomicNum())
154     return false;
155    
156     }
157 gezelter 1210 return true;
158     }
159    
160 gezelter 1274 struct SameAngle {
161 gezelter 1210 bool operator()(const triple<OBAtom*,OBAtom*,OBAtom*> t1,
162 gezelter 1274 const triple<OBAtom*,OBAtom*,OBAtom*> t2) const {
163 gezelter 1210 return (t1.second == t2.second) && ( (t1.first == t2.first && t1.third == t2.third) || (t1.first == t2.third && t1.third == t2.first));
164     }
165     };
166 gezelter 1269
167    
168 gezelter 1274 OBMol* OOPSEFormat::createMolFromFragment(OBMol& mol,
169     vector<int>& fragment) {
170 gezelter 1210
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 gezelter 1274
179 gezelter 1210 newMol->EndModify();
180     newMol->ConnectTheDots();
181 gezelter 1269 newMol->PerceiveBondOrders();
182    
183 gezelter 1210 return newMol;
184     }
185    
186 gezelter 1274 void OOPSEFormat::WriteMDFile(vector<OBMol*> mols, vector<int> numMols,
187     ostream& os, OBMol& mol,
188     vector<int>& indices) {
189    
190 gezelter 1210 std::string molPrefix("MolName");
191 gezelter 1269 std::string resName;
192 gezelter 1210 unsigned int i;
193     const int BUFFLEN = 1024;
194     char buffer[BUFFLEN];
195     string str, str1;
196 gezelter 1269 OBAtom *a, *b, *c, *d;
197 gezelter 1274 bool molIsWater = false;
198 gezelter 1269 OBResidue *r;
199     int resKey;
200     char type_name[10];
201     char *element_name;
202     int res_num;
203 gezelter 1277 OBChainsParser* chainParser = new OBChainsParser();
204     double min_x, max_x, min_y, max_y, min_z, max_z; /* Edges of bounding box */
205 gezelter 1210
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 gezelter 1269
213 gezelter 1274 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 gezelter 1269 }
221    
222 gezelter 1274 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 gezelter 1269
228 gezelter 1274 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 gezelter 1277 os << "}" << endl;
284 gezelter 1274 }
285    
286 gezelter 1277 os << endl;
287    
288 gezelter 1274 os << "}" << endl;
289     os << endl;
290     }
291 gezelter 1210 }
292    
293     os << endl;
294 gezelter 1277
295 gezelter 1274 for(i=0; i < mols.size(); ++i) {
296     OBMol* pmol = mols[i];
297 gezelter 1210 os << "component{" << endl;
298 gezelter 1274 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 gezelter 1210 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 gezelter 1274
316 gezelter 1277 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 gezelter 1210
322     os << buffer << endl;
323     os << " </FrameData>" << endl;
324     os << " <StuntDoubles>" << endl;
325    
326     OBAtom *atom;
327    
328 gezelter 1274 // still to do: intercept waters and recompute pvqj lines
329    
330 gezelter 1210 for(vector<int>::iterator i = indices.begin();i != indices.end(); ++i) {
331     atom = mol.GetAtom(*i);
332 gezelter 1277 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 gezelter 1210 os << buffer << endl;
335     }
336     os << " </StuntDoubles>" << endl;
337     os << " </Snapshot>" << endl;
338     os << "</OOPSE>" << endl;
339     }
340 gezelter 1277
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 gezelter 1210 } //namespace OpenBabel
383