1 /**********************************************************************
2 Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
3 Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
4 Some portions Copyright (C) 2004 by Chris Morley
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 #include <openbabel/babelconfig.h>
16 
17 #include <openbabel/obmolecformat.h>
18 #include <openbabel/mol.h>
19 #include <openbabel/atom.h>
20 #include <openbabel/bond.h>
21 #include <openbabel/elements.h>
22 #include <openbabel/data.h>
23 #include <openbabel/generic.h>
24 #include <cstdlib>
25 
26 
27 using namespace std;
28 namespace OpenBabel
29 {
30 
31   class BGFFormat : public OBMoleculeFormat
32   {
33   public:
34     //Register this format type ID
BGFFormat()35     BGFFormat()
36     {
37       OBConversion::RegisterFormat("bgf",this);
38     }
39 
Description()40     virtual const char* Description() //required
41     {
42       return
43         "MSI BGF format\n"
44         "No comments yet\n";
45     };
46 
SpecificationURL()47     virtual const char* SpecificationURL()
48     {return "";}; //optional
49 
50     //Flags() can return be any the following combined by | or be omitted if none apply
51     // NOTREADABLE  READONEONLY  NOTWRITABLE  WRITEONEONLY
Flags()52     virtual unsigned int Flags()
53     {
54       return READONEONLY | WRITEONEONLY;
55     };
56 
57     //*** This section identical for most OBMol conversions ***
58     ////////////////////////////////////////////////////
59     /// The "API" interface functions
60     virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
61     virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
62   };
63   //***
64 
65   //Make an instance of the format class
66   BGFFormat theBGFFormat;
67 
68   /////////////////////////////////////////////////////////////////
ReadMolecule(OBBase * pOb,OBConversion * pConv)69   bool BGFFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
70   {
71 
72     OBMol* pmol = pOb->CastAndClear<OBMol>();
73     if (pmol == nullptr)
74       return false;
75 
76     //Define some references so we can use the old parameter names
77     istream &ifs = *pConv->GetInStream();
78     OBMol &mol = *pmol;
79     mol.SetTitle( pConv->GetTitle()); //default title is the filename
80     mol.BeginModify();
81 
82     char buffer[BUFF_SIZE];
83     char tmp[16],tmptyp[16];
84     vector<string> vs;
85 
86     while (ifs.getline(buffer,BUFF_SIZE)) {
87       if (EQn(buffer,"CRYSTX",6)) {
88         // Parse unit cell
89         tokenize(vs,buffer," \n\t,");
90         if (vs.size() != 7)
91           continue; // something strange
92 
93         double A, B, C, Alpha, Beta, Gamma;
94         A = atof(vs[1].c_str());
95         B = atof(vs[2].c_str());
96         C = atof(vs[3].c_str());
97         Alpha = atof(vs[4].c_str());
98         Beta  = atof(vs[5].c_str());
99         Gamma = atof(vs[6].c_str());
100         OBUnitCell *uc = new OBUnitCell;
101         uc->SetOrigin(fileformatInput);
102         uc->SetData(A, B, C, Alpha, Beta, Gamma);
103         mol.SetData(uc);
104       } else if (EQn(buffer,"FORMAT",6))
105         break;
106     }
107 
108     ttab.SetFromType("DRE");
109     ttab.SetToType("INT");
110     OBAtom *atom;
111     double x,y,z,chrg;
112     for (;;)
113       {
114         if (!ifs.getline(buffer,BUFF_SIZE))
115           break;
116         if (EQn(buffer,"FORMAT",6))
117           break;
118 
119         sscanf(buffer,"%*s %*s %*s %*s %*s %*s %lf %lf %lf %15s %*s %*s %lf",
120                &x,&y,&z,
121                tmptyp,
122                &chrg);
123         atom = mol.NewAtom();
124 
125         ttab.Translate(tmp,tmptyp);
126         atom->SetType(tmp);
127 
128         CleanAtomType(tmptyp);
129         atom->SetAtomicNum(OBElements::GetAtomicNum(tmptyp));
130 
131         atom->SetVector(x,y,z);
132       }
133     unsigned int i;
134     vector<int> vtmp;
135     vector<vector<int> > vcon;
136     vector<vector<int> > vord;
137 
138     for (i = 0; i < mol.NumAtoms();i++)
139       {
140         vcon.push_back(vtmp);
141         vord.push_back(vtmp);
142       }
143 
144     unsigned int bgn;
145     for (;;)
146       {
147         if (!ifs.getline(buffer,BUFF_SIZE) || EQn(buffer,"END",3))
148           break;
149 
150         tokenize(vs,buffer);
151         if (vs.empty() || vs.size() < 3 || vs.size() > 10)
152           continue;
153 
154         if (EQn(buffer,"CONECT",6))
155           {
156             bgn = atoi((char*)vs[1].c_str()) - 1;
157             if (bgn < 1 || bgn > mol.NumAtoms())
158               continue;
159             for (i = 2;i < vs.size();i++)
160               {
161                 vcon[bgn].push_back(atoi((char*)vs[i].c_str()));
162                 vord[bgn].push_back(1);
163               }
164           }
165         else
166           if (EQn(buffer,"ORDER",5))
167             {
168               bgn = atoi((char*)vs[1].c_str()) - 1;
169               if (bgn < 1 || bgn > mol.NumAtoms())
170                 continue;
171               if (vs.size() > vord[bgn].size()+2)
172                 continue;
173               for (i = 2;i < vs.size();i++)
174                 vord[bgn][i-2] = atoi((char*)vs[i].c_str());
175             }
176       }
177 
178     unsigned int j;
179     for (i = 1;i <= mol.NumAtoms();i++)
180       if (!vcon[i - 1].empty())
181         for (j = 0;j < vcon[i - 1].size();j++)
182           {
183             mol.AddBond(i,vcon[i - 1][j],vord[i - 1][j]);
184           }
185 
186     //load up the next line after the END marker
187     ifs.getline(buffer,BUFF_SIZE);
188 
189     mol.EndModify();
190     return(true);
191   }
192 
193   ////////////////////////////////////////////////////////////////
194 
WriteMolecule(OBBase * pOb,OBConversion * pConv)195   bool BGFFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
196   {
197     OBMol* pmol = dynamic_cast<OBMol*>(pOb);
198     if (pmol == nullptr)
199       return false;
200 
201     //Define some references so we can use the old parameter names
202     ostream &ofs = *pConv->GetOutStream();
203     OBMol &mol = *pmol;
204 
205     vector<OBAtom*>::iterator i;
206     int max_val;
207     OBAtom *atom;
208     char buffer[BUFF_SIZE];
209     char elmnt_typ[8], dreid_typ[8], atm_sym[16], max_val_str[8];
210 
211     ofs << "BIOGRF 200\n";
212     snprintf(buffer, BUFF_SIZE, "DESCRP %s\n",mol.GetTitle());
213     ofs << buffer;
214     snprintf(buffer, BUFF_SIZE, "REMARK BGF file created by Open Babel %s\n",BABEL_VERSION);
215     ofs << "FORCEFIELD DREIDING  \n";
216 
217     // write unit cell if available
218     if (mol.HasData(OBGenericDataType::UnitCell))
219       {
220         OBUnitCell *uc = (OBUnitCell*)mol.GetData(OBGenericDataType::UnitCell);
221         // e.g. CRYSTX    49.30287   49.23010   25.45631   90.00008   89.99995   57.10041
222         snprintf(buffer, BUFF_SIZE,
223                  "CRYSTX%12.5f%12.5f%12.5f%12.5f%12.5f%12.5f",
224                  uc->GetA(), uc->GetB(), uc->GetC(),
225                  uc->GetAlpha() , uc->GetBeta(), uc->GetGamma());
226         ofs << buffer << "\n";
227       }
228 
229     ofs << "FORMAT ATOM   (a6,1x,i5,1x,a5,1x,a3,1x,a1,1x,a5,3f10.5,1x,a5,i3,i2,1x,f8.5)\n";
230 
231     ttab.SetFromType("INT");
232 
233     for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
234       {
235         strncpy(elmnt_typ,OBElements::GetSymbol(atom->GetAtomicNum()), 7); // make sure to null-terminate
236         elmnt_typ[sizeof(elmnt_typ) - 1] = '0';
237         ToUpper(elmnt_typ);
238 
239         ttab.SetToType("DRE");
240         ttab.Translate(dreid_typ,atom->GetType());
241         ttab.SetToType("HAD");
242         ttab.Translate(max_val_str,atom->GetType());
243         max_val = atoi(max_val_str);
244         if (max_val == 0)
245           max_val = 1;
246         snprintf(atm_sym,16,"%s%d",elmnt_typ,atom->GetIdx());
247         snprintf(buffer,BUFF_SIZE,"%6s %5d %-5s %3s %1s %5s%10.5f%10.5f%10.5f %-5s%3d%2d %8.5f\n",
248                 "HETATM",
249                 atom->GetIdx(),
250                 atm_sym,
251                 "RES",
252                 "A",
253                 "444",
254                 atom->GetX(),
255                 atom->GetY(),
256                 atom->GetZ(),
257                 dreid_typ,
258                 max_val,
259                 0,
260                 atom->GetPartialCharge());
261         ofs << buffer;
262       }
263     ofs<< "FORMAT CONECT (a6,12i6)\n\n";
264 
265     OBAtom *nbr;
266     vector<OBBond*>::iterator j;
267     for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
268       if (atom->GetExplicitDegree())
269         {
270           snprintf(buffer,BUFF_SIZE,"CONECT%6d",atom->GetIdx());
271           ofs << buffer;
272           for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j))
273             {
274               snprintf(buffer,BUFF_SIZE,"%6d",nbr->GetIdx());
275               ofs << buffer;
276             }
277           ofs << endl;
278 
279           snprintf(buffer,BUFF_SIZE,"ORDER %6d",atom->GetIdx());
280           ofs << buffer;
281           for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j))
282             {
283               snprintf(buffer,BUFF_SIZE,"%6d",(*j)->GetBondOrder());
284               ofs << buffer;
285             }
286           ofs << endl;
287         }
288 
289     ofs << "END" << endl;
290     return(true);
291   }
292 
293 } //namespace OpenBabel
294