From: Andreas T. <atr...@gm...> - 2009-04-08 17:41:42
|
/* $Revision$ $Author$ $Date$ * * Copyright (C) 1997-2007 The Chemistry Development Kit (CDK) project * 2009 Egon Willighagen <eg...@us...> * * Contact: cdk...@li... * * This program 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. * All we ask is that proper credit is given for our work, which includes * - but is not limited to - adding the above copyright notice to the beginning * of your source code files, and to any copyright notice that you may distribute * with programs based on this work. * * This program 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 program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ package CDKClasses; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.io.Writer; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TimeZone; import java.util.Map.Entry; import org.openscience.cdk.CDKConstants; import org.openscience.cdk.annotations.TestClass; import org.openscience.cdk.annotations.TestMethod; import org.openscience.cdk.config.IsotopeFactory; import org.openscience.cdk.exception.CDKException; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; 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.interfaces.IMolecule; import org.openscience.cdk.interfaces.IPseudoAtom; import org.openscience.cdk.io.DefaultChemObjectWriter; import org.openscience.cdk.io.formats.IResourceFormat; import org.openscience.cdk.io.formats.MDLFormat; import org.openscience.cdk.tools.LoggingTool; import org.openscience.cdk.tools.manipulator.ChemFileManipulator; /** * Writes MDL molfiles, which contains a single molecule. For writing a MDL * molfile you can this code: * * <pre> * MDLWriter writer = new MDLWriter(new FileWriter(new File("output.mol"))); * writer.write((Molecule) molecule); * writer.close(); * </pre> * * See {@cdk.cite DAL92}. * * @cdk.module io * @cdk.svnrev $Revision$ * @cdk.keyword file format, MDL molfile */ @TestClass("org.openscience.cdk.io.MDLWriterTest") public class MDLWriter extends DefaultChemObjectWriter { private final static LoggingTool logger = new LoggingTool(MDLWriter.class); private int numberOfMoleculesWritten = 0; private boolean writeSDFDataItems = false; private BufferedWriter writer; /** * Constructs a new MDLWriter that can write an {@link IMolecule} to the MDL * molfile format. * * @param out * The Writer to write to */ public MDLWriter(Writer out) { if (out instanceof BufferedWriter) { writer = (BufferedWriter) out; } else { writer = new BufferedWriter(out); } } /** * Constructs a new MDLWriter that can write an {@link IMolecule} to a given * OutputStream. * * @param output * The OutputStream to write to */ public MDLWriter(OutputStream output) { this(new OutputStreamWriter(output)); } public MDLWriter() { this(new StringWriter()); } @TestMethod("testGetFormat") public IResourceFormat getFormat() { return MDLFormat.getInstance(); } public void setWriter(Writer out) throws CDKException { if (out instanceof BufferedWriter) { writer = (BufferedWriter) out; } else { writer = new BufferedWriter(out); } } public void setWriter(OutputStream output) throws CDKException { setWriter(new OutputStreamWriter(output)); } /** * If write SDF data items is set to true, write all properties from * .getProperties() into the file. * * @param value * True -> write all properties from .getProperties() into the * file SD-File. */ public void setWriteSDFDataItems(boolean value) { writeSDFDataItems = value; } /** * Flushes the output and closes this object. */ @TestMethod("testClose") public void close() throws IOException { writer.close(); } @TestMethod("testAccepts") public boolean accepts(Class classObject) { Class[] interfaces = classObject.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { if (IAtomContainer.class.equals(interfaces[i])) return true; if (IChemFile.class.equals(interfaces[i])) return true; if (IChemModel.class.equals(interfaces[i])) return true; } Class superClass = classObject.getSuperclass(); if (superClass != null) return this.accepts(superClass); return false; } /** * Writes a {@link IChemObject} to the MDL molfile formated output. It can * only output ChemObjects of type {@link IChemFile}, {@link IMolecule} and * {@link IAtomContainer}. * * @param object * {@link IChemObject} to write * * @see #accepts(Class) */ public void write(IChemObject object) throws CDKException { try { if (object instanceof IChemFile) { writeChemFile((IChemFile) object); return; } else if (object instanceof IChemModel) { IChemFile file = object.getBuilder().newChemFile(); IChemSequence sequence = object.getBuilder().newChemSequence(); sequence.addChemModel((IChemModel) object); file.addChemSequence(sequence); writeChemFile((IChemFile) file); return; } else if (object instanceof IAtomContainer) { writeMolecule((IAtomContainer) object); return; } } catch (Exception ex) { logger.error(ex.getMessage()); logger.debug(ex); throw new CDKException("Exception while writing MDL file: " + ex.getMessage(), ex); } throw new CDKException("Only supported is writing of ChemFile, MoleculeSet, AtomContainer and Molecule objects."); } private void writeChemFile(IChemFile file) throws Exception { IAtomContainer bigPile = file.getBuilder().newAtomContainer(); for (IAtomContainer container : ChemFileManipulator.getAllAtomContainers(file)) { bigPile.add(container); } writeMolecule(bigPile); } /** * Writes a Molecule to an OutputStream in MDL sdf format. * * @param container * Molecule that is written to an OutputStream */ public void writeMolecule(IAtomContainer container) throws Exception { // if the user wants to write a sdfile, close the previous molecule with "$$$$" if (numberOfMoleculesWritten == 1) { writer.write("$$$$"); writer.newLine(); } String line = ""; // write header block // lines get shortened to 80 chars, that's in the spec String title = (String) container.getProperty(CDKConstants.TITLE); if (title == null) title = ""; if (title.length() > 80) title = title.substring(0, 80); writer.write(title); writer.newLine(); /* * From CTX spec This line has the format: * IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR (FORTRAN: A2<--A8--><---A10-->A2I2<--F10.5-><---F12.5--><-I6-> ) * User's first and last initials (l), program name (P), date/time * (M/D/Y,H:m), dimensional codes (d), scaling factors (S, s), energy * (E) if modeling program input, internal registry number (R) if input * through MDL form. A blank line can be substituted for line 2. */ writer.write(" CDK "); writer.write(new SimpleDateFormat("M/d/y,H:m", Locale.US).format(Calendar.getInstance(TimeZone.getDefault()).getTime())); writer.newLine(); String comment = (String) container.getProperty(CDKConstants.REMARK); if (comment == null) comment = ""; if (comment.length() > 80) comment = comment.substring(0, 80); writer.write(comment); writer.newLine(); // write Counts line line += formatMDLInt(container.getAtomCount(), 3); line += formatMDLInt(container.getBondCount(), 3); line += " 0 0 0 0 0 0 0 0999 V2000"; writer.write(line); writer.newLine(); // write Atom block for (int f = 0; f < container.getAtomCount(); f++) { IAtom atom = container.getAtom(f); line = ""; if (atom.getPoint3d() != null) { line += formatMDLFloat((float) atom.getPoint3d().x); line += formatMDLFloat((float) atom.getPoint3d().y); line += formatMDLFloat((float) atom.getPoint3d().z) + " "; } else if (atom.getPoint2d() != null) { line += formatMDLFloat((float) atom.getPoint2d().x); line += formatMDLFloat((float) atom.getPoint2d().y); line += " 0.0000 "; } else { // if no coordinates available, then output a number // of zeros line += formatMDLFloat((float) 0.0); line += formatMDLFloat((float) 0.0); line += formatMDLFloat((float) 0.0) + " "; } if (container.getAtom(f) instanceof IPseudoAtom) { //according to http://www.google.co.uk/url?sa=t&ct=res&cd=2&url=http%3A%2F%2Fwww.mdl.com%2Fdownloads%2Fpublic%2Fctfile%2Fctfile.pdf&ei=MsJjSMbjAoyq1gbmj7zCDQ&usg=AFQjCNGaJSvH4wYy4FTXIaQ5f7hjoTdBAw&sig2=eSfruNOSsdMFdlrn7nhdAw an R group is written as R# if (((IPseudoAtom) container.getAtom(f)).getLabel().equals("R")) line += "R#"; else line += formatMDLString(((IPseudoAtom) container.getAtom(f)).getLabel(), 3); } else { line += formatMDLString(container.getAtom(f).getSymbol(), 3); } line += " 0 0 0 0 0 0 0 0 0"; // Set atom id to he mmm field at position 61-63. This field is read by the MDLV2000Reader class to set the atom ID. // If it is null set it to current atom number if (container.getAtom(f).getID() != null) { // try to parse the integer String reactionAtomIDString = container.getAtom(f).getID(); logger.debug("Parsing mapping id: ", reactionAtomIDString); try { int reactionAtomID = Integer.parseInt(reactionAtomIDString); if (reactionAtomID != 0) { line += this.formatMDLInt(reactionAtomID, 3); } } catch (Exception exception) { logger.error("Mapping number ", reactionAtomIDString, " is not an integer."); logger.debug(exception); // if id was no valid integer, set a new one. line += this.formatMDLInt(f + 1, 3); } } else { line += this.formatMDLInt(f + 1, 3); } line += " 0 0"; writer.write(line); writer.newLine(); } // write Bond block Iterator<IBond> bonds = container.bonds().iterator(); while (bonds.hasNext()) { IBond bond = (IBond) bonds.next(); if (bond.getAtomCount() != 2) { logger.warn("Skipping bond with more/less than two atoms: " + bond); } else { if (bond.getStereo() == CDKConstants.STEREO_BOND_UP_INV || bond.getStereo() == CDKConstants.STEREO_BOND_DOWN_INV) { // turn around atom coding to correct for inv stereo line = formatMDLInt(container.getAtomNumber(bond.getAtom(1)) + 1, 3); line += formatMDLInt(container.getAtomNumber(bond.getAtom(0)) + 1, 3); } else { line = formatMDLInt(container.getAtomNumber(bond.getAtom(0)) + 1, 3); line += formatMDLInt(container.getAtomNumber(bond.getAtom(1)) + 1, 3); } line += formatMDLInt((int) bond.getOrder().ordinal() + 1, 3); line += " "; switch (bond.getStereo()) { case CDKConstants.STEREO_BOND_UP: line += "1"; break; case CDKConstants.STEREO_BOND_UP_INV: line += "1"; break; case CDKConstants.STEREO_BOND_DOWN: line += "6"; break; case CDKConstants.STEREO_BOND_DOWN_INV: line += "6"; break; default: line += "0"; } line += " 0 0 0 "; writer.write(line); writer.newLine(); } } // write formal atomic charges for (int i = 0; i < container.getAtomCount(); i++) { IAtom atom = container.getAtom(i); int charge = atom.getFormalCharge(); if (charge != 0) { writer.write("M CHG 1 "); writer.write(formatMDLInt(i + 1, 3)); writer.write(" "); writer.write(formatMDLInt(charge, 3)); writer.newLine(); } } // write formal isotope information for (int i = 0; i < container.getAtomCount(); i++) { IAtom atom = container.getAtom(i); if (!(atom instanceof IPseudoAtom)) { Integer atomicMass = atom.getMassNumber(); if (atomicMass != null) { int majorMass = IsotopeFactory.getInstance(atom.getBuilder()).getMajorIsotope(atom.getSymbol()).getMassNumber(); if (atomicMass != majorMass) { writer.write("M ISO 1 "); writer.write(formatMDLInt(i + 1, 3)); writer.write(" "); writer.write(formatMDLInt(atomicMass, 3)); writer.newLine(); } } } } // close molecule writer.write("M END"); writer.newLine(); // // If write sdf data items is turned on write all properties from .getProperties() into the file. // Format: // Data Header: > <field name> (one line) // This method writes only the field name and no additional data as seen in the specifications // Data: A value may extend over multiple lines containing up to 80 characters each. A blank line // terminates each data item. (In the MDL documentation are 200 characters defined. But the // MDLV2000Reader only supports 80 characters.) if (writeSDFDataItems) { Set<Entry<Object, Object>> propSet = container.getProperties().entrySet(); while (propSet.iterator().hasNext()) { Entry<Object, Object> entry = propSet.iterator().next(); if (entry.getKey() != null && entry.getValue() != null) { String key = String.valueOf(entry.getKey()).trim(); String value = String.valueOf(entry.getValue()).trim(); // write header writer.write("> <" + key + ">"); writer.newLine(); // write data for (int i = 0; i < value.length(); i += 80) { int beginIndex = i; int endIndex = i + 80; if (endIndex >= value.length()) { endIndex = value.length(); } writer.write(value.substring(beginIndex, endIndex)); writer.newLine(); } // Blank line writer.newLine(); } propSet.remove(entry); } } // Tag the end of the current molecule if this is a sdf. if (numberOfMoleculesWritten > 0) { writer.write("$$$$"); writer.newLine(); } numberOfMoleculesWritten++; writer.flush(); } /** * Formats an integer to fit into the connection table and changes it to a * String. * * @param i * The int to be formated * @param l * Length of the String * @return The String to be written into the connectiontable */ private String formatMDLInt(int i, int l) { String s = "", fs = ""; NumberFormat nf = NumberFormat.getNumberInstance(Locale.ENGLISH); nf.setParseIntegerOnly(true); nf.setMinimumIntegerDigits(1); nf.setMaximumIntegerDigits(l); nf.setGroupingUsed(false); s = nf.format(i); l = l - s.length(); for (int f = 0; f < l; f++) fs += " "; fs += s; return fs; } /** * Formats a float to fit into the connectiontable and changes it to a * String. * * @param fl * The float to be formated * @return The String to be written into the connectiontable */ private String formatMDLFloat(float fl) { String s = "", fs = ""; int l; NumberFormat nf = NumberFormat.getNumberInstance(Locale.ENGLISH); nf.setMinimumIntegerDigits(1); nf.setMaximumIntegerDigits(4); nf.setMinimumFractionDigits(4); nf.setMaximumFractionDigits(4); nf.setGroupingUsed(false); s = nf.format(fl); l = 10 - s.length(); for (int f = 0; f < l; f++) fs += " "; fs += s; return fs; } /** * Formats a String to fit into the connectiontable. * * @param s * The String to be formated * @param le * The length of the String * @return The String to be written in the connectiontable */ private String formatMDLString(String s, int le) { s = s.trim(); if (s.length() > le) return s.substring(0, le); int l; l = le - s.length(); for (int f = 0; f < l; f++) s += " "; return s; } } |
From: Egon W. <ego...@gm...> - 2009-04-08 17:47:12
|
Hi Andreas, On Wed, Apr 8, 2009 at 7:41 PM, Andreas Truszkowski <atr...@gm...> wrote: > i have made several changes to the MDLWriter class. My question is, is it > possible to implement them into the CDK. The revised file is appended to > this mail. But first let me explain the changes. This very much sounds like the SDFWriter... the MDLWriter only saves MDL molfiles, the SDFWriter is for MDL SD files... Can you compare your code with that class as I think your list includes some features that may not be available from the SDFWriter at this moment? Egon -- Post-doc @ Uppsala University http://chem-bla-ics.blogspot.com/ |
From: Andreas T. <ATr...@gm...> - 2009-04-08 18:28:43
|
Thanks for the fast reply. My mistake. I think in 1.0.4 the SDFWriter class was not there :) but is in 1.2.0. So i have looked through the SDFWriter class and the first two points from my mail can be ignored. But then is the point open which concerns the atom IDs. This problem depends on the MDLWriter class. Regards, Andreas Egon Willighagen schrieb: > Hi Andreas, > > On Wed, Apr 8, 2009 at 7:41 PM, Andreas Truszkowski <atr...@gm...> wrote: > >> i have made several changes to the MDLWriter class. My question is, is it >> possible to implement them into the CDK. The revised file is appended to >> this mail. But first let me explain the changes. >> > > This very much sounds like the SDFWriter... the MDLWriter only saves > MDL molfiles, the SDFWriter is for MDL SD files... Can you compare > your code with that class as I think your list includes some features > that may not be available from the SDFWriter at this moment? > > Egon > > |
From: Egon W. <ego...@gm...> - 2009-04-08 19:12:30
|
On Wed, Apr 8, 2009 at 8:28 PM, Andreas Truszkowski <ATr...@gm...> wrote: > Thanks for the fast reply. My mistake. I think in 1.0.4 the SDFWriter class > was not there :) Yes, it is new indeed. > but is in 1.2.0. So i have looked through the SDFWriter > class and the first two points from my mail can be ignored. But then is the > point open which concerns the atom IDs. This problem depends on the > MDLWriter class. Can you please submit the last point is as patch? By posting the patch here, as at SourceForge? Then we can have a look at it in a format that makes it easier to see what changed... Egon -- Post-doc @ Uppsala University http://chem-bla-ics.blogspot.com/ |
From: Andreas T. <atr...@gm...> - 2009-04-08 19:26:37
|
/* $Revision$ $Author$ $Date$ * * Copyright (C) 1997-2007 The Chemistry Development Kit (CDK) project * 2009 Egon Willighagen <eg...@us...> * * Contact: cdk...@li... * * This program 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. * All we ask is that proper credit is given for our work, which includes * - but is not limited to - adding the above copyright notice to the beginning * of your source code files, and to any copyright notice that you may distribute * with programs based on this work. * * This program 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 program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ package CDKClasses; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.io.Writer; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Iterator; import java.util.Locale; import java.util.TimeZone; import org.openscience.cdk.CDKConstants; import org.openscience.cdk.annotations.TestClass; import org.openscience.cdk.annotations.TestMethod; import org.openscience.cdk.config.IsotopeFactory; import org.openscience.cdk.exception.CDKException; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IBond; 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.interfaces.IMolecule; import org.openscience.cdk.interfaces.IPseudoAtom; import org.openscience.cdk.io.DefaultChemObjectWriter; import org.openscience.cdk.io.formats.IResourceFormat; import org.openscience.cdk.io.formats.MDLFormat; import org.openscience.cdk.tools.LoggingTool; import org.openscience.cdk.tools.manipulator.ChemFileManipulator; /** * Writes MDL molfiles, which contains a single molecule. * For writing a MDL molfile you can this code: * <pre> * MDLWriter writer = new MDLWriter(new FileWriter(new File("output.mol"))); * writer.write((Molecule)molecule); * writer.close(); * </pre> * * See {@cdk.cite DAL92}. * * @cdk.module io * @cdk.svnrev $Revision$ * @cdk.keyword file format, MDL molfile */ @TestClass("org.openscience.cdk.io.MDLWriterTest") public class MDLWriter extends DefaultChemObjectWriter { private final static LoggingTool logger = new LoggingTool(MDLWriter.class); private BufferedWriter writer; /** * Constructs a new MDLWriter that can write an {@link IMolecule} * to the MDL molfile format. * * @param out The Writer to write to */ public MDLWriter(Writer out) { if (out instanceof BufferedWriter) { writer = (BufferedWriter)out; } else { writer = new BufferedWriter(out); } } /** * Constructs a new MDLWriter that can write an {@link IMolecule} * to a given OutputStream. * * @param output The OutputStream to write to */ public MDLWriter(OutputStream output) { this(new OutputStreamWriter(output)); } public MDLWriter() { this(new StringWriter()); } @TestMethod("testGetFormat") public IResourceFormat getFormat() { return MDLFormat.getInstance(); } public void setWriter(Writer out) throws CDKException { if (out instanceof BufferedWriter) { writer = (BufferedWriter)out; } else { writer = new BufferedWriter(out); } } public void setWriter(OutputStream output) throws CDKException { setWriter(new OutputStreamWriter(output)); } /** * Flushes the output and closes this object. */ @TestMethod("testClose") public void close() throws IOException { writer.close(); } @TestMethod("testAccepts") public boolean accepts(Class classObject) { Class[] interfaces = classObject.getInterfaces(); for (int i=0; i<interfaces.length; i++) { if (IAtomContainer.class.equals(interfaces[i])) return true; if (IChemFile.class.equals(interfaces[i])) return true; if (IChemModel.class.equals(interfaces[i])) return true; } Class superClass = classObject.getSuperclass(); if (superClass != null) return this.accepts(superClass); return false; } /** * Writes a {@link IChemObject} to the MDL molfile formated output. * It can only output ChemObjects of type {@link IChemFile}, * {@link IMolecule} and {@link IAtomContainer}. * * @param object {@link IChemObject} to write * * @see #accepts(Class) */ public void write(IChemObject object) throws CDKException { try { if (object instanceof IChemFile) { writeChemFile((IChemFile)object); return; } else if (object instanceof IChemModel) { IChemFile file = object.getBuilder().newChemFile(); IChemSequence sequence = object.getBuilder().newChemSequence(); sequence.addChemModel((IChemModel)object); file.addChemSequence(sequence); writeChemFile((IChemFile)file); return; } else if (object instanceof IAtomContainer) { writeMolecule((IAtomContainer)object); return; } } catch (Exception ex) { logger.error(ex.getMessage()); logger.debug(ex); throw new CDKException("Exception while writing MDL file: " + ex.getMessage(), ex); } throw new CDKException("Only supported is writing of ChemFile, MoleculeSet, AtomContainer and Molecule objects."); } private void writeChemFile(IChemFile file) throws Exception { IAtomContainer bigPile = file.getBuilder().newAtomContainer(); for (IAtomContainer container : ChemFileManipulator.getAllAtomContainers(file)) { bigPile.add(container); } writeMolecule(bigPile); } /** * Writes a Molecule to an OutputStream in MDL sdf format. * * @param container Molecule that is written to an OutputStream */ public void writeMolecule(IAtomContainer container) throws Exception { String line = ""; // write header block // lines get shortened to 80 chars, that's in the spec String title = (String)container.getProperty(CDKConstants.TITLE); if (title == null) title = ""; if(title.length()>80) title=title.substring(0,80); writer.write(title); writer.newLine(); /* From CTX spec * This line has the format: * IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR * (FORTRAN: A2<--A8--><---A10-->A2I2<--F10.5-><---F12.5--><-I6-> ) * User's first and last initials (l), program name (P), * date/time (M/D/Y,H:m), dimensional codes (d), scaling factors (S, s), * energy (E) if modeling program input, internal registry number (R) * if input through MDL form. * A blank line can be substituted for line 2. */ writer.write(" CDK "); writer.write(new SimpleDateFormat("M/d/y,H:m",Locale.US).format( Calendar.getInstance(TimeZone.getDefault()).getTime()) ); writer.newLine(); String comment = (String)container.getProperty(CDKConstants.REMARK); if (comment == null) comment = ""; if(comment.length()>80) comment=comment.substring(0,80); writer.write(comment); writer.newLine(); // write Counts line line += formatMDLInt(container.getAtomCount(), 3); line += formatMDLInt(container.getBondCount(), 3); line += " 0 0 0 0 0 0 0 0999 V2000"; writer.write(line); writer.newLine(); // write Atom block for (int f = 0; f < container.getAtomCount(); f++) { IAtom atom = container.getAtom(f); line = ""; if (atom.getPoint3d() != null) { line += formatMDLFloat((float) atom.getPoint3d().x); line += formatMDLFloat((float) atom.getPoint3d().y); line += formatMDLFloat((float) atom.getPoint3d().z) + " "; } else if (atom.getPoint2d() != null) { line += formatMDLFloat((float) atom.getPoint2d().x); line += formatMDLFloat((float) atom.getPoint2d().y); line += " 0.0000 "; } else { // if no coordinates available, then output a number // of zeros line += formatMDLFloat((float)0.0); line += formatMDLFloat((float)0.0); line += formatMDLFloat((float)0.0) + " "; } if(container.getAtom(f) instanceof IPseudoAtom){ //according to http://www.google.co.uk/url?sa=t&ct=res&cd=2&url=http%3A%2F%2Fwww.mdl.com%2Fdownloads%2Fpublic%2Fctfile%2Fctfile.pdf&ei=MsJjSMbjAoyq1gbmj7zCDQ&usg=AFQjCNGaJSvH4wYy4FTXIaQ5f7hjoTdBAw&sig2=eSfruNOSsdMFdlrn7nhdAw an R group is written as R# if(((IPseudoAtom) container.getAtom(f)).getLabel().equals("R")) line += "R#"; else line += formatMDLString(((IPseudoAtom) container.getAtom(f)).getLabel(), 3); }else{ line += formatMDLString(container.getAtom(f).getSymbol(), 3); } line += " 0 0 0 0 0 0 0 0 0"; // Set atom id to he mmm field at position 61-63. This field is read by the MDLV2000Reader class to set the atom ID. // If it is null set it to current atom number if (container.getAtom(f).getID() != null) { // try to parse the integer String reactionAtomIDString = container.getAtom(f).getID(); logger.debug("Parsing mapping id: ", reactionAtomIDString); try { int reactionAtomID = Integer.parseInt(reactionAtomIDString); if (reactionAtomID != 0) { line += this.formatMDLInt(reactionAtomID, 3); } } catch (Exception exception) { logger.error("Mapping number ", reactionAtomIDString, " is not an integer."); logger.debug(exception); // if id was no valid integer, set a new one. line += this.formatMDLInt(f + 1, 3); } } else { line += this.formatMDLInt(f + 1, 3); } line += " 0 0"; writer.write(line); writer.newLine(); } // write Bond block Iterator<IBond> bonds = container.bonds().iterator(); while (bonds.hasNext()) { IBond bond = (IBond) bonds.next(); if (bond.getAtomCount() != 2) { logger.warn("Skipping bond with more/less than two atoms: " + bond); } else { if (bond.getStereo() == CDKConstants.STEREO_BOND_UP_INV || bond.getStereo() == CDKConstants.STEREO_BOND_DOWN_INV) { // turn around atom coding to correct for inv stereo line = formatMDLInt(container.getAtomNumber(bond.getAtom(1)) + 1,3); line += formatMDLInt(container.getAtomNumber(bond.getAtom(0)) + 1,3); } else { line = formatMDLInt(container.getAtomNumber(bond.getAtom(0)) + 1,3); line += formatMDLInt(container.getAtomNumber(bond.getAtom(1)) + 1,3); } line += formatMDLInt((int)bond.getOrder().ordinal()+1,3); line += " "; switch(bond.getStereo()){ case CDKConstants.STEREO_BOND_UP: line += "1"; break; case CDKConstants.STEREO_BOND_UP_INV: line += "1"; break; case CDKConstants.STEREO_BOND_DOWN: line += "6"; break; case CDKConstants.STEREO_BOND_DOWN_INV: line += "6"; break; default: line += "0"; } line += " 0 0 0 "; writer.write(line); writer.newLine(); } } // write formal atomic charges for (int i = 0; i < container.getAtomCount(); i++) { IAtom atom = container.getAtom(i); int charge = atom.getFormalCharge(); if (charge != 0) { writer.write("M CHG 1 "); writer.write(formatMDLInt(i+1,3)); writer.write(" "); writer.write(formatMDLInt(charge,3)); writer.newLine(); } } // write formal isotope information for (int i = 0; i < container.getAtomCount(); i++) { IAtom atom = container.getAtom(i); if (!(atom instanceof IPseudoAtom)) { Integer atomicMass = atom.getMassNumber(); if (atomicMass != null) { int majorMass = IsotopeFactory.getInstance(atom.getBuilder()).getMajorIsotope(atom.getSymbol()).getMassNumber(); if (atomicMass != majorMass) { writer.write("M ISO 1 "); writer.write(formatMDLInt(i+1,3)); writer.write(" "); writer.write(formatMDLInt(atomicMass,3)); writer.newLine(); } } } } // close molecule writer.write("M END"); writer.newLine(); writer.flush(); } /** * Formats an integer to fit into the connection table and changes it * to a String. * * @param i The int to be formated * @param l Length of the String * @return The String to be written into the connectiontable */ private String formatMDLInt(int i, int l) { String s = "", fs = ""; NumberFormat nf = NumberFormat.getNumberInstance(Locale.ENGLISH); nf.setParseIntegerOnly(true); nf.setMinimumIntegerDigits(1); nf.setMaximumIntegerDigits(l); nf.setGroupingUsed(false); s = nf.format(i); l = l - s.length(); for (int f = 0; f < l; f++) fs += " "; fs += s; return fs; } /** * Formats a float to fit into the connectiontable and changes it * to a String. * * @param fl The float to be formated * @return The String to be written into the connectiontable */ private String formatMDLFloat(float fl) { String s = "", fs = ""; int l; NumberFormat nf = NumberFormat.getNumberInstance(Locale.ENGLISH); nf.setMinimumIntegerDigits(1); nf.setMaximumIntegerDigits(4); nf.setMinimumFractionDigits(4); nf.setMaximumFractionDigits(4); nf.setGroupingUsed(false); s = nf.format(fl); l = 10 - s.length(); for (int f = 0; f < l; f++) fs += " "; fs += s; return fs; } /** * Formats a String to fit into the connectiontable. * * @param s The String to be formated * @param le The length of the String * @return The String to be written in the connectiontable */ private String formatMDLString(String s, int le) { s = s.trim(); if (s.length() > le) return s.substring(0, le); int l; l = le - s.length(); for (int f = 0; f < l; f++) s += " "; return s; } } |
From: Rajarshi G. <rg...@in...> - 2009-04-08 19:34:30
|
could you provide a diff of the file - it's easier to see the changes On Apr 8, 2009, at 3:26 PM, Andreas Truszkowski wrote: > Here is the patch. It is from the write atom block part and replaces > "line += " 0 0 0 0 0 0 0 0 0 0 0 0";" at line 265 of the > original class. The patched class is appended to the mail too. > > line += " 0 0 0 0 0 0 0 0 0"; > // Set atom id to the mmm field at position 61-63. This > field is read by the MDLV2000Reader class to set the atom ID. > // If it is null set it to current atom number > if (container.getAtom(f).getID() != null) { > // try to parse the integer > String reactionAtomIDString = > container.getAtom(f).getID(); > logger.debug("Parsing mapping id: ", > reactionAtomIDString); > try { > int reactionAtomID = > Integer.parseInt(reactionAtomIDString); > if (reactionAtomID != 0) { > line += this.formatMDLInt(reactionAtomID, 3); > } > } catch (Exception exception) { > logger.error("Mapping number ", > reactionAtomIDString, " is not an integer."); > logger.debug(exception); > // if id was no valid integer, set a new one. > line += this.formatMDLInt(f + 1, 3); > } > } else { > line += this.formatMDLInt(f + 1, 3); > } > line += " 0 0"; > > > Andreas > > Egon Willighagen schrieb: >> >> On Wed, Apr 8, 2009 at 8:28 PM, Andreas Truszkowski <ATr...@gm... >> > wrote: >> >>> Thanks for the fast reply. My mistake. I think in 1.0.4 the >>> SDFWriter class >>> was not there :) >>> >> Yes, it is new indeed. >> >> >>> but is in 1.2.0. So i have looked through the SDFWriter >>> class and the first two points from my mail can be ignored. But >>> then is the >>> point open which concerns the atom IDs. This problem depends on the >>> MDLWriter class. >>> >> Can you please submit the last point is as patch? By posting the >> patch >> here, as at SourceForge? Then we can have a look at it in a format >> that makes it easier to see what changed... >> >> Egon >> >> > > /* $Revision$ $Author$ $Date$ > * > * Copyright (C) 1997-2007 The Chemistry Development Kit (CDK) project > * 2009 Egon Willighagen <eg...@us...> > * > * Contact: cdk...@li... > * > * This program 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. > * All we ask is that proper credit is given for our work, which > includes > * - but is not limited to - adding the above copyright notice to the > beginning > * of your source code files, and to any copyright notice that you > may distribute > * with programs based on this work. > * > * This program 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 program; if not, write to the Free Software > * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA > 02110-1301 USA. > */ > package CDKClasses; > > import java.io.BufferedWriter; > import java.io.IOException; > import java.io.OutputStream; > import java.io.OutputStreamWriter; > import java.io.StringWriter; > import java.io.Writer; > import java.text.NumberFormat; > import java.text.SimpleDateFormat; > import java.util.Calendar; > import java.util.Iterator; > import java.util.Locale; > import java.util.TimeZone; > > import org.openscience.cdk.CDKConstants; > import org.openscience.cdk.annotations.TestClass; > import org.openscience.cdk.annotations.TestMethod; > import org.openscience.cdk.config.IsotopeFactory; > import org.openscience.cdk.exception.CDKException; > import org.openscience.cdk.interfaces.IAtom; > import org.openscience.cdk.interfaces.IAtomContainer; > import org.openscience.cdk.interfaces.IBond; > 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.interfaces.IMolecule; > import org.openscience.cdk.interfaces.IPseudoAtom; > import org.openscience.cdk.io.DefaultChemObjectWriter; > import org.openscience.cdk.io.formats.IResourceFormat; > import org.openscience.cdk.io.formats.MDLFormat; > import org.openscience.cdk.tools.LoggingTool; > import org.openscience.cdk.tools.manipulator.ChemFileManipulator; > > /** > * Writes MDL molfiles, which contains a single molecule. > * For writing a MDL molfile you can this code: > * <pre> > * MDLWriter writer = new MDLWriter(new FileWriter(new > File("output.mol"))); > * writer.write((Molecule)molecule); > * writer.close(); > * </pre> > * > * See {@cdk.cite DAL92}. > * > * @cdk.module io > * @cdk.svnrev $Revision$ > * @cdk.keyword file format, MDL molfile > */ > @TestClass("org.openscience.cdk.io.MDLWriterTest") > public class MDLWriter extends DefaultChemObjectWriter { > > private final static LoggingTool logger = new > LoggingTool(MDLWriter.class); > > private BufferedWriter writer; > > /** > * Constructs a new MDLWriter that can write an {@link IMolecule} > * to the MDL molfile format. > * > * @param out The Writer to write to > */ > public MDLWriter(Writer out) { > if (out instanceof BufferedWriter) { > writer = (BufferedWriter)out; > } else { > writer = new BufferedWriter(out); > } > } > > /** > * Constructs a new MDLWriter that can write an {@link IMolecule} > * to a given OutputStream. > * > * @param output The OutputStream to write to > */ > public MDLWriter(OutputStream output) { > this(new OutputStreamWriter(output)); > } > > public MDLWriter() { > this(new StringWriter()); > } > > @TestMethod("testGetFormat") > public IResourceFormat getFormat() { > return MDLFormat.getInstance(); > } > > public void setWriter(Writer out) throws CDKException { > if (out instanceof BufferedWriter) { > writer = (BufferedWriter)out; > } else { > writer = new BufferedWriter(out); > } > } > > public void setWriter(OutputStream output) throws CDKException { > setWriter(new OutputStreamWriter(output)); > } > > /** > * Flushes the output and closes this object. > */ > @TestMethod("testClose") > public void close() throws IOException { > writer.close(); > } > > @TestMethod("testAccepts") > public boolean accepts(Class classObject) { > Class[] interfaces = classObject.getInterfaces(); > for (int i=0; i<interfaces.length; i++) { > if (IAtomContainer.class.equals(interfaces[i])) return true; > if (IChemFile.class.equals(interfaces[i])) return true; > if (IChemModel.class.equals(interfaces[i])) return true; > } > Class superClass = classObject.getSuperclass(); > if (superClass != null) return this.accepts(superClass); > return false; > } > > /** > * Writes a {@link IChemObject} to the MDL molfile formated output. > * It can only output ChemObjects of type {@link IChemFile}, > * {@link IMolecule} and {@link IAtomContainer}. > * > * @param object {@link IChemObject} to write > * > * @see #accepts(Class) > */ > public void write(IChemObject object) throws CDKException { > try { > if (object instanceof IChemFile) { > writeChemFile((IChemFile)object); > return; > } else if (object instanceof IChemModel) { > IChemFile file = object.getBuilder().newChemFile(); > IChemSequence sequence = object.getBuilder().newChemSequence(); > sequence.addChemModel((IChemModel)object); > file.addChemSequence(sequence); > writeChemFile((IChemFile)file); > return; > } else if (object instanceof IAtomContainer) { > writeMolecule((IAtomContainer)object); > return; > } > } catch (Exception ex) { > logger.error(ex.getMessage()); > logger.debug(ex); > throw new CDKException("Exception while writing MDL file: " + > ex.getMessage(), ex); > } > throw new CDKException("Only supported is writing of ChemFile, > MoleculeSet, AtomContainer and Molecule objects."); > } > > private void writeChemFile(IChemFile file) throws Exception { > IAtomContainer bigPile = file.getBuilder().newAtomContainer(); > for (IAtomContainer container : > ChemFileManipulator.getAllAtomContainers(file)) { > bigPile.add(container); > } > writeMolecule(bigPile); > } > > /** > * Writes a Molecule to an OutputStream in MDL sdf format. > * > * @param container Molecule that is written to an OutputStream > */ > public void writeMolecule(IAtomContainer container) throws > Exception { > String line = ""; > // write header block > // lines get shortened to 80 chars, that's in the spec > String title = > (String)container.getProperty(CDKConstants.TITLE); > if (title == null) title = ""; > if(title.length()>80) > title=title.substring(0,80); > writer.write(title); > writer.newLine(); > > /* From CTX spec > * This line has the format: > * IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR > * (FORTRAN: A2<--A8--><---A10-->A2I2<--F10.5-><---F12.5--><- > I6-> ) > * User's first and last initials (l), program name (P), > * date/time (M/D/Y,H:m), dimensional codes (d), scaling > factors (S, s), > * energy (E) if modeling program input, internal registry > number (R) > * if input through MDL form. > * A blank line can be substituted for line 2. > */ > writer.write(" CDK "); > writer.write(new SimpleDateFormat("M/d/ > y,H:m",Locale.US).format( > Calendar.getInstance(TimeZone.getDefault()).getTime()) > ); > writer.newLine(); > > String comment = > (String)container.getProperty(CDKConstants.REMARK); > if (comment == null) comment = ""; > if(comment.length()>80) > comment=comment.substring(0,80); > writer.write(comment); > writer.newLine(); > > // write Counts line > line += formatMDLInt(container.getAtomCount(), 3); > line += formatMDLInt(container.getBondCount(), 3); > line += " 0 0 0 0 0 0 0 0999 V2000"; > writer.write(line); > writer.newLine(); > > // write Atom block > for (int f = 0; f < container.getAtomCount(); f++) { > IAtom atom = container.getAtom(f); > line = ""; > if (atom.getPoint3d() != null) { > line += formatMDLFloat((float) atom.getPoint3d().x); > line += formatMDLFloat((float) atom.getPoint3d().y); > line += formatMDLFloat((float) atom.getPoint3d().z) + " "; > } else if (atom.getPoint2d() != null) { > line += formatMDLFloat((float) atom.getPoint2d().x); > line += formatMDLFloat((float) atom.getPoint2d().y); > line += " 0.0000 "; > } else { > // if no coordinates available, then output a number > // of zeros > line += formatMDLFloat((float)0.0); > line += formatMDLFloat((float)0.0); > line += formatMDLFloat((float)0.0) + " "; > } > if(container.getAtom(f) instanceof IPseudoAtom){ > //according to http://www.google.co.uk/url?sa=t&ct=res&cd=2&url=http%3A%2F%2Fwww.mdl.com%2Fdownloads%2Fpublic%2Fctfile%2Fctfile.pdf&ei=MsJjSMbjAoyq1gbmj7zCDQ&usg=AFQjCNGaJSvH4wYy4FTXIaQ5f7hjoTdBAw&sig2=eSfruNOSsdMFdlrn7nhdAw > an R group is written as R# > if(((IPseudoAtom) > container.getAtom(f)).getLabel().equals("R")) > line += "R#"; > else > line += formatMDLString(((IPseudoAtom) > container.getAtom(f)).getLabel(), 3); > }else{ > line += formatMDLString(container.getAtom(f).getSymbol(), 3); > } > line += " 0 0 0 0 0 0 0 0 0"; > // Set atom id to he mmm field at position 61-63. This field is > read by the MDLV2000Reader class to set the atom ID. > // If it is null set it to current atom number > if (container.getAtom(f).getID() != null) { > // try to parse the integer > String reactionAtomIDString = container.getAtom(f).getID(); > logger.debug("Parsing mapping id: ", reactionAtomIDString); > try { > int reactionAtomID = Integer.parseInt(reactionAtomIDString); > if (reactionAtomID != 0) { > line += this.formatMDLInt(reactionAtomID, 3); > } > } catch (Exception exception) { > logger.error("Mapping number ", reactionAtomIDString, " is not > an integer."); > logger.debug(exception); > // if id was no valid integer, set a new one. > line += this.formatMDLInt(f + 1, 3); > } > } else { > line += this.formatMDLInt(f + 1, 3); > } > line += " 0 0"; > writer.write(line); > writer.newLine(); > } > > // write Bond block > Iterator<IBond> bonds = container.bonds().iterator(); > while (bonds.hasNext()) { > IBond bond = (IBond) bonds.next(); > > if (bond.getAtomCount() != 2) { > logger.warn("Skipping bond with more/less than two atoms: " > + bond); > } else { > if (bond.getStereo() == CDKConstants.STEREO_BOND_UP_INV || > bond.getStereo() == CDKConstants.STEREO_BOND_DOWN_INV) { > // turn around atom coding to correct for inv stereo > line = > formatMDLInt(container.getAtomNumber(bond.getAtom(1)) + 1,3); > line += > formatMDLInt(container.getAtomNumber(bond.getAtom(0)) + 1,3); > } else { > line = > formatMDLInt(container.getAtomNumber(bond.getAtom(0)) + 1,3); > line += > formatMDLInt(container.getAtomNumber(bond.getAtom(1)) + 1,3); > } > line += formatMDLInt((int)bond.getOrder().ordinal()+1,3); > line += " "; > switch(bond.getStereo()){ > case CDKConstants.STEREO_BOND_UP: > line += "1"; > break; > case CDKConstants.STEREO_BOND_UP_INV: > line += "1"; > break; > case CDKConstants.STEREO_BOND_DOWN: > line += "6"; > break; > case CDKConstants.STEREO_BOND_DOWN_INV: > line += "6"; > break; > default: > line += "0"; > } > line += " 0 0 0 "; > writer.write(line); > writer.newLine(); > } > } > > // write formal atomic charges > for (int i = 0; i < container.getAtomCount(); i++) { > IAtom atom = container.getAtom(i); > int charge = atom.getFormalCharge(); > if (charge != 0) { > writer.write("M CHG 1 "); > writer.write(formatMDLInt(i+1,3)); > writer.write(" "); > writer.write(formatMDLInt(charge,3)); > writer.newLine(); > } > } > > // write formal isotope information > for (int i = 0; i < container.getAtomCount(); i++) { > IAtom atom = container.getAtom(i); > if (!(atom instanceof IPseudoAtom)) { > Integer atomicMass = atom.getMassNumber(); > if (atomicMass != null) { > int majorMass = > IsotopeFactory > .getInstance > (atom.getBuilder()).getMajorIsotope(atom.getSymbol()).getMassNumber(); > if (atomicMass != majorMass) { > writer.write("M ISO 1 "); > writer.write(formatMDLInt(i+1,3)); > writer.write(" "); > writer.write(formatMDLInt(atomicMass,3)); > writer.newLine(); > } > } > } > } > > // close molecule > writer.write("M END"); > writer.newLine(); > writer.flush(); > } > > /** > * Formats an integer to fit into the connection table and changes it > * to a String. > * > * @param i The int to be formated > * @param l Length of the String > * @return The String to be written into the connectiontable > */ > private String formatMDLInt(int i, int l) { > String s = "", fs = ""; > NumberFormat nf = > NumberFormat.getNumberInstance(Locale.ENGLISH); > nf.setParseIntegerOnly(true); > nf.setMinimumIntegerDigits(1); > nf.setMaximumIntegerDigits(l); > nf.setGroupingUsed(false); > s = nf.format(i); > l = l - s.length(); > for (int f = 0; f < l; f++) > fs += " "; > fs += s; > return fs; > } > > > > > /** > * Formats a float to fit into the connectiontable and changes it > * to a String. > * > * @param fl The float to be formated > * @return The String to be written into the connectiontable > */ > private String formatMDLFloat(float fl) { > String s = "", fs = ""; > int l; > NumberFormat nf = > NumberFormat.getNumberInstance(Locale.ENGLISH); > nf.setMinimumIntegerDigits(1); > nf.setMaximumIntegerDigits(4); > nf.setMinimumFractionDigits(4); > nf.setMaximumFractionDigits(4); > nf.setGroupingUsed(false); > s = nf.format(fl); > l = 10 - s.length(); > for (int f = 0; f < l; f++) > fs += " "; > fs += s; > return fs; > } > > > > /** > * Formats a String to fit into the connectiontable. > * > * @param s The String to be formated > * @param le The length of the String > * @return The String to be written in the connectiontable > */ > private String formatMDLString(String s, int le) { > s = s.trim(); > if (s.length() > le) > return s.substring(0, le); > int l; > l = le - s.length(); > for (int f = 0; f < l; f++) > s += " "; > return s; > } > > } > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by: > High Quality Requirements in a Collaborative Environment. > Download a free trial of Rational Requirements Composer Now! > http://p.sf.net/sfu/www-ibm-com_______________________________________________ > Cdk-devel mailing list > Cdk...@li... > https://lists.sourceforge.net/lists/listinfo/cdk-devel ------------------------------------------------------------------- Rajarshi Guha <rg...@in...> GPG Fingerprint: D070 5427 CC5B 7938 929C DD13 66A1 922C 51E7 9E84 ------------------------------------------------------------------- Q: What's polite and works for the phone company? A: A deferential operator. |
From: Egon W. <ego...@gm...> - 2009-04-08 19:45:53
|
On Wed, Apr 8, 2009 at 9:26 PM, Andreas Truszkowski <atr...@gm...> wrote: > Here is the patch. It is from the write atom block part and replaces "line > += " 0 0 0 0 0 0 0 0 0 0 0 0";" at line 265 of the original > class. The patched class is appended to the mail too. Thanx. > line += " 0 0 0 0 0 0 0 0 0"; > // Set atom id to the mmm field at position 61-63. This field is > read by the MDLV2000Reader class to set the atom ID. I guess it could actually use a few more patches there to replace all those zeros... > // If it is null set it to current atom number > if (container.getAtom(f).getID() != null) { > // try to parse the integer > String reactionAtomIDString = container.getAtom(f).getID(); Since the atom ID is something general, I suggest to rename the variable to simply atomIDString. > logger.debug("Parsing mapping id: ", reactionAtomIDString); > try { > int reactionAtomID = > Integer.parseInt(reactionAtomIDString); > if (reactionAtomID != 0) { > line += this.formatMDLInt(reactionAtomID, 3); > } > } catch (Exception exception) { > logger.error("Mapping number ", reactionAtomIDString, " > is not an integer."); The atom ID is in no formalism said to be an integer (and I'm sure we would have used getID() -> Integer then :), to this exception is not an error... please catch a NumberFormatException instead, and not log anything, but merely observe in the code that the ID is not a number. (All: are there no cleaner methods to see if an String reflects an Integer?) > logger.debug(exception); > // if id was no valid integer, set a new one. > line += this.formatMDLInt(f + 1, 3); > } > } else { > line += this.formatMDLInt(f + 1, 3); > } > line += " 0 0"; Otherwise, looks fine to me. Egon -- Post-doc @ Uppsala University http://chem-bla-ics.blogspot.com/ |
From: Egon W. <ego...@gm...> - 2009-04-11 12:07:24
|
On Wed, Apr 8, 2009 at 9:26 PM, Andreas Truszkowski <atr...@gm...> wrote: > Here is the patch. For it to be applied to the CDK 1.2.x branch... it also needs a unit test, testing that the IDs are properly written to file... I suggest writing to a StringWriter, to which you can do a toString() later, to have access to the file content without having to use a temporary file. Egon -- Post-doc @ Uppsala University http://chem-bla-ics.blogspot.com/ |
From: Stefan K. <ste...@eb...> - 2009-04-11 12:21:55
|
> The atom ID is in no formalism said to be an integer (and I'm sure we > would have used getID() -> Integer then :), to this exception is not > an error... please catch a NumberFormatException instead, and not log > anything, but merely observe in the code that the ID is not a number. > > (All: are there no cleaner methods to see if an String reflects an > Integer?) If it is really testing about if something is a Java int: No. I have seen many solutions for this over times with regexp and other things, but no one really covered all the situations (think about negative values, E representation, range etc.). What you could do is create a method like this: public boolean isParsableToInt(String i) { try { Integer.parseInt(i); return true; } catch(NumberFormatException nfe) { return false; } } to make the code look better. Stefan -- Stefan Kuhn B. Sc. M. A. Software Engineer in the Chemoinformatics and Metabolism Team European Bioinformatics Institute (EBI) Wellcome Trust Genome Campus Hinxton, Cambridge CB10 1SD UK Phone +44 1223 49 2657 Fax +44 (0)1223 494 468 |
From: Egon W. <ego...@gm...> - 2009-04-11 12:25:25
|
On Sat, Apr 11, 2009 at 2:21 PM, Stefan Kuhn <ste...@eb...> wrote: >> (All: are there no cleaner methods to see if an String reflects an >> Integer?) > > If it is really testing about if something is a Java int: No. I have seen many > solutions for this over times with regexp and other things, but no one really > covered all the situations (think about negative values, E representation, > range etc.). What you could do is create a method like this: > public boolean isParsableToInt(String i) { > try { > Integer.parseInt(i); > return true; > } catch(NumberFormatException nfe) { > return false; > } > } Well, the whole idea was in the first place not to have catch Exceptions... :( So, maybe we are just stuck with that... Egon -- Post-doc @ Uppsala University http://chem-bla-ics.blogspot.com/ |