1 /* Copyright (C) 2001-2007 The Chemistry Development Kit (CDK) project 2 * 3 * Contact: cdk-devel@lists.sourceforge.net 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public License 7 * as published by the Free Software Foundation; either version 2.1 8 * of the License, or (at your option) any later version. 9 * All we ask is that proper credit is given for our work, which includes 10 * - but is not limited to - adding the above copyright notice to the beginning 11 * of your source code files, and to any copyright notice that you may distribute 12 * with programs based on this work. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 */ 24 package org.openscience.cdk.io; 25 26 import java.io.BufferedReader; 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.InputStreamReader; 30 import java.io.Reader; 31 import java.io.StringReader; 32 import java.util.StringTokenizer; 33 34 import javax.vecmath.Point3d; 35 36 import org.openscience.cdk.CDKConstants; 37 import org.openscience.cdk.exception.CDKException; 38 import org.openscience.cdk.geometry.ZMatrixTools; 39 import org.openscience.cdk.interfaces.IAtom; 40 import org.openscience.cdk.interfaces.IAtomContainer; 41 import org.openscience.cdk.interfaces.IAtomContainerSet; 42 import org.openscience.cdk.interfaces.IChemFile; 43 import org.openscience.cdk.interfaces.IChemModel; 44 import org.openscience.cdk.interfaces.IChemObject; 45 import org.openscience.cdk.interfaces.IChemSequence; 46 import org.openscience.cdk.io.formats.IResourceFormat; 47 import org.openscience.cdk.io.formats.ZMatrixFormat; 48 49 /** 50 * It reads Z matrices like in Gaussian input files. It seems that it cannot 51 * handle Z matrices where values are given via a stringID for which the value 52 * is given later. 53 * 54 * @cdk.module extra 55 * @cdk.githash 56 * @cdk.iooptions 57 * 58 * @cdk.keyword file format, Z-matrix 59 */ 60 public class ZMatrixReader extends DefaultChemObjectReader { 61 62 private BufferedReader input; 63 64 /** 65 * Constructs a ZMatrixReader from a Reader that contains the 66 * data to be parsed. 67 * 68 * @param input Reader containing the data to read 69 */ ZMatrixReader(Reader input)70 public ZMatrixReader(Reader input) { 71 this.input = new BufferedReader(input); 72 } 73 ZMatrixReader(InputStream input)74 public ZMatrixReader(InputStream input) { 75 this(new InputStreamReader(input)); 76 } 77 ZMatrixReader()78 public ZMatrixReader() { 79 this(new StringReader("")); 80 } 81 82 @Override getFormat()83 public IResourceFormat getFormat() { 84 return ZMatrixFormat.getInstance(); 85 } 86 87 @Override setReader(Reader input)88 public void setReader(Reader input) throws CDKException { 89 if (input instanceof BufferedReader) { 90 this.input = (BufferedReader) input; 91 } else { 92 this.input = new BufferedReader(input); 93 } 94 } 95 96 @Override setReader(InputStream input)97 public void setReader(InputStream input) throws CDKException { 98 setReader(new InputStreamReader(input)); 99 } 100 101 @Override accepts(Class<? extends IChemObject> classObject)102 public boolean accepts(Class<? extends IChemObject> classObject) { 103 return IChemFile.class.isAssignableFrom(classObject); 104 } 105 106 /** 107 * Returns a IChemObject of type object bye reading from 108 * the input. 109 * 110 * The function supports only reading of ChemFile's. 111 * 112 * @param object IChemObject that types the class to return. 113 * @throws CDKException when a IChemObject is requested that cannot be read. 114 */ 115 @Override read(T object)116 public <T extends IChemObject> T read(T object) throws CDKException { 117 if (object instanceof IChemFile) 118 return (T) readChemFile((IChemFile) object); 119 else 120 throw new CDKException("Only ChemFile objects can be read."); 121 } 122 123 /** 124 * Private method that actually parses the input to read a ChemFile 125 * object. 126 * 127 * @param file the file to read from 128 * @return A ChemFile containing the data parsed from input. 129 */ readChemFile(IChemFile file)130 private IChemFile readChemFile(IChemFile file) { 131 IChemSequence chemSequence = file.getBuilder().newInstance(IChemSequence.class); 132 133 int number_of_atoms; 134 StringTokenizer tokenizer; 135 136 try { 137 String line = input.readLine(); 138 while (line.startsWith("#")) 139 line = input.readLine(); 140 /* 141 * while (input.ready() && line != null) { 142 */ 143 // logger.debug("lauf"); 144 // parse frame by frame 145 tokenizer = new StringTokenizer(line, "\t ,;"); 146 147 String token = tokenizer.nextToken(); 148 number_of_atoms = Integer.parseInt(token); 149 String info = input.readLine(); 150 151 IChemModel chemModel = file.getBuilder().newInstance(IChemModel.class); 152 IAtomContainerSet setOfMolecules = file.getBuilder().newInstance(IAtomContainerSet.class); 153 154 IAtomContainer m = file.getBuilder().newInstance(IAtomContainer.class); 155 m.setTitle(info); 156 157 String[] types = new String[number_of_atoms]; 158 double[] d = new double[number_of_atoms]; 159 int[] d_atom = new int[number_of_atoms]; // Distances 160 double[] a = new double[number_of_atoms]; 161 int[] a_atom = new int[number_of_atoms]; // Angles 162 double[] da = new double[number_of_atoms]; 163 int[] da_atom = new int[number_of_atoms]; // Diederangles 164 //Point3d[] pos = new Point3d[number_of_atoms]; // calculated positions 165 166 int i = 0; 167 while (i < number_of_atoms) { 168 line = input.readLine(); 169 // logger.debug("line:\""+line+"\""); 170 if (line == null) break; 171 if (line.startsWith("#")) { 172 // skip comment in file 173 } else { 174 d[i] = 0d; 175 d_atom[i] = -1; 176 a[i] = 0d; 177 a_atom[i] = -1; 178 da[i] = 0d; 179 da_atom[i] = -1; 180 181 tokenizer = new StringTokenizer(line, "\t ,;"); 182 int fields = tokenizer.countTokens(); 183 184 if (fields < Math.min(i * 2 + 1, 7)) { 185 // this is an error but cannot throw exception 186 } else if (i == 0) { 187 types[i] = tokenizer.nextToken(); 188 i++; 189 } else if (i == 1) { 190 types[i] = tokenizer.nextToken(); 191 d_atom[i] = Integer.valueOf(tokenizer.nextToken()) - 1; 192 d[i] = Double.valueOf(tokenizer.nextToken()); 193 i++; 194 } else if (i == 2) { 195 types[i] = tokenizer.nextToken(); 196 d_atom[i] = Integer.valueOf(tokenizer.nextToken()) - 1; 197 d[i] = Double.valueOf(tokenizer.nextToken()); 198 a_atom[i] = Integer.valueOf(tokenizer.nextToken()) - 1; 199 a[i] = Double.valueOf(tokenizer.nextToken()); 200 i++; 201 } else { 202 types[i] = tokenizer.nextToken(); 203 d_atom[i] = Integer.valueOf(tokenizer.nextToken()) - 1; 204 d[i] = Double.valueOf(tokenizer.nextToken()); 205 a_atom[i] = Integer.valueOf(tokenizer.nextToken()) - 1; 206 a[i] = Double.valueOf(tokenizer.nextToken()); 207 da_atom[i] = Integer.valueOf(tokenizer.nextToken()) - 1; 208 da[i] = Double.valueOf(tokenizer.nextToken()); 209 i++; 210 } 211 } 212 } 213 214 // calculate cartesian coordinates 215 Point3d[] cartCoords = ZMatrixTools.zmatrixToCartesian(d, d_atom, a, a_atom, da, da_atom); 216 217 for (i = 0; i < number_of_atoms; i++) { 218 m.addAtom(file.getBuilder().newInstance(IAtom.class, types[i], cartCoords[i])); 219 } 220 221 // logger.debug("molecule:"+m); 222 223 setOfMolecules.addAtomContainer(m); 224 chemModel.setMoleculeSet(setOfMolecules); 225 chemSequence.addChemModel(chemModel); 226 line = input.readLine(); 227 file.addChemSequence(chemSequence); 228 } catch (IOException e) { 229 // should make some noise now 230 file = null; 231 } 232 return file; 233 } 234 235 @Override close()236 public void close() throws IOException { 237 input.close(); 238 } 239 } 240