1 /********************************************************************** 2 Copyright (C) 2000 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/obiter.h> 22 #include <openbabel/elements.h> 23 24 #include <cstdlib> 25 26 using namespace std; 27 namespace OpenBabel 28 { 29 30 class HINFormat : public OBMoleculeFormat 31 { 32 public: 33 //Register this format type ID HINFormat()34 HINFormat() 35 { 36 OBConversion::RegisterFormat("hin",this, "chemical/x-hin"); 37 } 38 Description()39 virtual const char* Description() //required 40 { 41 return "HyperChem HIN format\n" 42 "No comments yet\n"; 43 }; 44 SpecificationURL()45 virtual const char* SpecificationURL() 46 { return "";}; //optional 47 GetMIMEType()48 virtual const char* GetMIMEType() 49 { return "chemical/x-hin";}; //optional 50 51 //*** This section identical for most OBMol conversions *** 52 //////////////////////////////////////////////////// 53 /// The "API" interface functions 54 virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv); 55 virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv); 56 }; 57 //*** 58 59 //Make an instance of the format class 60 HINFormat theHINFormat; 61 62 ///////////////////////////////////////////////////////////////// ReadMolecule(OBBase * pOb,OBConversion * pConv)63 bool HINFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv) 64 { 65 66 OBMol* pmol = pOb->CastAndClear<OBMol>(); 67 if (pmol == nullptr) 68 return false; 69 70 //Define some references so we can use the old parameter names 71 istream &ifs = *pConv->GetInStream(); 72 OBMol &mol = *pmol; 73 const char* title = pConv->GetTitle(); 74 75 // Right now only read in the first molecule 76 int i; 77 int max, bo; 78 char buffer[BUFF_SIZE]; 79 string str,str1; 80 double x,y,z; 81 OBAtom *atom; 82 vector<string> vs; 83 84 ifs.getline(buffer, BUFF_SIZE); 85 while (ifs.good() && (strstr(buffer, "mol") == nullptr || buffer[0] == ';')) //The "mol" in comment line should be ignored. 86 { 87 ifs.getline(buffer, BUFF_SIZE); 88 if (ifs.peek() == EOF || !ifs.good()) 89 return false; 90 } 91 ifs.getline(buffer, BUFF_SIZE); 92 if (!ifs.good()) 93 return false; // ended early 94 95 mol.BeginModify(); 96 while (ifs.good() && strstr(buffer, "endmol") == nullptr) 97 { 98 if(buffer[0]==';'){ 99 ifs.getline(buffer, BUFF_SIZE); 100 continue; //The comment Line in HIN should be ignored. 101 } 102 103 tokenize(vs,buffer); // Don't really know how long it'll be 104 if (vs.size() < 11) 105 { 106 ifs.getline(buffer, BUFF_SIZE); 107 continue; 108 } 109 110 atom = mol.NewAtom(); 111 atom->SetAtomicNum(OBElements::GetAtomicNum(vs[3].c_str())); 112 atom->SetPartialCharge(atof(vs[6].c_str())); 113 x = atof((char*)vs[7].c_str()); 114 y = atof((char*)vs[8].c_str()); 115 z = atof((char*)vs[9].c_str()); 116 atom->SetVector(x,y,z); 117 118 max = 11 + 2 * atoi((char *)vs[10].c_str()); 119 for (i = 11; i < max; i+=2) 120 { 121 switch(((char*)vs[i+1].c_str())[0]) // First char in next token 122 { 123 case 's': 124 bo = 1; 125 break; 126 case 'd': 127 bo = 2; 128 break; 129 case 't': 130 bo = 3; 131 break; 132 case 'a': 133 bo = 5; 134 break; 135 default : 136 bo = 1; 137 break; 138 } 139 mol.AddBond(mol.NumAtoms(), atoi((char *)vs[i].c_str()), bo); 140 } 141 ifs.getline(buffer, BUFF_SIZE); 142 } 143 144 // clean out remaining blank lines 145 // blank lines cleaning codes rewritten for avoiding peek() and tellg() bugs 146 // https://github.com/openbabel/openbabel/issues/1569 147 std::streampos ipos; 148 do 149 { 150 ipos = ifs.tellg(); 151 ifs.getline(buffer,BUFF_SIZE); 152 } 153 while(strlen(buffer) == 0 && !ifs.eof() ); 154 ifs.seekg(ipos); 155 156 157 mol.EndModify(); 158 159 mol.SetTitle(title); 160 mol.SetPartialChargesPerceived(); 161 162 return(true); 163 } 164 165 //////////////////////////////////////////////////////////////// 166 WriteMolecule(OBBase * pOb,OBConversion * pConv)167 bool HINFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) 168 { 169 OBMol* pmol = dynamic_cast<OBMol*>(pOb); 170 if (pmol == nullptr) 171 return false; 172 173 //Define some references so we can use the old parameter names 174 ostream &ofs = *pConv->GetOutStream(); 175 OBMol &mol = *pmol; 176 177 unsigned int i, file_num = 1; 178 string str,str1; 179 char buffer[BUFF_SIZE]; 180 OBAtom *atom; 181 OBBond *bond; 182 vector<OBBond*>::iterator j; 183 char bond_char; 184 185 // make sure to escape titles in double quotes 186 // PR#1501694 187 ofs << "mol " << file_num << " \"" << mol.GetTitle() << "\"\n"; 188 189 for(i = 1;i <= mol.NumAtoms(); i++) 190 { 191 atom = mol.GetAtom(i); 192 snprintf(buffer, BUFF_SIZE, "atom %d - %-3s ** - %8.5f %8.5f %8.5f %8.5f %d ", 193 i, 194 OBElements::GetSymbol(atom->GetAtomicNum()), 195 atom->GetPartialCharge(), 196 atom->GetX(), 197 atom->GetY(), 198 atom->GetZ(), 199 atom->GetExplicitDegree()); 200 ofs << buffer; 201 for (bond = atom->BeginBond(j); bond; bond = atom->NextBond(j)) 202 { 203 switch(bond->GetBondOrder()) 204 { 205 case 1 : 206 bond_char = 's'; 207 break; 208 case 2 : 209 bond_char = 'd'; 210 break; 211 case 3 : 212 bond_char = 't'; 213 break; 214 case 5 : 215 bond_char = 'a'; 216 break; 217 default: 218 bond_char = 's'; 219 break; 220 } 221 if (bond->IsAromatic()) 222 bond_char = 'a'; 223 224 snprintf(buffer,BUFF_SIZE, "%d %c ", (bond->GetNbrAtom(atom))->GetIdx(), bond_char); 225 ofs << buffer; 226 } 227 ofs << endl; 228 } 229 ofs << "endmol " << file_num << endl; 230 return(true); 231 } 232 233 } //namespace OpenBabel 234