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