ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/atom2md/oopseformat.cpp
Revision: 1210
Committed: Wed Jan 23 03:45:33 2008 UTC (17 years, 3 months ago) by gezelter
File size: 11923 byte(s)
Log Message:
Removed older version of openbabel from our code.  We now have a
configure check to see if openbabel is installed and then we link to
the stuff we need.  Conversion to OOPSE's md format is handled by only
one application (atom2md), so most of the work went on there.
ElementsTable still needs some work to function in parallel.

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     #include <fstream>
20    
21     using namespace std;
22     namespace OpenBabel
23     {
24    
25     class OOPSEFormat : public OBMoleculeFormat
26     {
27     public:
28     //Register this format type ID
29     OOPSEFormat()
30     {
31     OBConversion::RegisterFormat("md",this);
32     }
33    
34     virtual const char* Description() //required
35     {
36     return
37     "OOPSE combined meta-data / cartesian coordinates format\nNo comments yet\n";
38     };
39    
40     virtual const char* SpecificationURL()
41     {return "http://www.oopse.org";}; //optional
42    
43     virtual const char* GetMIMEType()
44     {return "chemical/x-md"; };
45    
46     virtual unsigned int Flags()
47     {
48     return NOTREADABLE | WRITEONEONLY;
49     }
50    
51     //*** This section identical for most OBMol conversions ***
52     ////////////////////////////////////////////////////
53     /// The "API" interface functions
54     virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
55    
56     private:
57     bool AreSameFragments(OBMol& mol, vector<int>& frag1, vector<int>& frag2);
58     void findAngles(OBMol& mol);
59     OBMol* createMolFromFragment(OBMol& mol, vector<int>& fragment);
60     void WriteMDFile(vector<OBMol*> mols, vector<int> numMols, ostream& os, OBMol& mol, vector<int>& indices);
61     };
62    
63     //Make an instance of the format class
64     OOPSEFormat theOOPSEFormat;
65    
66     /////////////////////////////////////////////////////////////////
67    
68    
69     bool OOPSEFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
70     {
71     OBMol* pmol = dynamic_cast<OBMol*>(pOb);
72     if(pmol==NULL)
73     return false;
74    
75     vector<vector<int> > fragmentLists;
76     pmol->ContigFragList(fragmentLists);
77     OBBitVec unused;
78     vector<bool> used(fragmentLists.size(), 0);
79     vector<vector<int> > molecules;
80     vector<int> indices;
81     for(int i =0; i < used.size(); ++i) {
82     if (used[i])
83     {
84     continue;
85     }
86     used[i] = true;
87     vector<int> sameMolTypes;
88     sameMolTypes.push_back(i);
89     indices.insert(indices.end(), fragmentLists[i].begin(),
90     fragmentLists[i].end());
91     for (int j = i + 1;j < used.size(); ++j)
92     {
93     if (used[j])
94     {
95     continue;
96     }
97    
98     if (AreSameFragments(*pmol, fragmentLists[i], fragmentLists[j]))
99     {
100     sameMolTypes.push_back(j);
101     indices.insert(indices.end(), fragmentLists[j].begin(),
102     fragmentLists[j].end());
103     used[j]=true;
104     }
105     }
106     molecules.push_back(sameMolTypes);
107    
108     }
109    
110     //
111     vector<OBMol*> mdMols;
112     vector<int> numMols;
113     for(vector<vector<int> >::iterator i = molecules.begin();
114     i != molecules.end(); ++i)
115     {
116     mdMols.push_back(createMolFromFragment(*pmol,
117     fragmentLists[i->front()]));
118     numMols.push_back((*i).size());
119     }
120    
121     string OutputFileName = pConv->GetInFilename();
122     unsigned int pos = OutputFileName.rfind(".");
123     if(pos==string::npos)
124     OutputFileName += ".md";
125     else
126     OutputFileName = OutputFileName.substr(0, pos) + ".md";
127     ofstream ofs(OutputFileName.c_str());
128     if(!ofs)
129     {
130     cerr << "Cannot write to " << OutputFileName <<endl;
131     return false;
132     }
133    
134     WriteMDFile(mdMols, numMols, ofs, *pmol, indices);
135    
136     for(vector<OBMol*>::iterator i = mdMols.begin(); i != mdMols.end(); ++i)
137     {
138     delete *i;
139     }
140    
141     //
142    
143     return(true);
144     }
145    
146     bool OOPSEFormat::AreSameFragments(OBMol& mol, vector<int>& frag1,
147     vector<int>& frag2)
148     {
149     if (frag1.size() != frag2.size())
150     {
151     return false;
152     }
153    
154     //exact graph matching is a NP complete problem
155     /** @todo using sparse matrix to store the connectivities*/
156     for (unsigned int i =0 ; i < frag1.size(); ++i)
157     {
158     OBAtom* atom1 = mol.GetAtom(frag1[i]);
159     OBAtom* atom2 = mol.GetAtom(frag2[i]);
160    
161     if (atom1->GetAtomicNum() != atom2->GetAtomicNum())
162     {
163     return false;
164     }
165     }
166     return true;
167     }
168    
169     struct SameAngle
170     {
171     bool operator()(const triple<OBAtom*,OBAtom*,OBAtom*> t1,
172     const triple<OBAtom*,OBAtom*,OBAtom*> t2) const
173     {
174     return (t1.second == t2.second) && ( (t1.first == t2.first && t1.third == t2.third) || (t1.first == t2.third && t1.third == t2.first));
175     }
176     };
177    
178     void OOPSEFormat::findAngles(OBMol& mol) {
179     /*
180     //if already has data return
181     if(mol.HasData(OBGenericDataType::AngleData))
182     return;
183    
184     vector<OBEdgeBase*>::iterator bi1,bi2;
185     OBBond* bond;
186     OBAtom *a,*b,*c;
187    
188     set<triple<OBAtom*,OBAtom*,OBAtom*>, SameAngle> uniqueAngles;
189     //loop through all bonds generating torsions
190     for(bond = mol.BeginBond(bi1);bond;bond = mol.NextBond(bi1))
191     {
192     b = bond->GetBeginAtom();
193     c = bond->GetEndAtom();
194     if(b->IsHydrogen())
195     continue;
196    
197     for(a = b->BeginNbrAtom(bi2);a;a = b->NextNbrAtom(bi2))
198     {
199     if(a == c)
200     continue;
201    
202     uniqueAngles.insert(triple<OBAtom*,OBAtom*,OBAtom*>(a, b, c));
203     }
204     }
205    
206     //get new data and attach it to molecule
207     OBAngleData *angles = new OBAngleData;
208     mol.SetData(angles);
209     set<triple<OBAtom*,OBAtom*,OBAtom*>, SameAngle>::iterator i;
210    
211     for (i = uniqueAngles.begin(); i != uniqueAngles.end(); ++i) {
212     OBAngle angle;
213     angle.SetAtoms(i->first, i->second, i->second);
214     angles->SetData(angle);
215     }
216     */
217     }
218    
219     OBMol* OOPSEFormat::createMolFromFragment(OBMol& mol, vector<int>& fragment) {
220    
221     OBMol* newMol = new OBMol();
222     newMol->ReserveAtoms(fragment.size());
223     newMol->BeginModify();
224     for(vector<int>::iterator i = fragment.begin(); i != fragment.end(); ++i) {
225     OBAtom* newAtom = newMol->NewAtom();
226     *newAtom = *mol.GetAtom(*i);
227     }
228     newMol->EndModify();
229     newMol->ConnectTheDots();
230     findAngles(*newMol);
231     newMol->FindTorsions();
232     return newMol;
233     }
234    
235     void OOPSEFormat::WriteMDFile(vector<OBMol*> mols, vector<int> numMols, ostream& os, OBMol& mol, vector<int>& indices) {
236     std::string indentLevel1(" ");
237     std::string indentLevel2(" ");
238     std::string molPrefix("MolName");
239     unsigned int i;
240     const int BUFFLEN = 1024;
241     char buffer[BUFFLEN];
242     string str, str1;
243    
244    
245     os << "<OOPSE version=4>" << endl;
246     os << " <MetaData>" << endl << endl;
247    
248     for(i = 0; i < mols.size(); ++i) {
249     OBMol* pmol = mols[i];
250    
251     pmol->ConnectTheDots();
252     pmol->PerceiveBondOrders();
253     //pmol->FindSSSR();
254     //pmol->SetAromaticPerceived();
255     //pmol->Kekulize();
256    
257     map<OBAtom*, int> atomMap;
258     os << "molecule {\n";
259     sprintf(buffer, "%d", i);
260     os << indentLevel1 << "name = " << "\"" << molPrefix << buffer << "\"" << ";\n";
261    
262     //atom
263     int ai = 0;
264     FOR_ATOMS_OF_MOL(atom, *pmol ) {
265     str = atom->GetType();
266     ttab.SetFromType("INT");
267     ttab.SetToType("INT");
268     ttab.Translate(str1,str);
269     os << indentLevel1 << "atom[" << ai << "] {\n";
270     // os << indentLevel2 << "type = " << "\"" << etab.GetSymbol(atom->GetAtomicNum()) << "\"" << ";\n";
271     os << indentLevel2 << "type = " << "\"" << str1 << "\"" << ";\n";
272     os << indentLevel1 << "}\n";
273     atomMap[&(*atom)] = ai++;
274     }
275     os << "\n";
276    
277     //bond
278     FOR_BONDS_OF_MOL(bond, *pmol ) {
279     os << indentLevel1 << "bond {\n";
280     os << indentLevel2 << "members(" << atomMap[bond->GetBeginAtom()] << ", " << atomMap[bond->GetEndAtom()] << ");\n";
281     os << indentLevel1 << "}\n";
282     }
283     /*
284     //bend
285     OBGenericData* pGenericData = pmol->GetData(OBGenericDataType::AngleData);
286     OBAngleData* pAngleData = dynamic_cast<OBAngleData*>(pGenericData);
287     vector<OBAngle> angles = pAngleData->GetData();
288    
289     os << indentLevel1 << "nBends = " << angles.size() << ";\n";
290     int bendIndex = 0;
291     for (vector<OBAngle>::iterator ti = angles.begin(); ti != angles.end(); ++ti)
292     {
293     triple<OBAtom*, OBAtom*, OBAtom*> bendAtoms = ti->getAtoms();
294     os << indentLevel1 << "bend[" << bendIndex++ << "] {\n";
295     os << indentLevel2 << "member(" << atomMap[bendAtoms.first] << ", " << atomMap[bendAtoms.second] << atomMap[bendAtoms.third] <<");\n";
296     os << indentLevel1 << "}\n";
297     }
298    
299     //torsion
300     pGenericData = pmol->GetData(OBGenericDataType::TorsionData);
301     OBTorsionData* pTorsionData = dynamic_cast<OBTorsionData*>(pGenericData);
302     vector<OBTorsion> torsions = pTorsionData->GetData();
303     vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> > torsionArray;
304     for (vector<OBTorsion>::iterator ti = torsions.begin(); ti != torsions.end(); ++ti)
305     {
306     vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> > tmpTorsions = ti->getTorsions();
307     torsionArray.insert(torsionArray.end(), tmpTorsions.begin(), tmpTorsions.end());
308     }
309    
310     os << indentLevel1 << "nTorsions = " << torsionArray.size() << ";\n";
311     int torsionIndex = 0;
312     for (vector<quad<OBAtom*,OBAtom*,OBAtom*,OBAtom*> >::iterator ti = torsionArray.begin(); ti != torsionArray.end(); ++ti)
313     {
314     os << indentLevel1 << "torsion[" << torsionIndex++ << "] {\n";
315     os << indentLevel2 << "member(" << atomMap[ti->first] << ", " << atomMap[ti->second] <<", " << atomMap[ti->third] <<", " << atomMap[ti->forth] << ");\n";
316     os << indentLevel1 << "}\n";
317     }
318     */
319     os << "}" << endl;
320     os << endl;
321    
322     }
323    
324     os << endl;
325    
326    
327     for(i=0; i < mols.size(); ++i) {
328     os << "component{" << endl;
329     sprintf(buffer, "%d", i);
330     os << indentLevel1 << "type = " << molPrefix << buffer << ";" << endl;
331     os << indentLevel1 << "nMol = " << numMols[i]<< ";" << endl;
332     os << "}" << endl;
333     }
334    
335     os << " </MetaData>" << endl;
336     os << " <Snapshot>" << endl;
337     os << " <FrameData>" << endl;
338    
339     sprintf(buffer, " Time: %.10g", 0.0);
340    
341     os << buffer << endl;
342    
343     sprintf(buffer, " Hmat: {{ %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }}", 100.0, 0.0, 0.0, 0.0, 100.0, 0.0, 0.0, 0.0, 100.0);
344    
345     os << buffer << endl;
346     os << " </FrameData>" << endl;
347     os << " <StuntDoubles>" << endl;
348    
349     OBAtom *atom;
350    
351     for(vector<int>::iterator i = indices.begin();i != indices.end(); ++i) {
352     atom = mol.GetAtom(*i);
353     sprintf(buffer, "%10d %7s %18.10g %18.10g %18.10g %13e %13e %13e", *i - 1, "pv", atom->GetX(), atom->GetY(), atom->GetZ(), 0.0, 0.0, 0.0);
354     os << buffer << endl;
355     }
356     os << " </StuntDoubles>" << endl;
357     os << " </Snapshot>" << endl;
358     os << "</OOPSE>" << endl;
359     }
360    
361     } //namespace OpenBabel
362