19#include <openbabel/atom.h>
20#include <openbabel/babelconfig.h>
21#include <openbabel/bond.h>
22#include <openbabel/chains.h>
23#include <openbabel/data.h>
24#include <openbabel/mol.h>
25#include <openbabel/obiter.h>
26#include <openbabel/obmolecformat.h>
27#include <openbabel/obutil.h>
28#include <openbabel/stereo/tetrahedral.h>
35 class OpenMDFormat :
public OBMoleculeFormat {
38 OpenMDFormat() { OBConversion::RegisterFormat(
"omd",
this); }
40 virtual const char* Description()
42 return "OpenMD combined meta-data / cartesian coordinates format\n\
46 virtual const char* SpecificationURL() {
47 return "http://openmd.org";
50 virtual const char* GetMIMEType() {
return "chemical/x-omd"; };
52 virtual unsigned int Flags() {
return NOTREADABLE | WRITEONEONLY; }
54 virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
57 bool AreSameFragments(OBMol& mol, vector<int>& frag1, vector<int>& frag2);
58 OBMol* createMolFromFragment(OBMol& mol, vector<int>& fragment);
59 void WriteMDFile(vector<OBMol*> mols, vector<int> numMols, ostream& os,
60 OBMol& mol, vector<int>& indices);
61 void CalcBoundingBox(OBMol& mol,
double& min_x,
double& max_x,
62 double& min_y,
double& max_y,
double& min_z,
67 OpenMDFormat theOpenMDFormat;
69 bool OpenMDFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) {
70 OBMol* pmol =
dynamic_cast<OBMol*
>(pOb);
71 if (pmol == NULL)
return false;
73 vector<vector<int>> fragmentLists;
74 pmol->ContigFragList(fragmentLists);
76 vector<bool> used(fragmentLists.size(), 0);
77 vector<vector<int>> molecules;
79 for (std::size_t i = 0; i < used.size(); ++i) {
80 if (used[i])
continue;
83 vector<int> sameMolTypes;
84 sameMolTypes.push_back(i);
85 indices.insert(indices.end(), fragmentLists[i].begin(),
86 fragmentLists[i].end());
87 for (std::size_t j = i + 1; j < used.size(); ++j) {
88 if (used[j])
continue;
90 if (AreSameFragments(*pmol, fragmentLists[i], fragmentLists[j])) {
91 sameMolTypes.push_back(j);
92 indices.insert(indices.end(), fragmentLists[j].begin(),
93 fragmentLists[j].end());
97 molecules.push_back(sameMolTypes);
100 vector<OBMol*> mdMols;
102 for (vector<vector<int>>::iterator i = molecules.begin();
103 i != molecules.end(); ++i) {
104 mdMols.push_back(createMolFromFragment(*pmol, fragmentLists[i->front()]));
105 numMols.push_back((*i).size());
108 string OutputFileName = pConv->GetInFilename();
109 size_t pos = OutputFileName.rfind(
".");
110 if (pos != string::npos)
111 OutputFileName = OutputFileName.substr(0, pos) +
".omd";
113 OutputFileName +=
".omd";
115 ofstream ofs(OutputFileName.c_str());
117 cerr <<
"Cannot write to " << OutputFileName << endl;
121 WriteMDFile(mdMols, numMols, ofs, *pmol, indices);
123 for (vector<OBMol*>::iterator i = mdMols.begin(); i != mdMols.end(); ++i) {
130 bool OpenMDFormat::AreSameFragments(OBMol& mol, vector<int>& frag1,
131 vector<int>& frag2) {
132 if (frag1.size() != frag2.size())
return false;
138 for (
unsigned int i = 0; i < frag1.size(); ++i) {
139 OBAtom* atom1 = mol.GetAtom(frag1[i]);
140 OBAtom* atom2 = mol.GetAtom(frag2[i]);
142 if (atom1->GetAtomicNum() != atom2->GetAtomicNum())
return false;
145 OBMol* m1 =
new OBMol();
147 m1->ReserveAtoms(frag1.size());
149 for (
unsigned int i = 0; i < frag1.size(); ++i) {
150 OBAtom* atom1 = mol.GetAtom(frag1[i]);
151 OBAtom* newAtom = m1->NewAtom();
152 newAtom->Duplicate(atom1);
156 m1->ConnectTheDots();
157 m1->PerceiveBondOrders();
158 OBStereoFacade facade1(m1,
true);
160 OBMol* m2 =
new OBMol();
162 m2->ReserveAtoms(frag2.size());
164 for (
unsigned int i = 0; i < frag2.size(); ++i) {
165 OBAtom* atom2 = mol.GetAtom(frag2[i]);
166 OBAtom* newAtom = m2->NewAtom();
167 newAtom->Duplicate(atom2);
171 m2->ConnectTheDots();
172 m2->PerceiveBondOrders();
173 OBStereoFacade facade2(m2,
true);
175 OBTetrahedralStereo *stereo1;
176 OBTetrahedralStereo *stereo2;
177 OBTetrahedralStereo::Config config1;
178 OBTetrahedralStereo::Config config2;
183 for( a = m1->BeginAtoms(), b = m2->BeginAtoms(); a!= m1->EndAtoms(); ++a, ++b) {
185 std::cerr << (*a)->GetId() <<
" " << (*b)->GetId() <<
"\n";
187 if (facade1.HasTetrahedralStereo((*a)->GetId())) {
188 stereo1 = facade1.GetTetrahedralStereo((*a)->GetId());
189 config1 = stereo1->GetConfig();
190 std::cerr << *stereo1 <<
"\n";
193 if (facade2.HasTetrahedralStereo((*b)->GetId())) {
194 stereo2 = facade2.GetTetrahedralStereo((*b)->GetId());
195 config2 = stereo2->GetConfig();
196 std::cerr << *stereo2 <<
"\n";
199 if (config1 == config2) {
200 std::cerr <<
"configs are same";
202 std::cerr <<
"configs are different\n";
211 bool operator()(
const triple<OBAtom*, OBAtom*, OBAtom*> t1,
212 const triple<OBAtom*, OBAtom*, OBAtom*> t2)
const {
213 return (t1.second == t2.second) &&
214 ((t1.first == t2.first && t1.third == t2.third) ||
215 (t1.first == t2.third && t1.third == t2.first));
219 OBMol* OpenMDFormat::createMolFromFragment(OBMol& mol,
220 vector<int>& fragment) {
221 OBMol* newMol =
new OBMol();
223 newMol->ReserveAtoms(fragment.size());
224 newMol->BeginModify();
225 for (vector<int>::iterator i = fragment.begin(); i != fragment.end(); ++i) {
226 OBAtom* newAtom = newMol->NewAtom();
227 *newAtom = *mol.GetAtom(*i);
231 newMol->ConnectTheDots();
232 newMol->PerceiveBondOrders();
237 void OpenMDFormat::WriteMDFile(vector<OBMol*> mols, vector<int> numMols,
238 ostream& os, OBMol& mol,
239 vector<int>& indices) {
240 std::string molPrefix(
"MolName");
243 const int BUFFLEN = 1024;
244 char buffer[BUFFLEN];
245 string str, str1, str2, str3;
246 bool molIsWater =
false;
248 double min_x, max_x, min_y, max_y, min_z, max_z;
250 os <<
"<OpenMD version=2>" << endl;
251 os <<
" <MetaData>" << endl << endl;
253 for (i = 0; i < mols.size(); ++i) {
254 OBMol* pmol = mols[i];
255 map<OBAtom*, int> atomMap;
258 FOR_RESIDUES_OF_MOL(residue, *pmol) {
259 if (residue->GetName().compare(
"HOH") == 0) { molIsWater =
true; }
264 os <<
"#include \"water.omd\";\n";
265 pmol->SetTitle(
"HOH");
267 os <<
"molecule {\n";
268 snprintf(buffer, BUFFLEN,
"%u", i);
269 os <<
" name = \"" << molPrefix << buffer <<
"\";\n";
272 FOR_ATOMS_OF_MOL(atom, *pmol) {
273 str = atom->GetType();
275 r = atom->GetResidue();
280 resName = r->GetName();
282 if (resName.compare(
"NULL") == 0 || resName.compare(
"LIG") == 0 ||
283 resName.compare(
"UNL") == 0 || resName.compare(
"UNK") == 0) {
287 ttab.SetFromType(
"INT");
288 ttab.SetToType(
"INT");
289 ttab.Translate(str1, str);
297 str = r->GetAtomID(&*atom);
301 if (resName.compare(
"ARG") == 0) {
302 if (str.compare(
"NH1") == 0 || str.compare(
"NH2") == 0) {
306 if (resName.compare(
"VAL") == 0) {
307 if (str.compare(
"CG1") == 0 || str.compare(
"CG2") == 0) {
311 if (resName.compare(
"LEU") == 0) {
312 if (str.compare(
"CD1") == 0 || str.compare(
"CD2") == 0) {
316 if (resName.compare(
"ASP") == 0) {
317 if (str.compare(
"OD1") == 0 || str.compare(
"OD2") == 0) {
321 if (resName.compare(
"GLU") == 0) {
322 if (str.compare(
"OE1") == 0 || str.compare(
"OE2") == 0) {
326 if (resName.compare(
"TYR") == 0) {
327 if (str.compare(
"CD1") == 0 || str.compare(
"CD2") == 0) {
330 if (str.compare(
"CE1") == 0 || str.compare(
"CE2") == 0) {
335 if ((&*atom)->GetAtomicNum() == 1) {
336 FOR_NBORS_OF_ATOM(nbr, *atom) {
337 str2 = r->GetAtomID(&*nbr);
338 size_t startpos = str2.find_first_not_of(
" ");
339 size_t endpos = str2.find_last_not_of(
" ");
340 if ((endpos - startpos) < 1) {
346 if (str2.compare(
"OH") == 0) {
351 str3 = str2.substr(startpos + 1, endpos - startpos);
358 if (resName.compare(
"ARG") == 0) {
359 if (str.compare(
"HH1") == 0 || str.compare(
"HH2") == 0) {
363 if (resName.compare(
"VAL") == 0) {
364 if (str.compare(
"HG1") == 0 || str.compare(
"HG2") == 0) {
368 if (resName.compare(
"LEU") == 0) {
369 if (str.compare(
"HD1") == 0 || str.compare(
"HD2") == 0) {
373 if (resName.compare(
"TYR") == 0) {
374 if (str.compare(
"HD1") == 0 || str.compare(
"HD2") == 0) {
377 if (str.compare(
"HE1") == 0 || str.compare(
"HE2") == 0) {
385 size_t startpos = str.find_first_not_of(
" ");
386 size_t endpos = str.find_last_not_of(
" ");
387 str = str.substr(startpos, endpos - startpos + 1);
388 str1 = resName +
"-" + str;
390 os <<
" atom[" << ai <<
"] { ";
392 <<
"\"" << str1 <<
"\""
394 os <<
"position( " << (&*atom)->GetX() <<
", " << (&*atom)->GetY()
395 <<
", " << (&*atom)->GetZ() <<
");";
397 atomMap[&(*atom)] = ai++;
407 FOR_BONDS_OF_MOL(bond, *pmol) {
408 a = bond->GetBeginAtom();
409 b = bond->GetEndAtom();
413 bo = bond->GetBondOrder();
414 if (bond->IsAromatic()) bo = 1.5;
418 if ((a->GetType()[2] ==
'R' && b->GetType()[2] ==
'R') &&
419 (a->ExplicitHydrogenCount() == 1 &&
420 b->ExplicitHydrogenCount() == 1))
422 if (bond->IsAmide()) bo = 1.41;
427 os <<
"members(" << ai <<
", " << bi <<
"); ";
429 os <<
"members(" << bi <<
", " << ai <<
"); ";
431 if (bo != 1) os <<
"bondOrder = " << bo <<
"; ";
445 for (i = 0; i < mols.size(); ++i) {
446 OBMol* pmol = mols[i];
447 os <<
"component{" << endl;
448 if (std::string(pmol->GetTitle()).compare(
"HOH") == 0) {
451 <<
"; // change to appropriate water model" << endl;
453 snprintf(buffer, BUFFLEN,
"%u", i);
454 os <<
" type = " << molPrefix << buffer <<
";" << endl;
456 os <<
" nMol = " << numMols[i] <<
";" << endl;
460 os <<
" </MetaData>" << endl;
461 os <<
" <Snapshot>" << endl;
462 os <<
" <FrameData>" << endl;
464 snprintf(buffer, BUFFLEN,
" Time: %.10g", 0.0);
466 os << buffer << endl;
468 CalcBoundingBox(mol, min_x, max_x, min_y, max_y, min_z, max_z);
473 " Hmat: {{ %.10g, %.10g, %.10g }, { %.10g, %.10g, %.10g }, { "
476 max_x - min_x, 0.0, 0.0, 0.0, max_y - min_y, 0.0, 0.0, 0.0,
479 os << buffer << endl;
480 os <<
" </FrameData>" << endl;
481 os <<
" <StuntDoubles>" << endl;
485 for (vector<int>::iterator i = indices.begin(); i != indices.end(); ++i) {
486 atom = mol.GetAtom(*i);
487 snprintf(buffer, BUFFLEN,
488 "%10d %7s %18.10g %18.10g %18.10g %13e %13e %13e", *i - 1,
"pv",
489 atom->GetX(), atom->GetY(), atom->GetZ(), 0.0, 0.0, 0.0);
490 os << buffer << endl;
492 os <<
" </StuntDoubles>" << endl;
493 os <<
" </Snapshot>" << endl;
494 os <<
"</OpenMD>" << endl;
497 void OpenMDFormat::CalcBoundingBox(OBMol& mol,
double& min_x,
double& max_x,
498 double& min_y,
double& max_y,
499 double& min_z,
double& max_z) {
509 for (
unsigned int i = 1; i <= mol.NumAtoms(); ++i) {
511 OBAtom* atom = mol.GetAtom(i);
514 if (atom->GetX() < min_x) min_x = atom->GetX();
515 if (atom->GetX() > max_x) max_x = atom->GetX();
518 if (atom->GetY() < min_y) min_y = atom->GetY();
519 if (atom->GetY() > max_y) max_y = atom->GetY();
522 if (atom->GetZ() < min_z) min_z = atom->GetZ();
523 if (atom->GetZ() > max_z) max_z = atom->GetZ();