1 /********************************************************************** 2 Copyright (C) 2000-2006 by Geoffrey Hutchison 3 Some portions Copyright (C) 2004 by Chris Morley 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation version 2 of the License. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 ***********************************************************************/ 14 #include <openbabel/babelconfig.h> 15 16 #include <openbabel/obmolecformat.h> 17 #include <openbabel/mol.h> 18 #include <openbabel/atom.h> 19 #include <openbabel/bond.h> 20 #include <openbabel/obiter.h> 21 #include <openbabel/elements.h> 22 #include <openbabel/generic.h> 23 #include <cstdlib> 24 25 using namespace std; 26 namespace OpenBabel 27 { 28 29 #define BOHR_TO_ANGSTROM 0.529177249 30 #define ANGSTROM_TO_BOHR 1.889725989 31 32 33 class DMolFormat : public OBMoleculeFormat 34 { 35 public: 36 //Register this format type ID DMolFormat()37 DMolFormat() 38 { 39 OBConversion::RegisterFormat("dmol",this); 40 OBConversion::RegisterFormat("outmol",this, "chemical/x-dmol"); 41 } 42 Description()43 virtual const char* Description() //required 44 { 45 return 46 "DMol3 coordinates format\n" 47 "Read Options e.g. -as\n" 48 " s Output single bonds only\n" 49 " b Disable bonding entirely\n\n"; 50 }; 51 SpecificationURL()52 virtual const char* SpecificationURL() 53 { return "" ;}; //optional 54 55 //Flags() can return be any the following combined by | or be omitted if none apply 56 // NOTREADABLE READONEONLY NOTWRITABLE WRITEONEONLY Flags()57 virtual unsigned int Flags() 58 { 59 return READONEONLY | WRITEONEONLY; 60 }; 61 62 //*** This section identical for most OBMol conversions *** 63 //////////////////////////////////////////////////// 64 /// The "API" interface functions 65 virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv); 66 virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv); 67 }; 68 //*** 69 70 //Make an instance of the format class 71 DMolFormat theDMolFormat; 72 73 ///////////////////////////////////////////////////////////////// ReadMolecule(OBBase * pOb,OBConversion * pConv)74 bool DMolFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv) 75 { 76 77 OBMol* pmol = pOb->CastAndClear<OBMol>(); 78 if (pmol == nullptr) 79 return false; 80 81 //Define some references so we can use the old parameter names 82 istream &ifs = *pConv->GetInStream(); 83 OBMol &mol = *pmol; 84 const char* title = pConv->GetTitle(); 85 86 char buffer[BUFF_SIZE]; 87 string str; 88 double x,y,z; 89 OBAtom *atom; 90 vector3 v1,v2,v3; 91 vector<string> vs; 92 93 ifs.getline(buffer,BUFF_SIZE); 94 while (strstr(buffer, "$coordinates") == nullptr && 95 strstr(buffer, "$cell vectors") == nullptr) 96 { 97 if (ifs.peek() == EOF || !ifs.good()) 98 return false; 99 ifs.getline(buffer,BUFF_SIZE); 100 } 101 102 if (strstr(buffer, "$cell vectors") != nullptr) 103 { 104 ifs.getline(buffer,BUFF_SIZE); 105 tokenize(vs,buffer); // we really need to check that it's 3 entries only 106 if (vs.size() < 3) return false; // timvdm 18/06/2008 107 x = atof((char*)vs[0].c_str()) * BOHR_TO_ANGSTROM; 108 y = atof((char*)vs[1].c_str()) * BOHR_TO_ANGSTROM; 109 z = atof((char*)vs[2].c_str()) * BOHR_TO_ANGSTROM; 110 v1.Set(x,y,z); 111 ifs.getline(buffer,BUFF_SIZE); 112 tokenize(vs,buffer); 113 if (vs.size() < 3) return false; // timvdm 18/06/2008 114 x = atof((char*)vs[0].c_str()) * BOHR_TO_ANGSTROM; 115 y = atof((char*)vs[1].c_str()) * BOHR_TO_ANGSTROM; 116 z = atof((char*)vs[2].c_str()) * BOHR_TO_ANGSTROM; 117 v2.Set(x,y,z); 118 ifs.getline(buffer,BUFF_SIZE); 119 tokenize(vs,buffer); 120 if (vs.size() < 3) return false; // timvdm 18/06/2008 121 x = atof((char*)vs[0].c_str()) * BOHR_TO_ANGSTROM; 122 y = atof((char*)vs[1].c_str()) * BOHR_TO_ANGSTROM; 123 z = atof((char*)vs[2].c_str()) * BOHR_TO_ANGSTROM; 124 v3.Set(x,y,z); 125 126 OBUnitCell *uc = new OBUnitCell; 127 uc->SetOrigin(fileformatInput); 128 uc->SetData(v1,v2,v3); 129 mol.SetData(uc); 130 131 ifs.getline(buffer,BUFF_SIZE); // next line 132 } 133 134 mol.BeginModify(); 135 136 while (strstr(buffer, "$end") == nullptr) 137 { 138 if (!ifs.getline(buffer,BUFF_SIZE)) 139 break; 140 tokenize(vs,buffer); 141 if (vs.size() != 4) 142 break; 143 atom = mol.NewAtom(); 144 //set atomic number 145 atom->SetAtomicNum(OBElements::GetAtomicNum(vs[0].c_str())); 146 x = atof((char*)vs[1].c_str()) * BOHR_TO_ANGSTROM; 147 y = atof((char*)vs[2].c_str()) * BOHR_TO_ANGSTROM; 148 z = atof((char*)vs[3].c_str()) * BOHR_TO_ANGSTROM; 149 atom->SetVector(x,y,z); //set coordinates 150 } 151 152 if (!pConv->IsOption("b",OBConversion::INOPTIONS)) 153 mol.ConnectTheDots(); 154 if (!pConv->IsOption("s",OBConversion::INOPTIONS) && !pConv->IsOption("b",OBConversion::INOPTIONS)) 155 mol.PerceiveBondOrders(); 156 157 // clean out any remaining blank lines 158 std::streampos ipos; 159 do 160 { 161 ipos = ifs.tellg(); 162 ifs.getline(buffer,BUFF_SIZE); 163 } 164 while(strlen(buffer) == 0 && !ifs.eof() ); 165 ifs.seekg(ipos); 166 167 mol.EndModify(); 168 mol.SetTitle(title); 169 return(true); 170 } 171 172 //////////////////////////////////////////////////////////////// 173 WriteMolecule(OBBase * pOb,OBConversion * pConv)174 bool DMolFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) 175 { 176 OBMol* pmol = dynamic_cast<OBMol*>(pOb); 177 if (pmol == nullptr) 178 return false; 179 180 //Define some references so we can use the old parameter names 181 ostream &ofs = *pConv->GetOutStream(); 182 OBMol &mol = *pmol; 183 184 unsigned int i; 185 char buffer[BUFF_SIZE]; 186 187 if (mol.HasData(OBGenericDataType::UnitCell)) 188 { 189 OBUnitCell *uc = (OBUnitCell*)mol.GetData(OBGenericDataType::UnitCell); 190 vector<vector3> v = uc->GetCellVectors(); 191 vector3 v1; 192 193 ofs << "$cell vectors" << endl; 194 v1 = v[0] * ANGSTROM_TO_BOHR; 195 snprintf(buffer, BUFF_SIZE, 196 "%-3s% 27.14f% 20.14f% 20.14f","", v1.x(), v1.y(), v1.z()); 197 ofs << buffer << endl; 198 v1 = v[1] * ANGSTROM_TO_BOHR; 199 snprintf(buffer, BUFF_SIZE, 200 "%-3s% 27.14f% 20.14f% 20.14f","", v1.x(), v1.y(), v1.z()); 201 ofs << buffer << endl; 202 v1 = v[2] * ANGSTROM_TO_BOHR; 203 snprintf(buffer, BUFF_SIZE, 204 "%-3s% 27.14f% 20.14f% 20.14f","", v1.x(), v1.y(), v1.z()); 205 ofs << buffer << endl; 206 } 207 208 ofs << "$coordinates" << endl; 209 210 OBAtom *atom; 211 for(i = 1;i <= mol.NumAtoms(); i++) 212 { 213 atom = mol.GetAtom(i); 214 snprintf(buffer, BUFF_SIZE, "%-3s% 27.14f% 20.14f% 20.14f", 215 OBElements::GetSymbol(atom->GetAtomicNum()), 216 atom->GetX() * ANGSTROM_TO_BOHR, 217 atom->GetY() * ANGSTROM_TO_BOHR, 218 atom->GetZ() * ANGSTROM_TO_BOHR); 219 ofs << buffer << endl; 220 } 221 222 ofs << "$end" << endl; 223 224 return(true); 225 } 226 227 } //namespace OpenBabel 228