org.openscience.cdk.io.Gaussian03Reader Maven / Gradle / Ivy
/* Copyright (C) 2002-2003 Bradley A. Smith
*
* Contact: [email protected]
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.openscience.cdk.io;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.io.StringReader;
import javax.vecmath.Point3d;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomContainerSet;
import org.openscience.cdk.interfaces.IChemFile;
import org.openscience.cdk.interfaces.IChemModel;
import org.openscience.cdk.interfaces.IChemObject;
import org.openscience.cdk.interfaces.IChemSequence;
import org.openscience.cdk.io.formats.Gaussian03Format;
import org.openscience.cdk.io.formats.IResourceFormat;
import org.openscience.cdk.tools.ILoggingTool;
import org.openscience.cdk.tools.LoggingToolFactory;
import org.openscience.cdk.tools.periodictable.PeriodicTable;
/**
* A reader for Gaussian03 output.
* Gaussian 03 is a quantum chemistry program
* by Gaussian, Inc. (http://www.gaussian.com/).
*
* Molecular coordinates, energies, and normal coordinates of
* vibrations are read. Each set of coordinates is added to the
* ChemFile in the order they are found. Energies and vibrations
* are associated with the previously read set of coordinates.
*
*
This reader was developed from a small set of
* example output files, and therefore, is not guaranteed to
* properly read all Gaussian03 output. If you have problems,
* please contact the author of this code, not the developers
* of Gaussian03.
*
*
This code was adaptated by Jonathan from Gaussian98Reader written by
* Bradley, and ported to CDK by Egon.
*
* @author Jonathan C. Rienstra-Kiracofe
* @author Bradley A. Smith
* @author Egon Willighagen
* @cdk.module io
* @cdk.githash
* @cdk.iooptions
*/
public class Gaussian03Reader extends DefaultChemObjectReader {
private BufferedReader input;
private static ILoggingTool logger = LoggingToolFactory.createLoggingTool(Gaussian03Reader.class); ;
public Gaussian03Reader(Reader reader) {
input = new BufferedReader(reader);
}
public Gaussian03Reader(InputStream input) {
this(new InputStreamReader(input));
}
public Gaussian03Reader() {
this(new StringReader(""));
}
@Override
public IResourceFormat getFormat() {
return Gaussian03Format.getInstance();
}
@Override
public void setReader(Reader reader) throws CDKException {
this.input = new BufferedReader(input);
}
@Override
public void setReader(InputStream input) throws CDKException {
setReader(new InputStreamReader(input));
}
@Override
public boolean accepts(Class extends IChemObject> classObject) {
Class>[] interfaces = classObject.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
if (IChemFile.class.equals(interfaces[i])) return true;
if (IChemSequence.class.equals(interfaces[i])) return true;
}
return false;
}
@Override
public T read(T object) throws CDKException {
if (object instanceof IChemSequence) {
return (T) readChemSequence((IChemSequence) object);
} else if (object instanceof IChemFile) {
return (T) readChemFile((IChemFile) object);
} else {
throw new CDKException("Object " + object.getClass().getName() + " is not supported");
}
}
@Override
public void close() throws IOException {
input.close();
}
private IChemFile readChemFile(IChemFile chemFile) throws CDKException {
IChemSequence sequence = readChemSequence(chemFile.getBuilder().newInstance(IChemSequence.class));
chemFile.addChemSequence(sequence);
return chemFile;
}
private IChemSequence readChemSequence(IChemSequence sequence) throws CDKException {
IChemModel model = null;
try {
String line = input.readLine();
//String levelOfTheory = null;
// Find first set of coordinates
while (input.ready() && (line != null)) {
if (line.indexOf("Standard orientation:") >= 0) {
// Found a set of coordinates
model = sequence.getBuilder().newInstance(IChemModel.class);
try {
readCoordinates(model);
} catch (IOException exception) {
throw new CDKException("Error while reading coordinates: " + exception.toString(), exception);
}
break;
}
line = input.readLine();
}
if (model != null) {
// Read all other data
line = input.readLine();
while (input.ready() && (line != null)) {
if (line.indexOf("Standard orientation:") >= 0) {
// Found a set of coordinates
// Add current frame to file and create a new one.
sequence.addChemModel(model);
fireFrameRead();
model = sequence.getBuilder().newInstance(IChemModel.class);
readCoordinates(model);
} else if (line.indexOf("SCF Done:") >= 0) {
// Found an energy
model.setProperty("org.openscience.cdk.io.Gaussian03Reaer:SCF Done", line.trim());
} else if (line.indexOf("Harmonic frequencies") >= 0) {
// Found a set of vibrations
// try {
// readFrequencies(model);
// } catch (IOException exception) {
// throw new CDKException("Error while reading frequencies: " + exception.toString(), exception);
// }
} else if (line.indexOf("Mulliken atomic charges") >= 0) {
readPartialCharges(model);
} else if (line.indexOf("Magnetic shielding") >= 0) {
// Found NMR data
// try {
// readNMRData(model, line);
// } catch (IOException exception) {
// throw new CDKException("Error while reading NMR data: " + exception.toString(), exception);
// }
} else if (line.indexOf("GINC") >= 0) {
// Found calculation level of theory
//levelOfTheory = parseLevelOfTheory(line);
// FIXME: is doing anything with it?
}
line = input.readLine();
}
// Add current frame to file
sequence.addChemModel(model);
fireFrameRead();
}
} catch (IOException exception) {
throw new CDKException("Error while reading general structure: " + exception.toString(), exception);
}
return sequence;
}
/**
* Reads a set of coordinates into ChemModel.
*
* @param model the destination ChemModel
* @throws IOException if an I/O error occurs
*/
private void readCoordinates(IChemModel model) throws CDKException, IOException {
IAtomContainer container = model.getBuilder().newInstance(IAtomContainer.class);
String line = input.readLine();
line = input.readLine();
line = input.readLine();
line = input.readLine();
while (input.ready()) {
line = input.readLine();
if ((line == null) || (line.indexOf("-----") >= 0)) {
break;
}
int atomicNumber = 0;
StringReader sr = new StringReader(line);
StreamTokenizer token = new StreamTokenizer(sr);
token.nextToken();
// ignore first token
if (token.nextToken() == StreamTokenizer.TT_NUMBER) {
atomicNumber = (int) token.nval;
if (atomicNumber == 0) {
// Skip dummy atoms. Dummy atoms must be skipped
// if frequencies are to be read because Gaussian
// does not report dummy atoms in frequencies, and
// the number of atoms is used for reading frequencies.
continue;
}
} else {
throw new IOException("Error reading coordinates");
}
token.nextToken();
// ignore third token
double x = 0.0;
double y = 0.0;
double z = 0.0;
if (token.nextToken() == StreamTokenizer.TT_NUMBER) {
x = token.nval;
} else {
throw new IOException("Error reading coordinates");
}
if (token.nextToken() == StreamTokenizer.TT_NUMBER) {
y = token.nval;
} else {
throw new IOException("Error reading coordinates");
}
if (token.nextToken() == StreamTokenizer.TT_NUMBER) {
z = token.nval;
} else {
throw new IOException("Error reading coordinates");
}
String symbol = "Du";
symbol = PeriodicTable.getSymbol(atomicNumber);
IAtom atom = model.getBuilder().newInstance(IAtom.class, symbol);
atom.setPoint3d(new Point3d(x, y, z));
container.addAtom(atom);
}
IAtomContainerSet moleculeSet = model.getBuilder().newInstance(IAtomContainerSet.class);
moleculeSet.addAtomContainer(model.getBuilder().newInstance(IAtomContainer.class, container));
model.setMoleculeSet(moleculeSet);
}
/**
* Reads partial atomic charges and add the to the given ChemModel.
*/
private void readPartialCharges(IChemModel model) throws CDKException, IOException {
logger.info("Reading partial atomic charges");
IAtomContainerSet moleculeSet = model.getMoleculeSet();
IAtomContainer molecule = moleculeSet.getAtomContainer(0);
String line = input.readLine(); // skip first line after "Total atomic charges"
while (input.ready()) {
line = input.readLine();
logger.debug("Read charge block line: " + line);
if ((line == null) || (line.indexOf("Sum of Mulliken charges") >= 0)) {
logger.debug("End of charge block found");
break;
}
StringReader sr = new StringReader(line);
StreamTokenizer tokenizer = new StreamTokenizer(sr);
if (tokenizer.nextToken() == StreamTokenizer.TT_NUMBER) {
int atomCounter = (int) tokenizer.nval;
tokenizer.nextToken(); // ignore the symbol
double charge = 0.0;
if (tokenizer.nextToken() == StreamTokenizer.TT_NUMBER) {
charge = (double) tokenizer.nval;
logger.debug("Found charge for atom " + atomCounter + ": " + charge);
} else {
throw new CDKException("Error while reading charge: expected double.");
}
IAtom atom = molecule.getAtom(atomCounter - 1);
atom.setCharge(charge);
}
}
}
/**
* Reads a set of vibrations into ChemModel.
*
* @param model the destination ChemModel
* @throws IOException if an I/O error occurs
*/
// private void readFrequencies(IChemModel model) throws IOException {
/*
* This is yet to be ported. Vibrations don't exist yet in CDK. String line
* = input.readLine(); line = input.readLine(); line = input.readLine();
* line = input.readLine(); line = input.readLine(); while ((line != null)
* && line.startsWith(" Frequencies --")) { Vector currentVibs = new
* Vector(); StringReader vibValRead = new StringReader(line.substring(15));
* StreamTokenizer token = new StreamTokenizer(vibValRead); while
* (token.nextToken() != StreamTokenizer.TT_EOF) { Vibration vib = new
* Vibration(Double.toString(token.nval)); currentVibs.addElement(vib); }
* line = input.readLine(); // skip "Red. masses" line = input.readLine();
* // skip "Rfc consts" line = input.readLine(); // skip "IR Inten" while
* (!line.startsWith(" Atom AN")) { // skip all lines upto and including the
* " Atom AN" line line = input.readLine(); // skip } for (int i = 0; i <
* frame.getAtomCount(); ++i) { line = input.readLine(); StringReader
* vectorRead = new StringReader(line); token = new
* StreamTokenizer(vectorRead); token.nextToken(); // ignore first token
* token.nextToken(); // ignore second token for (int j = 0; j <
* currentVibs.size(); ++j) { double[] v = new double[3]; if
* (token.nextToken() == StreamTokenizer.TT_NUMBER) { v[0] = token.nval; }
* else { throw new IOException("Error reading frequency"); } if
* (token.nextToken() == StreamTokenizer.TT_NUMBER) { v[1] = token.nval; }
* else { throw new IOException("Error reading frequency"); } if
* (token.nextToken() == StreamTokenizer.TT_NUMBER) { v[2] = token.nval; }
* else { throw new IOException("Error reading frequency"); } ((Vibration)
* currentVibs.elementAt(j)).addAtomVector(v); } } for (int i = 0; i <
* currentVibs.size(); ++i) { frame.addVibration((Vibration)
* currentVibs.elementAt(i)); } line = input.readLine(); line =
* input.readLine(); line = input.readLine(); }
*/
// }
/**
* Reads NMR nuclear shieldings.
*/
// private void readNMRData(IChemModel model, String labelLine) throws IOException {
/*
* FIXME: this is yet to be ported. CDK does not have shielding stuff. //
* Determine label for properties String label; if
* (labelLine.indexOf("Diamagnetic") >= 0) { label =
* "Diamagnetic Magnetic shielding (Isotropic)"; } else if
* (labelLine.indexOf("Paramagnetic") >= 0) { label =
* "Paramagnetic Magnetic shielding (Isotropic)"; } else { label =
* "Magnetic shielding (Isotropic)"; } int atomIndex = 0; for (int i = 0; i
* < frame.getAtomCount(); ++i) { String line = input.readLine().trim();
* while (line.indexOf("Isotropic") < 0) { if (line == null) { return; }
* line = input.readLine().trim(); } StringTokenizer st1 = new
* StringTokenizer(line); // Find Isotropic label while
* (st1.hasMoreTokens()) { if (st1.nextToken().equals("Isotropic")) { break;
* } } // Find Isotropic value while (st1.hasMoreTokens()) { if
* (st1.nextToken().equals("=")) { break; } } double shielding =
* Double.valueOf(st1.nextToken()).doubleValue(); NMRShielding ns1 = new
* NMRShielding(label, shielding);
* ((org.openscience.jmol.Atom)frame.getAtomAt(atomIndex)).addProperty(ns1);
* ++atomIndex; }
*/
// }
/**
* Select the theory and basis set from the first archive line.
*/
/*
* private String parseLevelOfTheory(String line) { StringTokenizer st1 =
* new StringTokenizer(line, "\\"); // Must contain at least 6 tokens if
* (st1.countTokens() < 6) { return null; } // Skip first four tokens for
* (int i = 0; i < 4; ++i) { st1.nextToken(); } return st1.nextToken() + "/"
* + st1.nextToken(); }
*/
}