diff --git a/base/core/src/main/java/org/openscience/cdk/CDKConstants.java b/base/core/src/main/java/org/openscience/cdk/CDKConstants.java index 16a7a451cd1..7716712fb6c 100644 --- a/base/core/src/main/java/org/openscience/cdk/CDKConstants.java +++ b/base/core/src/main/java/org/openscience/cdk/CDKConstants.java @@ -285,6 +285,22 @@ public class CDKConstants { */ public static final String RELEVANT_RINGS = "cdk:RelevantRings"; + /** + * Property used for reactions when converted to/from molecules. It defines what role and atom + * has an a reaction. + * + * Used in. ReactionManipulator.toMolecule and ReactionManipulator.toReaction. + */ + public static final String REACTION_ROLE = "cdk:ReactionRole"; + + /** + * Property used for reactions when converted to/from molecules. It defines fragment grouping, for example + * when handling ionic components. + * + * Used in. ReactionManipulator.toMolecule and ReactionManipulator.toReaction. + */ + public static final String REACTION_GROUP = "cdk:ReactionGroup"; + /* ************************************** * Some predefined property names for * Atoms * * ************************************** diff --git a/base/standard/src/main/java/org/openscience/cdk/tools/manipulator/ReactionManipulator.java b/base/standard/src/main/java/org/openscience/cdk/tools/manipulator/ReactionManipulator.java index 5461331a49b..afaa6c20b3d 100644 --- a/base/standard/src/main/java/org/openscience/cdk/tools/manipulator/ReactionManipulator.java +++ b/base/standard/src/main/java/org/openscience/cdk/tools/manipulator/ReactionManipulator.java @@ -22,17 +22,26 @@ * */ package org.openscience.cdk.tools.manipulator; +import org.openscience.cdk.CDKConstants; +import org.openscience.cdk.ReactionRole; import org.openscience.cdk.interfaces.IAtom; import org.openscience.cdk.interfaces.IAtomContainer; import org.openscience.cdk.interfaces.IAtomContainerSet; import org.openscience.cdk.interfaces.IBond; import org.openscience.cdk.interfaces.IChemObject; +import org.openscience.cdk.interfaces.IChemObjectBuilder; +import org.openscience.cdk.interfaces.IDoubleBondStereochemistry; import org.openscience.cdk.interfaces.IElectronContainer; import org.openscience.cdk.interfaces.IMapping; import org.openscience.cdk.interfaces.IReaction; +import org.openscience.cdk.interfaces.IStereoElement; +import org.openscience.cdk.interfaces.ITetrahedralChirality; +import org.openscience.cdk.stereo.ExtendedTetrahedral; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @cdk.module standard @@ -257,4 +266,135 @@ public static IChemObject getMappedChemObject(IReaction reaction, IChemObject ch return null; } + /** + * Assigns a reaction role and group id to all atoms in a molecule. + * + * @param mol molecule + * @param role role to assign + * @param grpId group id + */ + private static void assignRoleAndGrp(IAtomContainer mol, ReactionRole role, int grpId) { + for (IAtom atom : mol.atoms()) { + atom.setProperty(CDKConstants.REACTION_ROLE, role); + atom.setProperty(CDKConstants.REACTION_GROUP, grpId); + } + } + + /** + *
Converts a reaction to an 'inlined' reaction stored as a molecule. All + * reactants, agents, products are added to the molecule as disconnected + * components with atoms flagged as to their role {@link ReactionRole} and + * component group.
+ *+ * The inlined reaction, stored in a molecule can be converted back to an explicit + * reaction with {@link #toReaction}. Data stored on the individual components (e.g. + * titles is lost in the conversion). + *
+ * + * @param rxn reaction to convert + * @return inlined reaction stored in a molecule + * @see #toReaction + */ + public static IAtomContainer toMolecule(IReaction rxn) { + if (rxn == null) + throw new IllegalArgumentException("Null reaction provided"); + final IChemObjectBuilder bldr = rxn.getBuilder(); + final IAtomContainer mol = bldr.newInstance(IAtomContainer.class); + mol.setProperties(rxn.getProperties()); + mol.setID(rxn.getID()); + int grpId = 0; + for (IAtomContainer comp : rxn.getReactants().atomContainers()) { + assignRoleAndGrp(comp, ReactionRole.Reactant, ++grpId); + mol.add(comp); + } + for (IAtomContainer comp : rxn.getAgents().atomContainers()) { + assignRoleAndGrp(comp, ReactionRole.Agent, ++grpId); + mol.add(comp); + } + for (IAtomContainer comp : rxn.getProducts().atomContainers()) { + assignRoleAndGrp(comp, ReactionRole.Product, ++grpId); + mol.add(comp); + } + return mol; + } + + /** + *Converts an 'inlined' reaction stored in a molecule back to a reaction.
+ * + * @param mol molecule to convert + * @return reaction + * @see #toMolecule(IReaction) + */ + public static IReaction toReaction(IAtomContainer mol) { + if (mol == null) + throw new IllegalArgumentException("Null molecule provided"); + final IChemObjectBuilder bldr = mol.getBuilder(); + final IReaction rxn = bldr.newInstance(IReaction.class); + rxn.setProperties(mol.getProperties()); + rxn.setID(mol.getID()); + + Map