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 16 /* contributed by Walter Scott (wscott@igc.phys.chem.ethz.ch) 17 18 (Actually the routine was copied from write_xyz and and write_pdb and 19 then modified...) 20 21 This is a small routine to write a GROMOS96 formatted 22 "position coordinate block" (POSITION) or a 23 "reduced position coordinate block" (POSITIONRED) 24 The former has name information (atom and residue names) while 25 the latter only has coordinates. 26 This version does not support the writing of binary 27 GROMOS files. 28 29 NOTE 1: the actual formats used in writing out the coordinates 30 do not matter, as GROMOS96 uses free formatted reads. 31 Each line may not be longer than 80 characters. 32 33 (Note, however, in the POSITION block, the first 24 (twenty four) 34 character on each line are ignored when the line is read in by GROMOS) 35 Comments lines, beginning with hash (#) may occur within a block and are 36 used as delimiters for easier reading. 37 38 NOTE 2: Many programs specify the units of the coordinates (e.g. Angstrom). 39 GROMOS96 does NOT, as all physical constants, from K_B to EPS are 40 NOT hardwired into the code, but specified by the user. 41 This allows some (mostly Americans) to use GROMOS96 in KCal and 42 Angstrom and the rest of us to use kJoule and nm. 43 It also makes it easy to use reduced units. 44 45 We get around this by supplying a routine, wr_sco_gr96, which 46 will scale the coordinates by a factor before writing. 47 This routine is then called with the factor set to 1.0 in 48 write_gr96A, or to 0.1 in write_gr96N depending on the users choice. 49 Thus, we always assume that we have read coordinates in Angstrom. 50 *** But now handled by a command line option in new framework. 51 */ 52 53 #include <openbabel/babelconfig.h> 54 #include <openbabel/obmolecformat.h> 55 #include <openbabel/mol.h> 56 #include <openbabel/atom.h> 57 #include <openbabel/elements.h> 58 59 60 using namespace std; 61 namespace OpenBabel 62 { 63 64 class GROMOS96Format : public OBMoleculeFormat 65 { 66 public: 67 //Register this format type ID GROMOS96Format()68 GROMOS96Format() 69 { 70 OBConversion::RegisterFormat("gr96",this); 71 } 72 Description()73 virtual const char* Description() //required 74 { 75 return 76 "GROMOS96 format\n" 77 "Write Options e.g. -xn\n" 78 " n output nm (not Angstroms)\n"; 79 }; 80 SpecificationURL()81 virtual const char* SpecificationURL() 82 { 83 return "http://manual.gromacs.org/documentation/current/reference-manual/file-formats.html#g96"; 84 } 85 86 //Flags() can return be any the following combined by | or be omitted if none apply 87 // NOTREADABLE READONEONLY NOTWRITABLE WRITEONEONLY Flags()88 virtual unsigned int Flags() 89 { 90 return NOTREADABLE | WRITEONEONLY; 91 }; 92 93 //////////////////////////////////////////////////// 94 /// The "API" interface functions 95 virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv); 96 97 }; 98 99 //Make an instance of the format class 100 GROMOS96Format theGROMOS96Format; 101 102 //////////////////////////////////////////////////////////////// 103 WriteMolecule(OBBase * pOb,OBConversion * pConv)104 bool GROMOS96Format::WriteMolecule(OBBase* pOb, OBConversion* pConv) 105 { 106 OBMol* pmol = dynamic_cast<OBMol*>(pOb); 107 if (pmol == nullptr) 108 return false; 109 110 //Define some references so we can use the old parameter names 111 ostream &ofs = *pConv->GetOutStream(); 112 OBMol &mol = *pmol; 113 double fac = pConv->IsOption("n") ? 0.1 : 1.0; //new framework 114 115 char type_name[16]; 116 char res_name[16]; 117 char buffer[BUFF_SIZE]; 118 string res_num; 119 120 snprintf(buffer, BUFF_SIZE, "#GENERATED BY OPEN BABEL %s\n",BABEL_VERSION); 121 ofs << buffer; 122 123 /* GROMOS wants a TITLE block, so let's write one*/ 124 ofs << "TITLE\n" << mol.GetTitle() << "\nEND\n"; 125 ofs << "POSITION\n"; 126 127 OBAtom *atom; 128 OBResidue *res; 129 vector<OBAtom*>::iterator i; 130 131 for(atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) 132 { 133 if ( (res = atom->GetResidue()) ) 134 { 135 // 16 = sizeof(res_name) and sizeof(type_name) 136 strncpy(res_name,(char*)res->GetName().c_str(), 16); 137 res_name[15] = '\0'; 138 strncpy(type_name,(char*)res->GetAtomID(atom).c_str(), 16); 139 type_name[15] = '\0'; 140 res_num = res->GetNumString(); 141 } 142 else 143 { 144 strncpy(type_name,OBElements::GetSymbol(atom->GetAtomicNum()), 16); 145 strcpy(res_name,"UNK"); 146 res_num = "1"; 147 } 148 149 snprintf(buffer, BUFF_SIZE, "%5s %5s %5s %6d %15.5f %15.5f %15.5f\n", 150 res_num.c_str(),res_name,type_name,atom->GetIdx(), 151 atom->x()*fac,atom->y()*fac,atom->z()*fac); 152 ofs << buffer; 153 154 if (!(atom->GetIdx()%10)) 155 { 156 snprintf(buffer, BUFF_SIZE, "# %d\n",atom->GetIdx()); 157 ofs << buffer; 158 } 159 } 160 161 ofs << "END\n"; 162 163 return(true); 164 } 165 166 } //namespace OpenBabel 167