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

# 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 <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