Permalink
Browse files

Merge branch 'cdk-1.4.x'

  • Loading branch information...
2 parents 416a4cc + 49eb772 commit 9b48adbecb07c9a7a4f308a986d7188f98842c5a @egonw egonw committed Mar 13, 2011
Showing with 1,374 additions and 118 deletions.
  1. +13 −1 AUTHORS
  2. +8 −5 build.xml
  3. +24 −0 doc/refs/cheminf.bibx
  4. +2 −0 javadoc.xml
  5. +2 −0 pmd-migrating.xml
  6. +2 −0 pmd-unused.xml
  7. +4 −0 pmd.xml
  8. +0 −1 src/META-INF/fingerprint.cdkdepends
  9. +0 −1 src/META-INF/smarts.cdkdepends
  10. +7 −0 src/META-INF/tautomer.cdkdepends
  11. +2 −0 src/META-INF/test-dict.cdkdepends
  12. +1 −0 src/META-INF/test-qsarprotein.cdkdepends
  13. +14 −0 src/META-INF/test-tautomer.cdkdepends
  14. +1 −0 src/META-INF/test-tautomer.devellibdepends
  15. +4 −0 src/META-INF/test-tautomer.libdepends
  16. +8 −7 src/main/org/openscience/cdk/ChemObject.java
  17. +4 −0 src/main/org/openscience/cdk/atomtype/CDKAtomTypeMatcher.java
  18. +7 −0 src/main/org/openscience/cdk/dict/data/cdk-atom-types.owl
  19. +1 −1 src/main/org/openscience/cdk/fingerprint/PubchemFingerprinter.java
  20. +1 −1 src/main/org/openscience/cdk/formula/MolecularFormulaRange.java
  21. +4 −2 src/main/org/openscience/cdk/graph/PathTools.java
  22. +1 −1 src/main/org/openscience/cdk/io/CMLWriter.java
  23. +34 −9 src/main/org/openscience/cdk/io/HINReader.java
  24. +2 −2 src/main/org/openscience/cdk/isomorphism/matchers/OrderQueryBond.java
  25. +8 −3 src/main/org/openscience/cdk/isomorphism/matchers/smarts/OrderQueryBond.java
  26. +1 −1 src/main/org/openscience/cdk/libio/cml/Convertor.java
  27. +10 −3 src/main/org/openscience/cdk/qsar/AtomValenceTool.java
  28. +1 −1 src/main/org/openscience/cdk/qsar/descriptors/molecular/AcidicGroupCountDescriptor.java
  29. +684 −0 src/main/org/openscience/cdk/tautomers/InChITautomerGenerator.java
  30. +31 −0 src/test/data/hin/arorings.hin
  31. +18 −1 src/test/org/openscience/cdk/atomtype/CDKAtomTypeMatcherSMILESTest.java
  32. +46 −6 src/test/org/openscience/cdk/atomtype/CDKAtomTypeMatcherTest.java
  33. +48 −0 src/test/org/openscience/cdk/coverage/TautomerCoverageTest.java
  34. +2 −0 src/test/org/openscience/cdk/formula/MolecularFormulaRangeTest.java
  35. +41 −3 src/test/org/openscience/cdk/io/HINReaderTest.java
  36. +24 −21 src/test/org/openscience/cdk/io/cml/CDKRoundTripTest.java
  37. +42 −41 src/test/org/openscience/cdk/io/cml/CMLRoundTripTest.java
  38. +3 −4 src/test/org/openscience/cdk/io/cml/CMLRoundTripTool.java
  39. +32 −1 src/test/org/openscience/cdk/isomorphism/IsomorphismTesterTest.java
  40. +41 −0 src/test/org/openscience/cdk/modulesuites/MtautomerTests.java
  41. +17 −2 src/test/org/openscience/cdk/qsar/descriptors/molecular/MolecularDescriptorTest.java
  42. +16 −0 src/test/org/openscience/cdk/smiles/smarts/parser/SMARTSSearchTest.java
  43. +163 −0 src/test/org/openscience/cdk/tautomers/InChITautomerGeneratorTest.java
View
14 AUTHORS
@@ -1,6 +1,9 @@
Sam Adams
+Jonathan Alvarsson
Rich Apodaca
+Saravanaraj N Ayyampalayam
Ulrich Bauer
+Stephan Beisken
Arvid Berg
Ed Cannon
Fabian Dortu
@@ -18,19 +21,27 @@ Oliver Horlacher
Miguel Howard
Nina Jeliazkova
Geert Josten
+Dmitry Katsubo
+Jules Kerssemakers
Anatoli Krassavine
Stefan Kuhn
+Uli Köhler
Violeta Labarta
Daniel Leidert
Edgar Luttmann
Todd Martin
Nathanaël Mazuir
Stephan Michels
+Scooter Morris
Peter Murray-Rust
+Carl Mäsak
Irilenia Nobeli
+Peter Odéus
Niels Out
Jerome Pansanel
+Julio Peironcely
Chris Pudney
+Syed Asad Rahman
Jonathan Rienstra-Kiracofe
Mark Rijnbeek
David Robinson
@@ -44,9 +55,10 @@ Christoph Steinbeck
Aleksey Tarkhov
Stephan Tomkinson
Gilleain Torrance
+Andreas Truszkowski
+Paul Turner
Joerg Wegner
Stephane Werner
Egon Willighagen
Yong Zhang
Daniel Zaharevitz
-Syed Asad Rahman
View
13 build.xml
@@ -540,7 +540,7 @@
list="charges,smarts,signature"/>
<foreach target="compile-module" param="module"
parallel="${parallel}" maxthreads="${threadCount}"
- list="qm,qsar,ionpot,fingerprint,pcore,smsd"/>
+ list="qm,qsar,ionpot,fingerprint,pcore,smsd,tautomer"/>
<foreach target="compile-module" param="module"
parallel="${parallel}" maxthreads="${threadCount}"
list="qsaratomic,qsarbond,qsarprotein,qsarcml,qsarmolecular"/>
@@ -576,7 +576,7 @@
test-nonotify"/>
<foreach target="compile-module" param="module"
parallel="${parallel}" maxthreads="${threadCount}"
- list="test-qsarprotein,test-qsarionpot,test-smsd"/>
+ list="test-qsarprotein,test-qsarionpot,test-smsd,test-tautomer"/>
<foreach target="compile-module" param="module"
parallel="${parallel}" maxthreads="${threadCount}"
list="test-signature"/>
@@ -683,6 +683,7 @@
<include name="cdk-iordf.jar"/>
<include name="cdk-signature.jar"/>
<include name="cdk-qm.jar"/>
+ <include name="cdk-tautomer.jar"/>
</fileset>
</unjar>
@@ -753,6 +754,7 @@
<include name="cdk-formula.jar"/>
<include name="cdk-atomtype.jar"/>
<include name="cdk-signature.jar"/>
+ <include name="cdk-tautomer.jar"/>
</fileset>
</unjar>
@@ -846,7 +848,8 @@
<include name="cdk-test-render.jar"/>
<include name="cdk-test-log4j.jar"/>
<include name="cdk-test-signature.jar"/>
- <include name="cdk-test-cip.jar"/>
+ <include name="cdk-test-cip.jar"/>
+ <include name="cdk-test-tautomer.jar"/>
</fileset>
</unjar>
@@ -1060,12 +1063,12 @@
description="Performs a full JUnit test for the CDK."
if="junit.present">
<foreach target="test-module" param="module" trim="true"
- list="core,data,datadebug,diff,nonotify,atomtype,standard,
+ list="core,data,datadebug,dict,diff,nonotify,atomtype,standard,
io,builder3d,forcefield,valencycheck,charges,reaction,
smarts,fingerprint,smiles,qsar,qsaratomic,qsarbond,
qsarmolecular,qsarionpot,qsarprotein,pdb,pcore,inchi,
structgen,libiomd,libiocml,formula,render,extra,sdg,
- ioformats,log4j,smsd,signature,iordf,cip"/>
+ ioformats,log4j,smsd,signature,iordf,cip,tautomer"/>
</target>
<target id="limitations" name="limitations" depends="noJunit, dist-all"
View
24 doc/refs/cheminf.bibx
@@ -223,6 +223,19 @@
</bibtex:article>
</bibtex:entry>
+ <bibtex:entry id="FLO62">
+ <bibtex:article>
+ <bibtex:author>Floyd, R.W.</bibtex:author>
+ <bibtex:title>Algorithm 97: Shortest path</bibtex:title>
+ <bibtex:journal>Commun. ACM</bibtex:journal>
+ <bibtex:year>1962</bibtex:year>
+ <bibtex:volume>5</bibtex:volume>
+ <bibtex:number>6</bibtex:number>
+ <bibtex:pages>345</bibtex:pages>
+ <bibtex:doi>10.1145/367766.368168</bibtex:doi>
+ </bibtex:article>
+ </bibtex:entry>
+
<bibtex:entry id="GH82">
<bibtex:article>
<bibtex:author>Gasteiger, J. and Hutchings, M.G.</bibtex:author>
@@ -1121,5 +1134,16 @@ Method </bibtex:title>
<bibtex:pages>2-4</bibtex:pages>
</bibtex:article>
</bibtex:entry>
+
+ <bibtex:entry id="Thalheim2010">
+ <bibtex:article>
+ <bibtex:author>Thalheim, T. and Vollmer, A. and Ebert, R. and Kuehne, R. and Schuurmann, G.</bibtex:author>
+ <bibtex:title>Tautomer Identification and Tautomer Structure Generation Based on the InChI Code</bibtex:title>
+ <bibtex:journal>J. Chem. Inf. Model.</bibtex:journal>
+ <bibtex:year>2010</bibtex:year>
+ <bibtex:volume>50</bibtex:volume>
+ <bibtex:pages>1223-1232</bibtex:pages>
+ </bibtex:article>
+ </bibtex:entry>
</bibtex:file>
View
2 javadoc.xml
@@ -116,6 +116,7 @@
<antcall target="ojdcheck-module"><param name="module" value="nonotify"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="standard"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="atomtype"/></antcall>
+ <antcall target="ojdcheck-module"><param name="module" value="dict"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="io"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="ioformats"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="iordf"/></antcall>
@@ -131,6 +132,7 @@
<antcall target="ojdcheck-module"><param name="module" value="smiles"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="smarts"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="sdg"/></antcall>
+ <antcall target="ojdcheck-module"><param name="module" value="tautomer"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="forcefield"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="pdb"/></antcall>
<antcall target="ojdcheck-module"><param name="module" value="qsar"/></antcall>
View
2 pmd-migrating.xml
@@ -45,6 +45,7 @@
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="builder3d"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="smiles"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="smarts"/></antcall>
+ <antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="tautomer"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="pcore"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="forcefield"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="qsar"/></antcall>
@@ -73,6 +74,7 @@
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="test-reaction"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="test-smiles"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="test-standard"/></antcall>
+ <antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="test-tautomer"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="test-valencycheck"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="test-charges"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="migrating"/><param name="module" value="test-pcore"/></antcall>
View
2 pmd-unused.xml
@@ -53,6 +53,7 @@
<antcall target="test-module"><param name="module" value="qsarmolecular"/></antcall>
<antcall target="test-module"><param name="module" value="qsarprotein"/></antcall>
<antcall target="test-module"><param name="module" value="structgen"/></antcall>
+ <antcall target="test-module"><param name="module" value="tautomer"/></antcall>
<antcall target="test-module"><param name="module" value="valencycheck"/></antcall>
<antcall target="test-module"><param name="module" value="charges"/></antcall>
<antcall target="test-module"><param name="module" value="diff"/></antcall>
@@ -74,6 +75,7 @@
<antcall target="test-module"><param name="module" value="test-reaction"/></antcall>
<antcall target="test-module"><param name="module" value="test-smiles"/></antcall>
<antcall target="test-module"><param name="module" value="test-standard"/></antcall>
+ <antcall target="test-module"><param name="module" value="test-tautomer"/></antcall>
<antcall target="test-module"><param name="module" value="test-valencycheck"/></antcall>
<antcall target="test-module"><param name="module" value="test-charges"/></antcall>
<antcall target="test-module"><param name="module" value="test-pcore"/></antcall>
View
4 pmd.xml
@@ -36,6 +36,7 @@
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="log4j"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="standard"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="atomtype"/></antcall>
+ <antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="dict"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="io"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="extra"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="formula"/></antcall>
@@ -60,6 +61,7 @@
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="qsarprotein"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="structgen"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="sdg"/></antcall>
+ <antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="tautomer"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="valencycheck"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="charges"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom"/><param name="module" value="cip"/></antcall>
@@ -73,6 +75,7 @@
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-interfaces"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-data"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-datadebug"/></antcall>
+ <antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-dict"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-nonotify"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-extra"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-forcefield"/></antcall>
@@ -93,6 +96,7 @@
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-diff"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-qm"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-smsd"/></antcall>
+ <antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-tautomer"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-log4j"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-signature"/></antcall>
<antcall target="test-module"><param name="pmd.test" value="custom-test"/><param name="module" value="test-iordf"/></antcall>
View
1 src/META-INF/fingerprint.cdkdepends
@@ -7,4 +7,3 @@ cdk-isomorphism.jar
cdk-valencycheck.jar
cdk-smarts.jar
cdk-formula.jar
-cdk-smsd.jar
View
1 src/META-INF/smarts.cdkdepends
@@ -7,4 +7,3 @@ cdk-standard.jar
cdk-valencycheck.jar
cdk-isomorphism.jar
cdk-extra.jar
-cdk-smsd.jar
View
7 src/META-INF/tautomer.cdkdepends
@@ -0,0 +1,7 @@
+cdk-annotation.jar
+cdk-interfaces.jar
+cdk-core.jar
+cdk-standard.jar
+cdk-smsd.jar
+cdk-inchi.jar
+
View
2 src/META-INF/test-dict.cdkdepends
@@ -1,3 +1,5 @@
cdk-annotation.jar
cdk-dict.jar
cdk-test.jar
+cdk-interfaces.jar
+cdk-core.jar
View
1 src/META-INF/test-qsarprotein.cdkdepends
@@ -21,3 +21,4 @@ cdk-sdg.jar
cdk-test-qsar.jar
cdk-testdata.jar
cdk-test-qsarmolecular.jar
+cdk-dict.jar
View
14 src/META-INF/test-tautomer.cdkdepends
@@ -0,0 +1,14 @@
+cdk-annotation.jar
+cdk-interfaces.jar
+cdk-core.jar
+cdk-standard.jar
+cdk-data.jar
+cdk-smsd.jar
+cdk-smiles.jar
+cdk-io.jar
+cdk-inchi.jar
+cdk-tautomer.jar
+cdk-valencycheck.jar
+cdk-nonotify.jar
+cdk-test.jar
+
View
1 src/META-INF/test-tautomer.devellibdepends
@@ -0,0 +1 @@
+junit-4.5.jar
View
4 src/META-INF/test-tautomer.libdepends
@@ -0,0 +1,4 @@
+vecmath1.2-1.14.jar
+jgrapht-0.6.0.jar
+jniinchi-0.7.jar
+
View
15 src/main/org/openscience/cdk/ChemObject.java
@@ -25,19 +25,20 @@
*/
package org.openscience.cdk;
+import org.openscience.cdk.event.ChemObjectChangeEvent;
+import org.openscience.cdk.interfaces.IChemObject;
+import org.openscience.cdk.interfaces.IChemObjectBuilder;
+import org.openscience.cdk.interfaces.IChemObjectChangeEvent;
+import org.openscience.cdk.interfaces.IChemObjectListener;
+
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import org.openscience.cdk.event.ChemObjectChangeEvent;
-import org.openscience.cdk.interfaces.IChemObject;
-import org.openscience.cdk.interfaces.IChemObjectChangeEvent;
-import org.openscience.cdk.interfaces.IChemObjectListener;
-import org.openscience.cdk.interfaces.IChemObjectBuilder;
-
/**
* The base class for all chemical objects in this cdk. It provides methods for
* adding listeners and for their notification of events, as well a a hash
@@ -220,7 +221,7 @@ public void notifyChanged(IChemObjectChangeEvent evt) {
{
if (properties == null)
{
- properties = new HashMap<Object, Object>();
+ properties = new LinkedHashMap<Object, Object>();
}
return properties;
}
View
4 src/main/org/openscience/cdk/atomtype/CDKAtomTypeMatcher.java
@@ -1234,6 +1234,10 @@ private IAtomType perceiveCommonSalts(IAtomContainer atomContainer, IAtom atom)
atom.getFormalCharge() == +2)) {
IAtomType type = getAtomType("Co.2plus");
if (isAcceptable(atom, atomContainer, type)) return type;
+ } else if ((atom.getFormalCharge() != CDKConstants.UNSET &&
+ atom.getFormalCharge() == +3)) {
+ IAtomType type = getAtomType("Co.3plus");
+ if (isAcceptable(atom, atomContainer, type)) return type;
} else if ((atom.getFormalCharge() == CDKConstants.UNSET ||
atom.getFormalCharge() == 0)) {
IAtomType type = getAtomType("Co.metallic");
View
7 src/main/org/openscience/cdk/dict/data/cdk-atom-types.owl
@@ -1227,6 +1227,13 @@
<at:piBondCount>0</at:piBondCount>
</at:AtomType>
+ <at:AtomType rdf:ID="Co.3plus">
+ <at:formalCharge>3</at:formalCharge>
+ <at:hasElement rdf:resource="&elem;Co"/>
+ <at:formalNeighbourCount>0</at:formalNeighbourCount>
+ <at:piBondCount>0</at:piBondCount>
+ </at:AtomType>
+
<at:AtomType rdf:ID="Co.metallic">
<at:formalCharge>0</at:formalCharge>
<at:hasElement rdf:resource="&elem;Co"/>
View
2 src/main/org/openscience/cdk/fingerprint/PubchemFingerprinter.java
@@ -105,7 +105,7 @@ public PubchemFingerprinter() {
}
/**
- * Calculate 881 bit Pubchem fingperprint for a molecule.
+ * Calculate 881 bit Pubchem fingerprint for a molecule.
* <p/>
* See
* <a href="ftp://ftp.ncbi.nlm.nih.gov/pubchem/specifications/pubchem_fingerprints.txt">here</a>
View
2 src/main/org/openscience/cdk/formula/MolecularFormulaRange.java
@@ -222,7 +222,7 @@ public Object clone() throws CloneNotSupportedException {
*/
private boolean isTheSame(IIsotope isotopeOne, IIsotope isotopeTwo) {
- if(isotopeOne.getSymbol() != isotopeTwo.getSymbol() )
+ if(!isotopeOne.getSymbol().equals(isotopeTwo.getSymbol()) )
return false;
if(isotopeOne.getNaturalAbundance() != isotopeTwo.getNaturalAbundance() )
return false;
View
6 src/main/org/openscience/cdk/graph/PathTools.java
@@ -69,7 +69,8 @@
/**
- * All-Pairs-Shortest-Path computation based on Floyds algorithm. Takes an nxn
+ * All-Pairs-Shortest-Path computation based on Floyd's
+ * algorithm {@cdk.cite FLO62}. It takes an nxn
* matrix C of edge costs and produces an nxn matrix A of lengths of shortest
* paths.
*
@@ -111,7 +112,8 @@
}
/**
- * All-Pairs-Shortest-Path computation based on Floyds algorithm Takes an nxn
+ * All-Pairs-Shortest-Path computation based on Floyd's
+ * algorithm {@cdk.cite FLO62}. It takes an nxn
* matrix C of edge costs and produces an nxn matrix A of lengths of shortest
* paths.
*
View
2 src/main/org/openscience/cdk/io/CMLWriter.java
@@ -126,7 +126,7 @@
private static ILoggingTool logger =
LoggingToolFactory.createLoggingTool(CMLWriter.class);
- private static List<ICMLCustomizer> customizers = null;
+ private List<ICMLCustomizer> customizers = null;
/**
* Constructs a new CMLWriter class. Output will be stored in the Writer
View
43 src/main/org/openscience/cdk/io/HINReader.java
@@ -1,6 +1,6 @@
/* $Revision$ $Author$ $Date$
*
- * Copyright (C) 2004-2007 Rajarshi Guha <rajarshi@presidency.com>
+ * Copyright (C) 2004-2007 Rajarshi Guha <rajarshi.guha@gmail.com>
*
* Contact: cdk-devel@lists.sourceforge.net
*
@@ -53,7 +53,7 @@
* @cdk.module io
* @cdk.githash
*
- * @author Rajarshi Guha <rajarshi@presidency.com>
+ * @author Rajarshi Guha <rajarshi.guha@gmail.com>
* @cdk.created 2004-01-27
*
* @cdk.keyword file format, HIN
@@ -160,6 +160,8 @@ private IChemFile readChemFile(IChemFile file) {
String info;
StringTokenizer tokenizer;
+ List<String> aroringText = new ArrayList<String>();
+ List<IMolecule> mols = new ArrayList<IMolecule>();
try {
String line;
@@ -255,27 +257,50 @@ private IChemFile readChemFile(IChemFile file) {
if (!isConnected(m, s, e))
m.addBond(file.getBuilder().newInstance(IBond.class,s, e, bo));
}
- setOfMolecules.addMolecule(m);
+ mols.add(m);
// we may not get a 'mol N' immediately since
// the aromaticring keyword might be present
// and doesn't seem to be located within the molecule
- // block
+ // block. However, if we do see this keyword we save this
+ // since it can contain aromatic specs for any molecule
+ // listed in the file
+ //
+ // The docs do not explicitly state the the keyword comes
+ // after *all* molecules. So we save and then reprocess
+ // all the molecules in a second pass
while (true) {
line = input.readLine();
if (line == null || line.startsWith("mol")) break;
+ if (line.startsWith("aromaticring")) aroringText.add(line.trim());
}
}
- // got all the molecule in the HIN file (hopefully!)
- chemModel.setMoleculeSet(setOfMolecules);
- chemSequence.addChemModel(chemModel);
- file.addChemSequence(chemSequence);
-
} catch (IOException e) {
// FIXME: should make some noise now
file = null;
}
+
+ if (aroringText.size() > 0) { // process aromaticring annotations
+ for (String line : aroringText) {
+ String[] toks = line.split(" ");
+ int natom = Integer.parseInt(toks[1]);
+ int n = 0;
+ for (int i = 2; i < toks.length; i += 2) {
+ int molnum = Integer.parseInt(toks[i]); // starts from 1
+ int atnum = Integer.parseInt(toks[i+1]); // starts from 1
+ mols.get(molnum-1).getAtom(atnum-1).setFlag(CDKConstants.ISAROMATIC, true);
+ n++;
+ }
+ assert n == natom;
+ }
+ }
+
+ for (IMolecule mol : mols) setOfMolecules.addMolecule(mol);
+ chemModel.setMoleculeSet(setOfMolecules);
+ chemSequence.addChemModel(chemModel);
+ file.addChemSequence(chemSequence);
+
return file;
}
View
4 src/main/org/openscience/cdk/isomorphism/matchers/OrderQueryBond.java
@@ -48,10 +48,10 @@ public boolean matches(IBond bond) {
return true;
} else if (this.getFlag(CDKConstants.ISAROMATIC) &&
bond.getFlag(CDKConstants.ISAROMATIC)) {
- // or both are aromatic
+ return true;
} // else
return false;
- };
+ };
public void setAtoms(IAtom[] atoms) {
if (atoms.length > 0 && atoms[0] instanceof IQueryAtom) {
View
11 src/main/org/openscience/cdk/isomorphism/matchers/smarts/OrderQueryBond.java
@@ -54,9 +54,14 @@ public OrderQueryBond(IBond.Order order) {
* @see org.openscience.cdk.isomorphism.matchers.smarts.SMARTSBond#matches(org.openscience.cdk.interfaces.IBond)
*/
public boolean matches(IBond bond) {
- if (getOrder() == IBond.Order.SINGLE) {
- return !bond.getFlag(CDKConstants.ISAROMATIC) && getOrder() == bond.getOrder();
- } else return getOrder() == bond.getOrder();
+ if (bond.getFlag(CDKConstants.ISAROMATIC) ^ getFlag(CDKConstants.ISAROMATIC)) return false;
+
+ // we check for both bonds being aromatic - but the query will
+ // never come in as aromatic (since there is a separate aromatic
+ // query bond). But no harm in checking
+ if (bond.getFlag(CDKConstants.ISAROMATIC) && getFlag(CDKConstants.ISAROMATIC)) return true;
+
+ return bond.getOrder() == getOrder();
}
/* (non-Javadoc)
View
2 src/main/org/openscience/cdk/libio/cml/Convertor.java
@@ -101,7 +101,7 @@
LoggingToolFactory.createLoggingTool(Convertor.class);
private final static String CUSTOMIZERS_LIST = "libio-cml-customizers.set";
- private static Map<String, ICMLCustomizer> customizers = null;
+ private Map<String, ICMLCustomizer> customizers = null;
private boolean useCMLIDs;
private String prefix;
View
13 src/main/org/openscience/cdk/qsar/AtomValenceTool.java
@@ -21,11 +21,11 @@
*/
package org.openscience.cdk.qsar;
+import org.openscience.cdk.interfaces.IAtom;
+
import java.util.HashMap;
import java.util.Map;
-import org.openscience.cdk.interfaces.IAtom;
-
/**
* This class returns the valence of an atom.
*
@@ -41,8 +41,15 @@
public static int getValence(IAtom atom) {
if (valencesTable == null) {
- valencesTable = new HashMap<String,Integer>();
+ valencesTable = new HashMap<String, Integer>();
valencesTable.put("H", 1);
+ valencesTable.put("He", 8);
+ valencesTable.put("Ne", 8);
+ valencesTable.put("Ar", 8);
+ valencesTable.put("Kr", 8);
+ valencesTable.put("Xe", 8);
+ valencesTable.put("Hg", 2);
+ valencesTable.put("Rn", 8);
valencesTable.put("Li", 1);
valencesTable.put("Be", 2);
valencesTable.put("B", 3);
View
2 src/main/org/openscience/cdk/qsar/descriptors/molecular/AcidicGroupCountDescriptor.java
@@ -76,7 +76,7 @@ public AcidicGroupCountDescriptor() throws CDKException {
@TestMethod("testGetSpecification")
public DescriptorSpecification getSpecification() {
return new DescriptorSpecification(
- "http://www.blueobelisk.org/ontologies/chemoinformatics-algorithms/#acidGroupCount",
+ "http://www.blueobelisk.org/ontologies/chemoinformatics-algorithms/#acidicGroupCount",
this.getClass().getName(),
"$Id$",
"The Chemistry Development Kit"
View
684 src/main/org/openscience/cdk/tautomers/InChITautomerGenerator.java
@@ -0,0 +1,684 @@
+/* Copyright (C) 2011 Mark Rijnbeek <markr@ebi.ac.uk>
+ *
+ * Contact: cdk-devel@lists.sourceforge.net
+ *
+ * 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 org.openscience.cdk.tautomers;
+
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.openscience.cdk.CDKConstants;
+import org.openscience.cdk.annotations.TestClass;
+import org.openscience.cdk.annotations.TestMethod;
+import org.openscience.cdk.exception.CDKException;
+import org.openscience.cdk.inchi.InChIGenerator;
+import org.openscience.cdk.inchi.InChIGeneratorFactory;
+import org.openscience.cdk.interfaces.IAtom;
+import org.openscience.cdk.interfaces.IAtomContainer;
+import org.openscience.cdk.interfaces.IAtomType;
+import org.openscience.cdk.interfaces.IBond;
+import org.openscience.cdk.smsd.Isomorphism;
+import org.openscience.cdk.smsd.interfaces.Algorithm;
+import org.openscience.cdk.tools.ILoggingTool;
+import org.openscience.cdk.tools.LoggingToolFactory;
+
+
+/**
+ * Creates tautomers for a given input molecule, based on the mobile H atoms listed in the InChI.
+ * Algorithm described in {@cdk.cite Thalheim2010}.
+ * <br>
+ * <B>Provide your input molecules in Kekule form.</B></br>
+ * When creating an input molecule by reading an MDL file, make sure to set implicit hydrogens. See the
+ * {@link InChITautomerGeneratorTest test case}.
+ * @author Mark Rijnbeek
+ * @cdk.module tautomer
+ */
+@TestClass("org.openscience.cdk.tautomers.InChITautomerGeneratorTest")
+public class InChITautomerGenerator {
+
+ private final static ILoggingTool LOGGER = LoggingToolFactory.createLoggingTool(InChITautomerGenerator.class);
+
+ /**
+ * Public method to get tautomers for an input molecule, based on the InChI which will be calculated by jniinchi.
+ * @param molecule molecule for which to generate tautomers
+ * @return a list of tautomers, if any
+ * @throws CDKException
+ * @throws CloneNotSupportedException
+ */
+ @TestMethod("test_withJniInchi")
+ public List<IAtomContainer> getTautomers(IAtomContainer molecule) throws CDKException, CloneNotSupportedException {
+
+ InChIGenerator gen = InChIGeneratorFactory.getInstance().getInChIGenerator(molecule);
+ String inchi = gen.getInchi();
+ if (inchi == null)
+ throw new CDKException(InChIGenerator.class +
+ " failed to create an InChI for the provided molecule, InChI -> null.");
+ return getTautomers(molecule, inchi);
+ }
+
+ /**
+ * Overloaded {@link #getTautomers(IAtomContainer)} to get tautomers for an input molecule with the InChI already
+ * provided as input argument.
+ * @param inputMolecule and input molecule for which to generate tautomers
+ * @param inchi InChI for the inpute molecule
+ * @return a list of tautomers
+ * @throws CDKException
+ * @throws CloneNotSupportedException
+ */
+ @TestMethod("test1,test2,test3")
+ public List<IAtomContainer> getTautomers(IAtomContainer inputMolecule, String inchi)
+ throws CDKException, CloneNotSupportedException {
+
+ //Initial checks
+ if (inputMolecule == null || inchi == null)
+ throw new CDKException("Please provide a valid input molecule and its corresponding InChI value.");
+
+ List<IAtomContainer> tautomers = new ArrayList<IAtomContainer>();
+ if (inchi.indexOf("(H") == -1) { //No mobile H atoms according to InChI, so bail out.
+ tautomers.add(inputMolecule);
+ return tautomers;
+ }
+
+ //Preparation: translate the InChi
+ Map<Integer, IAtom> inchiAtomsByPosition = getElementsByPosition(inchi,inputMolecule);
+ IAtomContainer inchiMolGraph = connectAtoms(inchi,inputMolecule,inchiAtomsByPosition);
+ List<IAtomContainer> mappedContainers = mapInputMoleculeToInchiMolgraph(inchiMolGraph,inputMolecule);
+ inchiMolGraph = mappedContainers.get(0);
+ inputMolecule = mappedContainers.get(1);
+ List<Integer> mobHydrAttachPositions= new ArrayList<Integer>();
+ int totalMobHydrCount = parseMobileHydrogens(mobHydrAttachPositions, inchi);
+
+ tautomers = constructTautomers(inputMolecule,mobHydrAttachPositions,totalMobHydrCount);
+ //Remove duplicates
+ return removeDuplicates(tautomers);
+ }
+
+
+ /**
+ * Parses the InChI's formula (ignoring hydrogen) and returns a map
+ * with with a position for each atom, increasing in the order
+ * of the elements as listed in the formula.
+ * @param inputInchi user input InChI
+ * @param inputMolecule user input molecule
+ * @return <Integer,IAtom> map indicating position and atom
+ */
+ private Map<Integer, IAtom> getElementsByPosition(String inputInchi,IAtomContainer inputMolecule) throws CDKException {
+ Map<Integer, IAtom> inchiAtomsByPosition = new HashMap<Integer, IAtom>();
+ int position = 0;
+ String inchi = inputInchi;
+
+ inchi = inchi.substring(inchi.indexOf('/') + 1);
+ String formula = inchi.substring(0, inchi.indexOf('/'));
+
+ /* Test for dots in the formula. For now, bail out when encountered;
+ * it would require more sophisticated InChI connection table parsing.
+ *
+ * Example: what happened to tyhe platinum connectivity below?
+ * N.N.O=C1O[Pt]OC(=O)C12CCC2<br>
+ * InChI=1S/C6H8O4.2H3N.Pt/c7-4(8)6(5(9)10)2-1-3-6;;;/h1-3H2,(H,7,8)(H,9,10);2*1H3;/q;;;+2/p-2*/
+ if (formula.contains("."))
+ throw new CDKException
+ ("Cannot parse InChI, formula contains dot (unsupported feature). Input formula=" +formula);
+
+ Pattern formulaPattern = Pattern.compile("\\.?[0-9]*[A-Z]{1}[a-z]?[0-9]*");
+ Matcher match = formulaPattern.matcher(formula);
+ while (match.find()) {
+ String symbolAndCount = match.group();
+ String elementSymbol = (symbolAndCount.split("[0-9]"))[0];
+ if (!elementSymbol.equals("H")) {
+ int elementCnt = 1;
+ if (!(elementSymbol.length() == symbolAndCount.length())) {
+ elementCnt = Integer.valueOf(symbolAndCount.substring(elementSymbol.length()));
+ }
+
+ for (int i = 0; i < elementCnt; i++) {
+ position++;
+ IAtom atom = inputMolecule.getBuilder().newInstance(IAtom.class, elementSymbol);
+ /* This class uses the atom's ID attribute to keep track of atom positions defined in the InChi.
+ * So if for example atom.ID=14, it means this atom has position 14 in the InChI connection table.*/
+ atom.setID(position + "");
+ inchiAtomsByPosition.put(position, atom);
+ }
+ }
+ }
+ return inchiAtomsByPosition;
+ }
+
+ /**
+ * Pops and pushes its ways through the InChI connection table to build up a simple molecule.
+ * @param inputInchi user input InChI
+ * @param inputMolecule user input molecule
+ * @param inchiAtomsByPosition
+ * @return molecule with single bonds and no hydrogens.
+ */
+ private IAtomContainer connectAtoms
+ (String inputInchi,IAtomContainer inputMolecule,Map<Integer, IAtom> inchiAtomsByPosition) throws CDKException {
+ String inchi = inputInchi;
+ inchi = inchi.substring(inchi.indexOf('/') + 1);
+ inchi = inchi.substring(inchi.indexOf('/') + 1);
+ String connections = inchi.substring(1, inchi.indexOf('/'));
+ Pattern connectionPattern = Pattern.compile("(-|\\(|\\)|,|([0-9])*)");
+ Matcher match = connectionPattern.matcher(connections);
+ Stack<IAtom> atomStack = new Stack<IAtom>();
+ IAtomContainer inchiMolGraph = inputMolecule.getBuilder().newInstance(IAtomContainer.class);
+ boolean pop = false;
+ boolean push = true;
+ while (match.find()) {
+ String group = match.group();
+ push = true;
+ if (!group.isEmpty()) {
+ if (group.matches("[0-9]*")) {
+ IAtom atom = inchiAtomsByPosition.get(Integer.valueOf(group));
+ if (!inchiMolGraph.contains(atom))
+ inchiMolGraph.addAtom(atom);
+ IAtom prevAtom = null;
+ if (atomStack.size() != 0) {
+ if (pop) {
+ prevAtom = atomStack.pop();
+ } else {
+ prevAtom = atomStack.get(atomStack.size() - 1);
+ }
+ IBond bond =
+ inputMolecule.getBuilder().newInstance(IBond.class, prevAtom, atom, IBond.Order.SINGLE);
+ inchiMolGraph.addBond(bond);
+ }
+ if (push) {
+ atomStack.push(atom);
+ }
+ } else if (group.equals("-")) {
+ pop = true;
+ push = true;
+ } else if (group.equals(",")) {
+ atomStack.pop();
+ pop = false;
+ push = false;
+ } else if (group.equals("(")) {
+ pop = false;
+ push = true;
+ } else if (group.equals(")")) {
+ atomStack.pop();
+ pop = true;
+ push = true;
+ } else {
+ throw new CDKException("Unexpected token " + group + " in connection table encountered.");
+ }
+ }
+ }
+ //put any unconnected atoms in the output as well
+ for (IAtom at : inchiAtomsByPosition.values()) {
+ if (!inchiMolGraph.contains(at))
+ inchiMolGraph.addAtom(at);
+ }
+ return inchiMolGraph;
+ }
+
+
+ /**
+ * Atom-atom mapping of the input molecule to the bare container constructed from the InChI connection table.
+ * This makes it possible to map the positions of the mobile hydrogens in the InChI back to the input molecule.
+ * @param inchiMolGraph molecule (bare) as defined in InChI
+ * @param inputMolecule user input molecule
+ * @throws CDKException
+ */
+ private List<IAtomContainer> mapInputMoleculeToInchiMolgraph(IAtomContainer inchiMolGraph,
+ IAtomContainer inputMolecule)
+ throws CDKException {
+ List<IAtomContainer> mappedContainers = new ArrayList<IAtomContainer>();
+ Isomorphism isomorphism = new Isomorphism(Algorithm.TurboSubStructure, false);
+ isomorphism.init(inchiMolGraph, inputMolecule, true, false);
+ isomorphism.setChemFilters(true, true, true);
+ Map<IAtom, IAtom> mapping = isomorphism.getFirstAtomMapping();
+ inchiMolGraph = isomorphism.getReactantMolecule();
+ inputMolecule = isomorphism.getProductMolecule();
+ for (IAtom inchiAtom : inchiMolGraph.atoms()) {
+ String position = inchiAtom.getID();
+ IAtom molAtom = mapping.get(inchiAtom);
+ molAtom.setID(position);
+ LOGGER.debug("Mapped InChI ",inchiAtom.getSymbol()," ",inchiAtom.getID(),
+ " to ",molAtom.getSymbol()," "+molAtom.getID());
+ }
+ mappedContainers.add(inchiMolGraph);
+ mappedContainers.add(inputMolecule);
+ return mappedContainers;
+ }
+
+ /**
+ * Parses mobile H group(s) in an InChI String.
+ * <p>
+ * Multiple InChI sequences of mobile hydrogens are joined into a single sequence (list),
+ * see step 1 of algorithm in paper.
+ * <br>
+ * Mobile H group has syntax (H[n][-[m]],a1,a2[,a3[,a4...]])
+ * Brackets [ ] surround optional terms.
+ * <ul>
+ * <li>Term H[n] stands for 1 or, if the number n (n>1) is present, n mobile hydrogen atoms.</li>
+ * <li>Term [-[m]], if present, stands for 1 or, if the number m (m>1) is present, m mobile negative charges.</li>
+ * <li>a1,a2[,a3[,a4...]] are canonical numbers of atoms in the mobile H group.</li>
+ * <li>no two mobile H groups may have an atom (a canonical number) in common.</li>
+ * </ul>
+ * @param mobHydrAttachPositions list of positions where mobile H can attach
+ * @param inputInchi InChI input
+ * @return overall count of hydrogens to be dispersed over the positions
+ */
+ private int parseMobileHydrogens(List<Integer> mobHydrAttachPositions,String inputInchi) {
+
+ int totalMobHydrCount = 0;
+ String hydrogens = "";
+ String inchi = inputInchi;
+ if (inchi.indexOf("/h") != -1) {
+ hydrogens = inchi.substring(inchi.indexOf("/h") + 2);
+ if (hydrogens.indexOf('/') != -1) {
+ hydrogens = hydrogens.substring(0, hydrogens.indexOf('/'));
+ }
+ String mobileHydrogens = hydrogens.substring(hydrogens.indexOf('('));
+ Pattern mobileHydrPattern = Pattern.compile("\\((.)*?\\)");
+ Matcher match = mobileHydrPattern.matcher(mobileHydrogens);
+ while (match.find()) {
+ String mobileHGroup = match.group();
+ int mobHCount = 0;
+ String head = mobileHGroup.substring(0, mobileHGroup.indexOf(',') + 1);
+ if (head.contains("H,"))
+ head = head.replace("H,", "H1,");
+ if (head.contains("-,"))
+ head = head.replace("-,", "-1,");
+ head = head.substring(2);
+ Pattern subPattern = Pattern.compile("[0-9]*");
+ Matcher subMatch = subPattern.matcher(head);
+ /*
+ Pragmatically, also add any delocalised neg charge to the mobile H count.
+ Based on examples like:
+ C[N+](C)(C)CCCCC\C=C(/NC(=O)C1CC1(Cl)Cl)\C(=O)O -> ...(H-,18,20,21,22)
+ COc1cc(N)c(Cl)cc1C(=O)NC2C[N+]3(CCl)CCC2CC3 -> ...(H2-,19,20,22)
+ */
+ while (subMatch.find()) {
+ if (!subMatch.group().equals("")) {
+ mobHCount += Integer.valueOf(subMatch.group());
+ }
+ }
+ totalMobHydrCount += mobHCount;
+ mobileHGroup = mobileHGroup.substring(mobileHGroup.indexOf(',') + 1).replace(")", "");
+ StringTokenizer tokenizer = new StringTokenizer(mobileHGroup, ",");
+ while (tokenizer.hasMoreTokens()) {
+ Integer position = Integer.valueOf(tokenizer.nextToken());
+ mobHydrAttachPositions.add(position);
+ }
+ }
+ }
+ LOGGER.debug("#total mobile hydrogens: ",totalMobHydrCount);
+ return totalMobHydrCount;
+ }
+
+
+ /**
+ * Constructs tautomers following (most) steps of the algorithm in {@cdk.cite Thalheim2010}.
+ * @param inputMolecule input molecule
+ * @param mobHydrAttachPositions mobile H positions
+ * @param totalMobHydrCount count of mobile hydrogens in molecule
+ * @return tautomers
+ * @throws CloneNotSupportedException
+ */
+ private List<IAtomContainer> constructTautomers(IAtomContainer inputMolecule,List<Integer> mobHydrAttachPositions,
+ int totalMobHydrCount)
+ throws CloneNotSupportedException {
+ List<IAtomContainer> tautomers = new ArrayList<IAtomContainer>();
+
+ //Tautomeric skeleton generation
+ IAtomContainer skeleton = (IAtomContainer)inputMolecule.clone();
+
+ boolean atomsToRemove = true;
+ List<IAtom> removedAtoms = new ArrayList<IAtom>();
+ boolean atomRemoved=false;
+ while (atomsToRemove) {
+ ATOMS:
+ for (IAtom atom : skeleton.atoms()) {
+ atomRemoved=false;
+ int position = Integer.valueOf(atom.getID());
+ if (!mobHydrAttachPositions.contains(position) &&
+ atom.getHybridization().equals(IAtomType.Hybridization.SP3)) {
+ skeleton.removeAtom(atom);
+ removedAtoms.add(atom);
+ atomRemoved=true;
+ break ATOMS;
+ } else {
+ for (IBond bond : skeleton.bonds()) {
+ if (bond.contains(atom) && bond.getOrder().equals(IBond.Order.TRIPLE)) {
+ skeleton.removeAtom(atom);
+ removedAtoms.add(atom);
+ atomRemoved=true;
+ break ATOMS;
+ }
+ }
+ }
+ }
+ if (!atomRemoved)
+ atomsToRemove = false;
+
+ }
+ boolean bondsToRemove = true;
+ boolean bondRemoved=false;
+ while (bondsToRemove) {
+ BONDS:
+ for (IBond bond : skeleton.bonds()) {
+ bondRemoved=false;
+ for (IAtom removedAtom : removedAtoms) {
+ if (bond.contains(removedAtom)) {
+ IAtom other = bond.getConnectedAtom(removedAtom);
+ int decValence = 0;
+ switch (bond.getOrder()) {
+ case SINGLE:
+ decValence = 1;
+ break;
+ case DOUBLE:
+ decValence = 2;
+ break;
+ case TRIPLE:
+ decValence = 3;
+ break;
+ case QUADRUPLE:
+ decValence = 4;
+ break;
+ }
+ other.setValency(other.getValency() - decValence);
+ skeleton.removeBond(bond);
+ bondRemoved=true;
+ break BONDS;
+ }
+ }
+ }
+ if (!bondRemoved)
+ bondsToRemove = false;
+
+ }
+ int doubleBondCount = 0;
+ for (IBond bond : skeleton.bonds()) {
+ if (bond.getOrder().equals(IBond.Order.DOUBLE)) {
+ doubleBondCount++;
+ }
+ }
+
+ for (int hPosition : mobHydrAttachPositions) {
+ IAtom atom = findAtomByPosition (skeleton, hPosition);
+ atom.setImplicitHydrogenCount(0);
+ }
+
+ for (IBond bond : skeleton.bonds()) {
+ if (bond.getOrder().equals(IBond.Order.DOUBLE)) {
+ bond.setOrder(IBond.Order.SINGLE);
+ }
+ }
+
+ // Make combinations for mobile Hydrogen attachments
+ List<List<Integer>> combinations = new ArrayList<List<Integer>>();
+ combineHydrogenPositions(new ArrayList<Integer>(),combinations,skeleton,
+ totalMobHydrCount,mobHydrAttachPositions);
+
+ Stack<Object> solutions = new Stack<Object>();
+ for (List<Integer> hPositions : combinations) {
+ IAtomContainer tautomerSkeleton = (IAtomContainer)skeleton.clone();
+ for (Integer hPos : hPositions) {
+ IAtom atom = findAtomByPosition (tautomerSkeleton,hPos);
+ atom.setImplicitHydrogenCount(atom.getImplicitHydrogenCount() + 1);
+ }
+ List<IAtom> atomsInNeedOfFix = new ArrayList<IAtom>();
+ for (IAtom atom : tautomerSkeleton.atoms()) {
+ if (atom.getValency() - atom.getFormalCharge() !=
+ atom.getImplicitHydrogenCount() + getConnectivity(atom, tautomerSkeleton))
+ atomsInNeedOfFix.add(atom);
+ }
+ List<Integer> dblBondPositions =
+ tryDoubleBondCombinations(tautomerSkeleton, 0, 0, doubleBondCount, atomsInNeedOfFix);
+ if (dblBondPositions != null) {
+ //Found a valid double bond combination for this mobile hydrogen configuration..
+ solutions.push(dblBondPositions);
+ solutions.push(tautomerSkeleton);
+ }
+ }
+ LOGGER.debug("#possible solutions : ",solutions.size());
+ if (solutions.size() == 0) {
+ LOGGER.error("Could not generate any tautomers for the input. Is input in Kekule form? ");
+ tautomers.add(inputMolecule);
+ } else {
+
+ while (solutions.size() != 0) {
+ IAtomContainer tautomerSkeleton = (IAtomContainer)solutions.pop();
+ List<Integer> dblBondPositions = (List<Integer>)solutions.pop();
+ IAtomContainer tautomer = (IAtomContainer)inputMolecule.clone();
+ for (IAtom skAtom1 : tautomerSkeleton.atoms()) {
+ for (IAtom atom1 :
+ tautomer.atoms()) {
+ if (atom1.getID().equals(skAtom1.getID())) {
+ atom1.setImplicitHydrogenCount(skAtom1.getImplicitHydrogenCount());
+ for (int bondIdx = 0; bondIdx < tautomerSkeleton.getBondCount(); bondIdx++) {
+ IBond skBond = tautomerSkeleton.getBond(bondIdx);
+ if (skBond.contains(skAtom1)) {
+ IAtom skAtom2 = skBond.getConnectedAtom(skAtom1);
+ for (IAtom atom2 : tautomer.atoms()) {
+ if (atom2.getID().equals(skAtom2.getID())) {
+ IBond tautBond = tautomer.getBond(atom1, atom2);
+ if (dblBondPositions.contains(bondIdx))
+ tautBond.setOrder(IBond.Order.DOUBLE);
+ else
+ tautBond.setOrder(IBond.Order.SINGLE);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ for (IAtom atom : tautomer.atoms()) {
+ atom.setFlag(CDKConstants.ISAROMATIC, false);
+ atom.setValency(null);
+ }
+ for (IBond bond : tautomer.bonds())
+ bond.setFlag(CDKConstants.ISAROMATIC, false);
+ tautomers.add(tautomer);
+ }
+ }
+ LOGGER.debug("# initial tautomers generated : ",tautomers.size());
+ return tautomers;
+ }
+
+ /**
+ * Removes duplicates from a molecule set. Uses SMSD to detect identical molecules.
+ * An example of pruning can be a case where double bonds are placed in different positions in
+ * an aromatic (Kekule) ring, which all amounts to one same aromatic ring.
+ *
+ * @param tautomers molecule set of tautomers with possible duplicates
+ * @return tautomers same set with duplicates removed
+ * @throws CDKException
+ */
+ private List<IAtomContainer> removeDuplicates(List<IAtomContainer> tautomers) throws CDKException {
+ List<IAtomContainer> unique = new ArrayList<IAtomContainer>();
+ Isomorphism isomorphism = new Isomorphism(Algorithm.DEFAULT.TurboSubStructure, true);
+ BitSet removed = new BitSet(tautomers.size());
+ for (int idx1 = 0; idx1 < tautomers.size(); idx1++) {
+ if (removed.get(idx1)) {
+ continue;
+ }
+ IAtomContainer tautomer1 = tautomers.get(idx1);
+ for (int idx2 = idx1 + 1; idx2 < tautomers.size(); idx2++) {
+ if (removed.get(idx2)) {
+ continue;
+ }
+ IAtomContainer tautomer2 = tautomers.get(idx2);
+ isomorphism.init(tautomer1, tautomer2, false, false);
+ isomorphism.setChemFilters(true, true, true);
+ if (isomorphism.isSubgraph()) {
+ removed.set(idx2);
+ }
+ }
+ unique.add(tautomer1);
+ }
+ LOGGER.debug("# tautomers after clean up : ",tautomers.size());
+ return unique;
+ }
+
+
+ /**
+ * Makes combinations recursively of all possible mobile Hydrogen positions.
+ * @param taken positions taken by hydrogen
+ * @param combinations combinations made so far
+ * @param skeleton container to work on
+ * @param totalMobHydrCount
+ * @param mobHydrAttachPositions
+ */
+ private void combineHydrogenPositions( List<Integer> taken
+ ,List<List<Integer>> combinations
+ ,IAtomContainer skeleton
+ ,int totalMobHydrCount
+ ,List<Integer> mobHydrAttachPositions) {
+ if (taken.size() != totalMobHydrCount) {
+ for (int i = 0; i < mobHydrAttachPositions.size(); i++) {
+ int pos = mobHydrAttachPositions.get(i);
+ IAtom atom = findAtomByPosition (skeleton,pos);
+ int conn = getConnectivity(atom, skeleton);
+ int hCnt=0;
+ for (int t : taken)
+ if (t==pos)
+ hCnt++;
+ if (atom.getValency() - atom.getFormalCharge()>(hCnt+conn)) {
+ taken.add(pos);
+ combineHydrogenPositions(taken, combinations, skeleton,totalMobHydrCount,mobHydrAttachPositions);
+ taken.remove(taken.size() - 1);
+ }
+ }
+ } else {
+ List<Integer> addList = new ArrayList<Integer>(taken.size());
+ addList.addAll(taken);
+ Collections.sort(addList);
+ if (!combinations.contains(addList)) {
+ combinations.add(addList);
+ }
+ }
+ }
+
+
+ /**
+ * Helper method that locates an atom based on its InChi atom table
+ * position, which has been set as ID.
+ * @param container input container
+ * @param position InChI atom table position
+ * @return atom on the position
+ */
+ private IAtom findAtomByPosition (IAtomContainer container, int position) {
+ String pos = String.valueOf(position);
+ for (IAtom atom : container.atoms()) {
+ if (atom.getID().equals(pos))
+ return atom;
+ }
+ return null;
+ }
+
+
+ /**
+ * Tries double bond combinations for a certain input container of which the double bonds have been stripped
+ * around the mobile hydrogen positions. Recursive.
+ *
+ * @param container
+ * @param dblBondsAdded counts double bonds added so far
+ * @param bondOffSet offset for next double bond position to consider
+ * @param doubleBondMax maximum number of double bonds to add
+ * @param atomsInNeedOfFix atoms that require more bonds
+ * @return a list of double bond positions (index) that make a valid combination, null if none found
+ */
+ private List<Integer> tryDoubleBondCombinations(IAtomContainer container, int dblBondsAdded, int bondOffSet,
+ int doubleBondMax, List<IAtom> atomsInNeedOfFix) {
+
+ int offSet = bondOffSet;
+ List<Integer> dblBondPositions = null;
+
+ while (offSet < container.getBondCount() && dblBondPositions == null) {
+ IBond bond = container.getBond(offSet);
+ if (atomsInNeedOfFix.contains(bond.getAtom(0)) && atomsInNeedOfFix.contains(bond.getAtom(1))) {
+ bond.setOrder(IBond.Order.DOUBLE);
+ dblBondsAdded = dblBondsAdded + 1;
+ if (dblBondsAdded == doubleBondMax) {
+ boolean validDoubleBondConfig = true;
+ CHECK:
+ for (IAtom atom : container.atoms()) {
+ if (atom.getValency() != atom.getImplicitHydrogenCount() + getConnectivity(atom, container)) {
+ validDoubleBondConfig = false;
+ break CHECK;
+ }
+ }
+ if (validDoubleBondConfig) {
+ dblBondPositions = new ArrayList<Integer>();
+ for (int idx = 0; idx < container.getBondCount(); idx++) {
+ if (container.getBond(idx).getOrder().equals(IBond.Order.DOUBLE))
+ dblBondPositions.add(idx);
+ }
+ return dblBondPositions;
+ }
+ } else {
+ dblBondPositions =
+ tryDoubleBondCombinations(container, dblBondsAdded, offSet + 1, doubleBondMax, atomsInNeedOfFix);
+ }
+
+ bond.setOrder(IBond.Order.SINGLE);
+ dblBondsAdded = dblBondsAdded - 1;
+ }
+ offSet++;
+ }
+ return dblBondPositions;
+ }
+
+
+ /**
+ * Sums the number of bonds (counting order) an atom is hooked up with.
+ * @param atom
+ * @param container
+ * @return
+ */
+ private int getConnectivity(IAtom atom, IAtomContainer container) {
+ int connectivity = 0;
+ for (IBond bond : container.bonds()) {
+ if (bond.contains(atom)) {
+ switch (bond.getOrder()) {
+ case SINGLE:
+ connectivity++;
+ break;
+ case DOUBLE:
+ connectivity += 2;
+ break;
+ case TRIPLE:
+ connectivity += 3;
+ break;
+ case QUADRUPLE:
+ connectivity += 4;
+ break;
+ default:
+ connectivity += 10;
+ }
+ }
+ }
+ return connectivity;
+ }
+}
View
31 src/test/data/hin/arorings.hin
@@ -0,0 +1,31 @@
+forcefield mm+
+sys 0 0 1
+view 40 0.1471 55 15 0.5586844 -0.7573253 0.3381274 0.8112321 0.583803 -0.03280994 -0.172552 0.2926302 0.9405283 -1.5498 -0.69331 -55.277
+seed 0
+mol 1
+atom 1 - C CA - -0.1921654 0.5444375 -0.480369 0.1121711 3 3 a 2 a 14 s
+atom 2 - C CA - -0.07865381 1.48883 -1.507176 0.1121711 3 5 a 1 a 15 s
+atom 3 - C CA - 0.1260283 0.9869497 0.8709679 0.1121711 3 1 a 4 a 7 s
+atom 4 - C CA - -0.1945596 2.357387 1.141245 0.1121711 3 3 a 6 a 20 s
+atom 5 - C CA - -0.1604924 2.854465 -1.227169 0.1121711 3 2 a 6 a 21 s
+atom 6 - C CA - -0.08668089 3.281385 0.09564244 0.1121711 3 5 a 4 a 16 s
+atom 7 - O O2 - -0.1584311 -0.06161446 1.767233 0.1121711 2 3 s 8 s
+atom 8 - C CA - 0.09127665 -0.009773561 3.152164 0.1121711 3 13 a 7 s 9 a
+atom 9 - C CA - -0.1865864 1.073688 4.026796 0.1121711 3 10 a 22 s 8 a
+atom 10 - C CA - -0.1031656 0.8394372 5.407645 0.1121711 3 9 a 11 a 17 s
+atom 11 - C CA - -0.153739 -0.452265 5.91707 0.1121711 3 10 a 12 a 18 s
+atom 12 - C CA - -0.1025772 -1.539669 5.037201 0.1121711 3 11 a 13 a 19 s
+atom 13 - C CA - -0.1454592 -1.331929 3.667263 0.1121711 3 12 a 8 a 23 s
+atom 14 - Br BR - 0.07038784 -1.265702 -0.9827618 0.1121711 1 1 s
+atom 15 - H H - 0.149111 1.15467 -2.557919 0.1121711 1 2 s
+atom 16 - H H - 0.1373875 4.357067 0.3297046 0.1121711 1 6 s
+atom 17 - H H - 0.1337775 1.701587 6.091895 0.1121711 1 10 s
+atom 18 - H H - 0.1358719 -0.6226702 7.002957 0.1121711 1 11 s
+atom 19 - H H - 0.1372966 -2.566783 5.432249 0.1121711 1 12 s
+atom 20 - H H - 0.145665 2.75555 2.159567 0.1121711 1 4 s
+atom 21 - H H - 0.1408581 3.583701 -2.04989 0.1121711 1 5 s
+atom 22 - H H - 0.1395921 2.117928 3.702678 0.1121711 1 9 s
+atom 23 - H H - 0.1552575 -2.176271 2.961693 0.1121711 1 13 s
+endmol 1
+aromaticring 6 1 1 1 3 1 4 1 6 1 5 1 2
+aromaticring 6 1 8 1 13 1 12 1 11 1 10 1 9
View
19 src/test/org/openscience/cdk/atomtype/CDKAtomTypeMatcherSMILESTest.java
@@ -108,7 +108,24 @@
Assert.assertNotNull(type.getAtomTypeName());
}
}
-
+
+ /**
+ * @cdk.bug 3093644
+ */
+ @Test public void testBug3093644() throws Exception {
+ String smiles1 =
+ "[H]C5(CCC(N)=O)(C=1N=C(C=C4N=C(C(C)=C3[N-]C(C)(C2N=C(C=1(C))C(C)" +
+ "(CCC(=O)NCC(C)O)C2([H])(CC(N)=O))C(C)(CC(N)=O)C3([H])(CCC(N)=O))" +
+ "C(C)(CC(N)=O)C4([H])(CCC(N)=O))C5(C)(C)).[H][C-]([H])C3([H])(OC([H])" +
+ "(N2C=NC=1C(N)=NC=NC=12)C([H])(O)C3([H])(O)).[Co+3]";
+
+ IMolecule mol1 = smilesParser.parseSmiles(smiles1);
+ IAtomType[] types1 = atomTypeMatcher.findMatchingAtomType(mol1);
+ for (IAtomType type : types1) {
+ Assert.assertNotNull(type.getAtomTypeName());
+ }
+ }
+
@Test public void testPlatinum4() throws Exception {
String smiles1 = "Cl[Pt]1(Cl)(Cl)(Cl)NC2CCCCC2N1";
View
52 src/test/org/openscience/cdk/atomtype/CDKAtomTypeMatcherTest.java
@@ -1,7 +1,5 @@
-/* $Revision$ $Author$ $Date$
- *
- * Copyright (C) 2007 Egon Willighagen <egonw@users.sf.net>
- * 2007 Rajarshi Guha
+/* Copyright (C) 2007-2011 Egon Willighagen <egonw@users.sf.net>
+ * 2007 Rajarshi Guha
*
* Contact: cdk-devel@lists.sourceforge.net
*
@@ -35,17 +33,21 @@
import org.openscience.cdk.PseudoAtom;
import org.openscience.cdk.Ring;
import org.openscience.cdk.config.AtomTypeFactory;
+import org.openscience.cdk.config.Elements;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomType;
-import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
-import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.interfaces.IAtomType.Hybridization;
+import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IBond.Order;
+import org.openscience.cdk.interfaces.IMolecule;
+import org.openscience.cdk.nonotify.NNAtom;
+import org.openscience.cdk.nonotify.NNAtomType;
import org.openscience.cdk.nonotify.NoNotificationChemObjectBuilder;
import org.openscience.cdk.templates.MoleculeFactory;
import org.openscience.cdk.tools.periodictable.PeriodicTable;
+import org.openscience.cdk.tools.manipulator.AtomTypeManipulator;
/**
* This class tests the matching of atom types defined in the
@@ -1619,6 +1621,13 @@ public void testTetrahydropyran() throws Exception {
assertAtomTypes(testedAtomTypes, expectedTypes, mol);
mol = new Molecule();
+ atom = new Atom("Co");
+ atom.setFormalCharge(+3);
+ mol.addAtom(atom);
+ expectedTypes = new String[]{"Co.3plus"};
+ assertAtomTypes(testedAtomTypes, expectedTypes, mol);
+
+ mol = new Molecule();
atom = new Atom("Cu");
atom.setFormalCharge(+2);
mol.addAtom(atom);
@@ -3347,6 +3356,37 @@ public void testNOxide() throws Exception {
assertAtomTypes(testedAtomTypes, expectedTypes, mol);
}
+ /**
+ * @cdk.bug 3190151
+ */
+ public void testP() throws Exception {
+ IAtom atomP = new NNAtom("P");
+ IAtomContainer mol = new Molecule();
+ mol.addAtom(atomP);
+ String[] expectedTypes = {"P.ine"};
+
+ assertAtomTypes(testedAtomTypes, expectedTypes, mol);
+ }
+
+ /**
+ * @cdk.bug 3190151
+ */
+ public void testPine() throws Exception {
+ IAtom atomP = new NNAtom(Elements.PHOSPHORUS);
+ IAtomType atomTypeP = new NNAtomType(Elements.PHOSPHORUS);
+ AtomTypeManipulator.configure(atomP, atomTypeP);
+
+ IAtomContainer ac = atomP.getBuilder().newInstance(IAtomContainer.class);
+ ac.addAtom(atomP);
+ IAtomType type = null;
+ for (IAtom atom : ac.atoms()) {
+ type = CDKAtomTypeMatcher.getInstance(
+ ac.getBuilder()
+ ).findMatchingAtomType(ac, atom);
+ Assert.assertNotNull(type);
+ }
+ }
+
@Test public void countTestedAtomTypes() {
super.countTestedAtomTypes(testedAtomTypes);
}
View
48 src/test/org/openscience/cdk/coverage/TautomerCoverageTest.java
@@ -0,0 +1,48 @@
+/* Copyright (C) 2011 Egon Willighagen <egonw@users.sf.net>
+ *
+ * Contact: cdk-devel@lists.sourceforge.net
+ *
+ * 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 org.openscience.cdk.coverage;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * TestSuite that tests whether all public methods in the <code>tautomer</code>
+ * module are tested. Unlike Emma, it does not test that all code is
+ * tested, just all methods.
+ *
+ * @cdk.module test-tautomer
+ */
+public class TautomerCoverageTest extends CoverageAnnotationTest {
+
+ private final static String CLASS_LIST = "tautomer.javafiles";
+
+ @BeforeClass public static void setUp() throws Exception {
+ loadClassList(CLASS_LIST, TautomerCoverageTest.class.getClassLoader());
+ }
+
+ @Test public void testCoverage() {
+ Assert.assertTrue(super.runCoverageTest());
+ }
+
+}
View
2 src/test/org/openscience/cdk/formula/MolecularFormulaRangeTest.java
@@ -275,6 +275,7 @@ public void testContains_IIsotope() {
MolecularFormulaRange mfRange = new MolecularFormulaRange();
IIsotope carb = builder.newInstance(IIsotope.class,"C");
+ IIsotope cl = builder.newInstance(IIsotope.class, "Cl");
IIsotope h1 = builder.newInstance(IIsotope.class,"H");
IIsotope h2 = builder.newInstance(IIsotope.class,"H");
h2.setExactMass(2.0004);
@@ -283,6 +284,7 @@ public void testContains_IIsotope() {
mfRange.addIsotope( h1 , 0, 10);
Assert.assertTrue(mfRange.contains(carb));
+ Assert.assertFalse(mfRange.contains(cl));
Assert.assertTrue(mfRange.contains(h1));
Assert.assertFalse(mfRange.contains(h2));
}
View
44 src/test/org/openscience/cdk/io/HINReaderTest.java
@@ -30,8 +30,10 @@
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.ChemFile;
import org.openscience.cdk.ChemObject;
+import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IChemFile;
import org.openscience.cdk.tools.ILoggingTool;
@@ -133,7 +135,7 @@
String filename = "data/hin/connectivity1.hin";
InputStream ins = this.getClass().getClassLoader().getResourceAsStream(filename);
ISimpleChemObjectReader reader = new HINReader(ins);
- IChemFile content = (IChemFile) reader.read(new ChemFile());
+ IChemFile content = reader.read(new ChemFile());
List<IAtomContainer> cList = ChemFileManipulator.getAllAtomContainers(content);
IAtomContainer ac = cList.get(0);
Assert.assertEquals(57, ac.getAtomCount());
@@ -148,9 +150,45 @@
String filename = "data/hin/bug2984581.hin";
InputStream ins = this.getClass().getClassLoader().getResourceAsStream(filename);
ISimpleChemObjectReader reader = new HINReader(ins);
- IChemFile content = (IChemFile) reader.read(new ChemFile());
+ IChemFile content = reader.read(new ChemFile());
List<IAtomContainer> cList = ChemFileManipulator.getAllAtomContainers(content);
Assert.assertEquals(1, cList.size());
- IAtomContainer ac = cList.get(0);
+ }
+
+ /**
+ * @cdk.bug 2984581
+ * @throws Exception
+ */
+ @Test
+ public void testReadAromaticRingsKeyword() throws Exception {
+ String filename = "data/hin/arorings.hin";
+ InputStream ins = this.getClass().getClassLoader().getResourceAsStream(filename);
+ ISimpleChemObjectReader reader = new HINReader(ins);
+ IChemFile content = reader.read(new ChemFile());
+ List<IAtomContainer> cList = ChemFileManipulator.getAllAtomContainers(content);
+ Assert.assertEquals(1, cList.size());
+
+ IAtomContainer mol = cList.get(0);
+ Assert.assertTrue(mol.getAtom(0).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(2).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(3).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(5).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(4).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(1).getFlag(CDKConstants.ISAROMATIC));
+
+ Assert.assertTrue(mol.getAtom(7).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(12).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(11).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(10).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(9).getFlag(CDKConstants.ISAROMATIC));
+ Assert.assertTrue(mol.getAtom(8).getFlag(CDKConstants.ISAROMATIC));
+
+ // make sure that only the phenyl C's were marked as aromatic
+ for (IAtom atom : mol.atoms()) {
+ if (atom.getSymbol().equals("C"))
+ Assert.assertTrue(atom.getSymbol()+" (index "+mol.getAtomNumber(atom)+") was wrongly marked as aromatic",
+ atom.getFlag(CDKConstants.ISAROMATIC));
+ }
+
}
}
View
45 src/test/org/openscience/cdk/io/cml/CDKRoundTripTest.java
@@ -34,8 +34,9 @@
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomType;
import org.openscience.cdk.interfaces.IBond;
-import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
+import org.openscience.cdk.interfaces.IMolecule;
+import org.openscience.cdk.libio.cml.Convertor;
import org.openscience.cdk.nonotify.NoNotificationChemObjectBuilder;
import org.openscience.cdk.tools.diff.AtomDiff;
@@ -46,11 +47,13 @@
private static IChemObjectBuilder builder = NoNotificationChemObjectBuilder.getInstance();
+ private static Convertor convertor = new Convertor(false, "");
+
@Test public void testIElement_Symbol() throws Exception {
IMolecule mol = builder.newInstance(IMolecule.class);
IAtom atom = builder.newInstance(IAtom.class,"C");
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -60,7 +63,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setAtomicNumber(6);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -70,7 +73,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setNaturalAbundance(99.);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -80,7 +83,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setExactMass(12.);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -90,7 +93,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setMassNumber(13);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -100,7 +103,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setAtomTypeName("C.sp3");
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -110,7 +113,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setMaxBondOrder(IBond.Order.TRIPLE);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -120,7 +123,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setBondOrderSum(4.);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -130,7 +133,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setFormalCharge(+1);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -140,7 +143,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setFormalNeighbourCount(4);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -150,7 +153,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setHybridization(IAtomType.Hybridization.SP3);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -160,7 +163,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setCovalentRadius(1.5d);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -170,7 +173,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setValency(4);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -180,7 +183,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setCharge(0.3);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -190,7 +193,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setImplicitHydrogenCount(4);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -200,7 +203,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setPoint2d(new Point2d(1.0, 2.0));
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -210,7 +213,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setPoint3d(new Point3d(1.0, 2.0, 3.0));
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -220,7 +223,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setFractionalPoint3d(new Point3d(1.0, 2.0, 3.0));
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -232,7 +235,7 @@
atom.setPoint3d(new Point3d(-1.0, -2.0, -3.0));
atom.setFractionalPoint3d(new Point3d(1.0, 2.0, 3.0));
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
@@ -242,7 +245,7 @@
IAtom atom = builder.newInstance(IAtom.class,"C");
atom.setStereoParity(-1);
mol.addAtom(atom);
- IMolecule copy = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule copy = CMLRoundTripTool.roundTripMolecule(convertor, mol);
String difference = AtomDiff.diff(atom, copy.getAtom(0));;
Assert.assertEquals("Found non-zero diff: " + difference, 0, difference.length());
}
View
83 src/test/org/openscience/cdk/io/cml/CMLRoundTripTest.java
@@ -31,6 +31,7 @@
import org.junit.Assert;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import org.openscience.cdk.Atom;
import org.openscience.cdk.Bond;
@@ -87,7 +88,7 @@
Atom atom = new Atom("N");
mol.addAtom(atom);
- IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(convertor, mol);
Assert.assertEquals(1, roundTrippedMol.getAtomCount());
IAtom roundTrippedAtom = roundTrippedMol.getAtom(0);
@@ -100,7 +101,7 @@
atom.setID("N1");
mol.addAtom(atom);
- IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(convertor, mol);
Assert.assertEquals(1, roundTrippedMol.getAtomCount());
IAtom roundTrippedAtom = roundTrippedMol.getAtom(0);
@@ -114,7 +115,7 @@
atom.setPoint2d(p2d);
mol.addAtom(atom);
- IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(convertor, mol);
Assert.assertEquals(1, roundTrippedMol.getAtomCount());
IAtom roundTrippedAtom = roundTrippedMol.getAtom(0);
@@ -128,7 +129,7 @@
atom.setPoint3d(p3d);
mol.addAtom(atom);
- IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(convertor, mol);
Assert.assertEquals(1, roundTrippedMol.getAtomCount());
IAtom roundTrippedAtom = roundTrippedMol.getAtom(0);
@@ -144,7 +145,7 @@
atom.setPoint3d(p3d);
mol.addAtom(atom);
- IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(convertor, mol);
Assert.assertEquals(1, roundTrippedMol.getAtomCount());
IAtom roundTrippedAtom = roundTrippedMol.getAtom(0);
@@ -159,7 +160,7 @@
atom.setFractionalPoint3d(p3d);
mol.addAtom(atom);
- IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(mol);
+ IMolecule roundTrippedMol = CMLRoundTripTool.roundTripMolecule(convertor, mol);
Assert.assertEquals(1, roundTrippedMol.getAtomCount());
IAtom roundTrippedAtom = roundTrippedMol.getAtom(0);
@@ -172,7 +173,7 @@
atom.setLabel("Glu55");
mol.addAtom(atom);