Skip to content

Commit

Permalink
Unified reaction SMILES API with the molecule and make it so reaction…
Browse files Browse the repository at this point in the history
…s can be canonicalised.
  • Loading branch information
johnmay committed Aug 16, 2016
1 parent c2b88b4 commit fc5e945
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.openscience.cdk.interfaces.ISingleElectron;
import org.openscience.cdk.sgroup.Sgroup;
import org.openscience.cdk.sgroup.SgroupKey;
import org.openscience.cdk.tools.manipulator.ReactionManipulator;
import uk.ac.ebi.beam.Functions;
import uk.ac.ebi.beam.Graph;

Expand Down Expand Up @@ -431,39 +432,62 @@ public String create(IAtomContainer molecule, int[] order) throws CDKException {
}
}

@Deprecated
public String createReactionSMILES(IReaction reaction) throws CDKException {
return create(reaction);
}

public String create(IReaction reaction) throws CDKException {
return create(reaction, new int[ReactionManipulator.getAtomCount(reaction)]);
}

/**
* Generate a SMILES for the given <code>Reaction</code>.
*
* @param reaction the reaction in question
* @return the SMILES representation of the reaction
* @throws org.openscience.cdk.exception.CDKException if there is an error during SMILES generation
*/
public String createReactionSMILES(IReaction reaction) throws CDKException {
StringBuffer reactionSMILES = new StringBuffer();
public String create(IReaction reaction, int[] ordering) throws CDKException {

IAtomContainerSet reactants = reaction.getReactants();
IAtomContainerSet agents = reaction.getAgents();
IAtomContainerSet products = reaction.getProducts();

IAtomContainer reactantPart = reaction.getBuilder().newInstance(IAtomContainer.class);
IAtomContainer agentPart = reaction.getBuilder().newInstance(IAtomContainer.class);
IAtomContainer productPart = reaction.getBuilder().newInstance(IAtomContainer.class);

for (int i = 0; i < reactants.getAtomContainerCount(); i++) {
reactionSMILES.append(create(reactants.getAtomContainer(i)));
if (i + 1 < reactants.getAtomContainerCount()) {
reactionSMILES.append('.');
}
reactantPart.add(reactants.getAtomContainer(i));
}
reactionSMILES.append('>');
IAtomContainerSet agents = reaction.getAgents();
for (int i = 0; i < agents.getAtomContainerCount(); i++) {
reactionSMILES.append(create(agents.getAtomContainer(i)));
if (i + 1 < agents.getAtomContainerCount()) {
reactionSMILES.append('.');
}
agentPart.add(agents.getAtomContainer(i));
}
reactionSMILES.append('>');
IAtomContainerSet products = reaction.getProducts();
for (int i = 0; i < products.getAtomContainerCount(); i++) {
reactionSMILES.append(create(products.getAtomContainer(i)));
if (i + 1 < products.getAtomContainerCount()) {
reactionSMILES.append('.');
}
productPart.add(products.getAtomContainer(i));
}
return reactionSMILES.toString();

int[] reactantOrder = new int[reactantPart.getAtomCount()];
int[] agentOrder = new int[agentPart.getAtomCount()];
int[] productOrder = new int[productPart.getAtomCount()];

final int expectedSize = reactantOrder.length + agentOrder.length + productOrder.length;
if (expectedSize != ordering.length) {
throw new CDKException("Output ordering array does not have correct amount of space: " + ordering.length +
" expected: " + expectedSize);
}

String smi = create(reactantPart, reactantOrder) + ">" +
create(agentPart, agentOrder) + ">" +
create(productPart, productOrder);

// copy ordering back to unified array
System.arraycopy(reactantOrder, 0, ordering, 0, reactantOrder.length);
System.arraycopy(agentOrder, 0, ordering, reactantOrder.length, agentOrder.length);
System.arraycopy(productOrder, 0, ordering, reactantOrder.length + agentOrder.length, productOrder.length);

return smi;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import org.openscience.cdk.interfaces.IChemObjectBuilder;
import org.openscience.cdk.interfaces.IChemSequence;
import org.openscience.cdk.interfaces.IDoubleBondStereochemistry;
import org.openscience.cdk.interfaces.IReaction;
import org.openscience.cdk.interfaces.IStereoElement;
import org.openscience.cdk.interfaces.ITetrahedralChirality;
import org.openscience.cdk.io.CMLReader;
Expand Down Expand Up @@ -674,7 +675,7 @@ public void testReactionSMILES() throws Exception {
gold.getAtom(0).setImplicitHydrogenCount(0);

SmilesGenerator sg = new SmilesGenerator();
String smiles = sg.createReactionSMILES(reaction);
String smiles = sg.create(reaction);
//logger.debug("Generated SMILES: " + smiles);
Assert.assertEquals("C>*>[Au]", smiles);
}
Expand Down Expand Up @@ -1218,6 +1219,16 @@ public void assignDbStereo() throws Exception {
Assert.assertEquals("C(\\N)=C/C=C/1\\N=C1", SmilesGenerator.isomeric().create(mol));
}

@Test public void canonicalReactions() throws Exception {
SmilesParser smipar = new SmilesParser(SilentChemObjectBuilder.getInstance());
IReaction r1 = smipar.parseReactionSmiles("CC(C)C1=CC=CC=C1.C(CC(=O)Cl)CCl>[Al+3].[Cl-].[Cl-].[Cl-].C(Cl)Cl>CC(C)C1=CC=C(C=C1)C(=O)CCCCl");
IReaction r2 = smipar.parseReactionSmiles("C(CC(=O)Cl)CCl.CC(C)C1=CC=CC=C1>[Al+3].[Cl-].[Cl-].[Cl-].C(Cl)Cl>CC(C)C1=CC=C(C=C1)C(=O)CCCCl");
IReaction r3 = smipar.parseReactionSmiles("CC(C)C1=CC=CC=C1.C(CC(=O)Cl)CCl>C(Cl)Cl.[Al+3].[Cl-].[Cl-].[Cl-]>CC(C)C1=CC=C(C=C1)C(=O)CCCCl");
SmilesGenerator smigen = new SmilesGenerator(SmiOpt.Canonical);
assertThat(smigen.create(r1), is(smigen.create(r2)));
assertThat(smigen.create(r2), is(smigen.create(r3)));
}

static ITetrahedralChirality anticlockwise(IAtomContainer container, int central, int a1, int a2, int a3, int a4) {
return new TetrahedralChirality(container.getAtom(central), new IAtom[]{container.getAtom(a1),
container.getAtom(a2), container.getAtom(a3), container.getAtom(a4)},
Expand Down

0 comments on commit fc5e945

Please sign in to comment.