1 /**********************************************************************
2 Copyright (C) 2005-2006 by Geoffrey R. Hutchison
3 
4 Thanks to Kevin Gilbert from Serena Software for documentation and examples!
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 2 of the License.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 ***********************************************************************/
15 
16 #include <openbabel/obmolecformat.h>
17 #include <openbabel/mol.h>
18 #include <openbabel/atom.h>
19 #include <openbabel/elements.h>
20 #include <openbabel/data.h>
21 #include <openbabel/obiter.h>
22 #include <openbabel/bond.h>
23 #include <cstdlib>
24 
25 
26 using namespace std;
27 namespace OpenBabel
28 {
29 
30   class PCModelFormat : public OBMoleculeFormat
31   {
32   public:
33     //Register this format type ID
PCModelFormat()34     PCModelFormat()
35     {
36       OBConversion::RegisterFormat("pcm", this);
37     }
38 
Description()39     virtual const char* Description() //required
40     {
41       return
42         "PCModel Format\n"
43         "No comments yet\n";
44     };
45 
46     //Flags() can return be any the following combined by | or be omitted if none apply
47     // NOTREADABLE  READONEONLY  NOTWRITABLE  WRITEONEONLY
48     //  virtual unsigned int Flags()
49     //  {
50     //    return NOTREADABLE;
51     //  };
52 
SpecificationURL()53     virtual const char* SpecificationURL()
54     {return "http://www.serenasoft.com/";}; //optional
55 
56     //*** This section identical for most OBMol conversions ***
57     ////////////////////////////////////////////////////
58     /// The "API" interface functions
59     virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
60     virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
61   };
62   //***
63 
64   //Make an instance of the format class
65   PCModelFormat thePCModelFormat;
66 
67   /////////////////////////////////////////////////////////////////
ReadMolecule(OBBase * pOb,OBConversion * pConv)68   bool PCModelFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
69   {
70 
71     OBMol* pmol = dynamic_cast<OBMol*>(pOb);
72     if (pmol == nullptr)
73       return false;
74 
75     //Define some references so we can use the old parameter names
76     istream &ifs = *pConv->GetInStream();
77     OBMol &mol = *pmol;
78     const char* title = pConv->GetTitle();
79     char buffer[BUFF_SIZE];
80     string temp, temp2;
81 
82     OBAtom *atom;
83     vector<string> vs;
84     double x, y, z;
85     unsigned int token;
86     int bondNbr, bondOrder;
87     bool parsingBonds, readingMol = false;
88     bool hasPartialCharges = false;
89 
90     ttab.SetFromType("PCM");
91 
92     mol.BeginModify();
93 
94     while (ifs.getline(buffer,BUFF_SIZE))
95       {
96         if(strncmp(buffer,"{PCM", 4) == 0)
97           {
98             temp = buffer;
99             temp = temp.substr(4, temp.length());
100             mol.SetTitle(temp);
101             readingMol = true;
102           }
103         else if (readingMol && strncmp(buffer,"}", 1) == 0)
104           {
105             readingMol = false;
106             break;
107           }
108         else if (readingMol && strncmp(buffer,"AT ",3) == 0)
109           {
110             tokenize(vs,buffer, "\n\r\t ,:");
111             if (vs.size() < 3)
112               return false;
113 
114             atom = mol.NewAtom();
115             temp = vs[2].c_str();
116             ttab.SetToType("INT");
117             ttab.Translate(temp2, temp);
118             atom->SetType(temp2);
119 
120             ttab.SetToType("ATN");
121             ttab.Translate(temp2, temp);
122             atom->SetAtomicNum(atoi(temp2.c_str()));
123             x = atof(vs[3].c_str());
124             y = atof(vs[4].c_str());
125             z = atof(vs[5].c_str());
126             atom->SetVector(x,y,z); //set coordinates
127 
128             token = 6;
129             parsingBonds = false;
130             while(token < vs.size())
131               {
132                 if (vs[token] == "B")
133                   parsingBonds = true;
134                 else if (vs[token][0] == 'C')
135                   {
136                     parsingBonds = false;
137                     hasPartialCharges = true;
138                     if (vs[token].size() > 1)
139                       temp = vs[token].substr(1,vs[token].size());
140                     else
141                       {
142                         token++;
143                         temp = vs[token];
144                       }
145                     atom->SetPartialCharge(atof(temp.c_str()));
146                   }
147 
148                 else if (parsingBonds && token < vs.size() - 1 &&
149                          isdigit(vs[token][0]))
150                   {
151                     bondNbr = atoi(vs[token++].c_str()); // advance to bond order
152                     bondOrder = atoi(vs[token].c_str());
153                     if (bondOrder == 9)
154                       bondOrder = 1;
155                     mol.AddBond(atom->GetIdx(), bondNbr, bondOrder, 0);
156                   }
157                 else
158                   parsingBonds = false; // any other token
159 
160                 token++;
161               } // end atom fields
162           } // end AT line
163       } // end reading
164 
165     // clean out remaining blank lines
166     std::streampos ipos;
167     do
168     {
169       ipos = ifs.tellg();
170       ifs.getline(buffer,BUFF_SIZE);
171     }
172     while(strlen(buffer) == 0 && !ifs.eof() );
173     ifs.seekg(ipos);
174 
175     mol.EndModify();
176     if (hasPartialCharges)
177       mol.SetPartialChargesPerceived();
178     mol.SetTitle(title);
179     return(true);
180   }
181 
182   ////////////////////////////////////////////////////////////////
183 
WriteMolecule(OBBase * pOb,OBConversion * pConv)184   bool PCModelFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
185   {
186     OBMol* pmol = dynamic_cast<OBMol*>(pOb);
187     if (pmol == nullptr)
188       return false;
189 
190     //Define some references so we can use the old parameter names
191     ostream &ofs = *pConv->GetOutStream();
192     OBMol &mol = *pmol;
193     OBAtom *nbr;
194     vector<OBBond*>::iterator j;
195     string type, temp;
196     int nbrIdx, atomIdx;
197 
198     temp = mol.GetTitle();
199     ofs << "{PCM " << temp.substr(0,60) << endl;
200     ofs << "NA " << mol.NumAtoms() << endl;
201     ofs << "ATOMTYPES 1" << endl; // MMX atom types
202 
203     ttab.SetFromType("INT");
204     ttab.SetToType("PCM");
205 
206     string str,str1;
207     FOR_ATOMS_OF_MOL(atom, mol)
208       {
209         ttab.Translate(type,atom->GetType());
210         atomIdx = atom->GetIdx();
211 
212         ofs << "AT " << atom->GetIdx() << "," << type << ":";
213         ofs << atom->GetX() << "," << atom->GetY() << "," << atom->GetZ();
214 
215         if (atom->GetExplicitDegree() > 0)
216           {
217             ofs << " B";
218             for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j))
219               {
220                 nbrIdx = nbr->GetIdx();
221                 ofs << " " << nbrIdx << ","
222                     << (mol.GetBond(nbrIdx, atomIdx))->GetBondOrder();
223               }
224           }
225 
226         ofs << " C " << atom->GetPartialCharge();
227 
228         ofs << endl;
229       }
230 
231     ofs << "}" << endl;
232 
233     return(true);
234   }
235 
236 } //namespace OpenBabel
237