diff --git a/tool/tautomer/src/main/java/org/openscience/cdk/tautomers/InChITautomerGenerator.java b/tool/tautomer/src/main/java/org/openscience/cdk/tautomers/InChITautomerGenerator.java
index 7ed022aa39..7f78366778 100644
--- a/tool/tautomer/src/main/java/org/openscience/cdk/tautomers/InChITautomerGenerator.java
+++ b/tool/tautomer/src/main/java/org/openscience/cdk/tautomers/InChITautomerGenerator.java
@@ -31,7 +31,6 @@
import org.openscience.cdk.graph.invariant.InChINumbersTools;
import org.openscience.cdk.inchi.InChIGenerator;
import org.openscience.cdk.inchi.InChIGeneratorFactory;
-import org.openscience.cdk.inchi.InChIToStructure;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomType;
@@ -56,12 +55,43 @@
* @cdk.module tautomer
* @cdk.githash
*/
-public class InChITautomerGenerator {
+public final class InChITautomerGenerator {
private final static ILoggingTool LOGGER = LoggingToolFactory.createLoggingTool(InChITautomerGenerator.class);
private static final SmilesGenerator CANSMI = new SmilesGenerator(SmiFlavor.Canonical);
+ /** Generate InChI with -KET (keto-enol tautomers) option. */
+ public static final int KETO_ENOL = 0x1;
+
+ /** Generate InChI with -15T (1,5-shift tautomers) option. */
+ public static final int ONE_FIVE_SHIFT = 0x2;
+
+ private final int flags;
+
+ /**
+ * Create a tautomer generator specifygin whether to enable, keto-enol (-KET) and 1,5-shifts (-15T).
+ *
+ *
{@code
+ * // enabled -KET option
+ * InChITautomerGenerator tautgen = new InChITautomerGenerator(InChITautomerGenerator.KETO_ENOL);
+ * // enabled both -KET and -15T
+ * InChITautomerGenerator tautgen = new InChITautomerGenerator(InChITautomerGenerator.KETO_ENOL | InChITautomerGenerator.ONE_FIVE_SHIFT);
+ * }
+ *
+ * @param flags the options
+ */
+ public InChITautomerGenerator(int flags) {
+ this.flags = flags;
+ }
+
+ /**
+ * Create a tautomer generator, keto-enol (-KET) and 1,5-shifts (-15T) are disabled.
+ */
+ public InChITautomerGenerator() {
+ this(0);
+ }
+
/**
* Public method to get tautomers for an input molecule, based on the InChI which will be calculated by JNI-InChI.
* @param mol molecule for which to generate tautomers
@@ -71,7 +101,13 @@ public class InChITautomerGenerator {
*/
public List getTautomers(IAtomContainer mol) throws CDKException, CloneNotSupportedException {
- InChIGenerator gen = InChIGeneratorFactory.getInstance().getInChIGenerator(mol, "");
+ String opt = "";
+ if ((flags & KETO_ENOL) != 0)
+ opt += " -KET";
+ if ((flags & ONE_FIVE_SHIFT) != 0)
+ opt += " -15T";
+
+ InChIGenerator gen = InChIGeneratorFactory.getInstance().getInChIGenerator(mol, opt);
String inchi = gen.getInchi();
String aux = gen.getAuxInfo();
@@ -84,6 +120,18 @@ public List getTautomers(IAtomContainer mol) throws CDKException
return getTautomers(mol, inchi, amap);
}
+ /**
+ * This method is slower than recalculating the InChI with {@link #getTautomers(IAtomContainer)} as the mapping
+ * between the two can be found more efficiently.
+ *
+ * @param mol
+ * @param inchi
+ * @return
+ * @throws CDKException
+ * @throws CloneNotSupportedException
+ * @deprecated use {@link #getTautomers(IAtomContainer)} directly
+ */
+ @Deprecated
public List getTautomers(IAtomContainer mol, String inchi) throws CDKException, CloneNotSupportedException {
return getTautomers(mol, inchi, null);
}
diff --git a/tool/tautomer/src/test/java/org/openscience/cdk/tautomers/InChITautomerGeneratorTest.java b/tool/tautomer/src/test/java/org/openscience/cdk/tautomers/InChITautomerGeneratorTest.java
index a31a594008..0733138167 100644
--- a/tool/tautomer/src/test/java/org/openscience/cdk/tautomers/InChITautomerGeneratorTest.java
+++ b/tool/tautomer/src/test/java/org/openscience/cdk/tautomers/InChITautomerGeneratorTest.java
@@ -71,6 +71,16 @@ private List unitTestWithInchiProvided(String smiles, String inc
return tautomers;
}
+ private List unitTestWithoutInchiProvided(String smiles, int flags, int tautCountExpected)
+ throws Exception {
+ IAtomContainer container = smilesParser.parseSmiles(smiles);
+ AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(container);
+ InChITautomerGenerator tautegen = new InChITautomerGenerator(flags);
+ List tautomers = tautegen.getTautomers(container);
+ Assert.assertEquals(tautCountExpected, tautomers.size());
+ return tautomers;
+ }
+
@Test
public void test1() throws Exception {
unitTestWithInchiProvided("NC1=CC(N)=NC(O)=N1", "InChI=1S/C4H6N4O/c5-2-1-3(6)8-4(9)7-2/h1H,(H5,5,6,7,8,9)", 5);
@@ -108,6 +118,37 @@ public void test6() throws Exception {
+ "h2-10,15H,1H3,(H2,11,20)(H,17,21,22)", 6);
}
+ @Test
+ public void test1_fast() throws Exception {
+ unitTestWithoutInchiProvided("NC1=CC(N)=NC(O)=N1", 0, 5);
+ }
+
+ @Test
+ public void test2_fast() throws Exception {
+ unitTestWithoutInchiProvided("CCCN1C2=C(NC=N2)C(=O)NC1=O", 0, 8);
+ }
+
+ @Test
+ public void test3_fast() throws Exception {
+ unitTestWithoutInchiProvided("CCNC(=N)NC", 0, 3);
+ }
+
+ @Test
+ public void test4_fast() throws Exception {
+ unitTestWithoutInchiProvided("O=C1NC=CC(=O)N1", 0, 6);
+ }
+
+ @Test
+ public void test5_fast() throws Exception {
+ unitTestWithoutInchiProvided("CCN1CCOC2=CC(NC3=NCCN3)=CC=C12", 0, 2);
+ }
+
+ @Test
+ public void test6_fast() throws Exception {
+ //Warfarin: not you need to create the InChI with option KET to get the ketone/hydroxyl tautomerism
+ unitTestWithoutInchiProvided("CC(=O)CC(C1=CC=CC=C1)C1=C(O)C2=C(OC1=O)C=CC=C2", InChITautomerGenerator.KETO_ENOL, 6);
+ }
+
@Test(expected = CDKException.class)
// bail out on dots in formula
public void testFail1() throws Exception {