1 package org.openscience.cdk.smsd.labelling;
2 
3 import org.openscience.cdk.CDKConstants;
4 import org.openscience.cdk.DefaultChemObjectBuilder;
5 import org.openscience.cdk.Mapping;
6 import org.openscience.cdk.Reaction;
7 import org.openscience.cdk.interfaces.IAtom;
8 import org.openscience.cdk.interfaces.IAtomContainer;
9 import org.openscience.cdk.interfaces.IAtomContainerSet;
10 import org.openscience.cdk.interfaces.IChemObject;
11 import org.openscience.cdk.interfaces.IMapping;
12 import org.openscience.cdk.interfaces.IReaction;
13 import org.openscience.cdk.tools.manipulator.ReactionManipulator;
14 
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.Comparator;
18 import java.util.HashMap;
19 import java.util.Hashtable;
20 import java.util.List;
21 import java.util.Map;
22 
23 /**
24  * @cdk.module smsd
25  * @cdk.githash
26  * @deprecated This class is part of SMSD and either duplicates functionality elsewhere in the CDK or provides public
27  *             access to internal implementation details. SMSD has been deprecated from the CDK with a newer, more recent
28  *             version of SMSD is available at <a href="http://github.com/asad/smsd">http://github.com/asad/smsd</a>.
29  */
30 @Deprecated
31 public class AbstractReactionLabeller {
32 
33     /**
34      * A nasty hack necessary to get around a bug in the CDK
35      */
36     private boolean fixAtomMappingCastType = false;
37 
fixAtomMapping(IAtomContainer canonicalForm)38     private void fixAtomMapping(IAtomContainer canonicalForm) {
39         for (IAtom a : canonicalForm.atoms()) {
40             String v = (String) a.getProperty(CDKConstants.ATOM_ATOM_MAPPING);
41             if (v != null) {
42                 a.setProperty(CDKConstants.ATOM_ATOM_MAPPING, Integer.valueOf(v));
43             }
44         }
45     }
46 
atomAtomMap(IReaction reaction, IReaction clone, Map<IAtomContainer, int[]> permutationMap)47     private Map<IAtom, IAtom> atomAtomMap(IReaction reaction, IReaction clone, Map<IAtomContainer, int[]> permutationMap) {
48         // create a Map of corresponding atoms for molecules
49         // (key: original Atom, value: clone Atom)
50         Map<IAtom, IAtom> atomAtom = new Hashtable<IAtom, IAtom>();
51         IAtomContainerSet reactants = reaction.getReactants();
52         IAtomContainerSet clonedReactants = clone.getReactants();
53         for (int i = 0; i < reactants.getAtomContainerCount(); ++i) {
54             IAtomContainer mol = reactants.getAtomContainer(i);
55             IAtomContainer mol2 = clonedReactants.getAtomContainer(i);
56             int[] permutation = permutationMap.get(mol2);
57             for (int j = 0; j < mol.getAtomCount(); ++j) {
58                 atomAtom.put(mol.getAtom(j), mol2.getAtom(permutation[j]));
59             }
60         }
61         IAtomContainerSet products = reaction.getProducts();
62         IAtomContainerSet clonedProducts = clone.getProducts();
63         for (int i = 0; i < products.getAtomContainerCount(); ++i) {
64             IAtomContainer mol = products.getAtomContainer(i);
65             IAtomContainer mol2 = clonedProducts.getAtomContainer(i);
66             int[] permutation = permutationMap.get(mol2);
67             for (int j = 0; j < mol.getAtomCount(); ++j) {
68                 atomAtom.put(mol.getAtom(j), mol2.getAtom(permutation[j]));
69             }
70         }
71 
72         for (IAtom key : atomAtom.keySet()) {
73             IAtomContainer keyAC = ReactionManipulator.getRelevantAtomContainer(reaction, key);
74             int keyIndex = keyAC.indexOf(key);
75             IAtom value = atomAtom.get(key);
76             IAtomContainer valueAC = ReactionManipulator.getRelevantAtomContainer(clone, value);
77             int valueIndex = valueAC.indexOf(value);
78             System.out.println("key " + keyIndex + key.getSymbol() + " mapped to " + valueIndex + value.getSymbol());
79         }
80 
81         return atomAtom;
82     }
83 
cloneMappings(IReaction reaction, Map<IAtom, IAtom> atomAtomMap)84     private List<IMapping> cloneMappings(IReaction reaction, Map<IAtom, IAtom> atomAtomMap) {
85         // clone the mappings
86         int numberOfMappings = reaction.getMappingCount();
87         List<IMapping> map = new ArrayList<IMapping>();
88         for (int mappingIndex = 0; mappingIndex < numberOfMappings; mappingIndex++) {
89             IMapping mapping = reaction.getMapping(mappingIndex);
90             IChemObject keyChemObj0 = mapping.getChemObject(0);
91             IChemObject keyChemObj1 = mapping.getChemObject(1);
92             IChemObject co0 = (IChemObject) atomAtomMap.get(keyChemObj0);
93             IChemObject co1 = (IChemObject) atomAtomMap.get(keyChemObj1);
94             map.add(new Mapping(co0, co1));
95         }
96         return map;
97     }
98 
99     /**
100      * Clone and Sort the mappings based on the order of the first object
101      * in the mapping (which is assumed to be the reactant).
102      *
103      * @param reaction
104      */
cloneAndSortMappings(IReaction reaction, IReaction copyOfReaction, Map<IAtomContainer, int[]> permutationMap)105     private void cloneAndSortMappings(IReaction reaction, IReaction copyOfReaction,
106             Map<IAtomContainer, int[]> permutationMap) {
107 
108         // make a lookup for the indices of the atoms in the copy
109         final Map<IChemObject, Integer> indexMap = new HashMap<IChemObject, Integer>();
110         List<IAtomContainer> all = ReactionManipulator.getAllAtomContainers(copyOfReaction);
111         int globalIndex = 0;
112         for (IAtomContainer ac : all) {
113             for (IAtom atom : ac.atoms()) {
114                 indexMap.put(atom, globalIndex);
115                 globalIndex++;
116             }
117         }
118 
119         Map<IAtom, IAtom> atomAtomMap = atomAtomMap(reaction, copyOfReaction, permutationMap);
120         List<IMapping> map = cloneMappings(reaction, atomAtomMap);
121 
122         Comparator<IMapping> mappingSorter = new Comparator<IMapping>() {
123 
124             /**
125              * {@inheritDoc}
126              */
127             @Override
128             public int compare(IMapping o1, IMapping o2) {
129                 IChemObject o10 = o1.getChemObject(0);
130                 IChemObject o20 = o2.getChemObject(0);
131                 return indexMap.get(o10).compareTo(indexMap.get(o20));
132             }
133 
134         };
135         Collections.sort(map, mappingSorter);
136         int mappingIndex = 0;
137         for (IMapping mapping : map) {
138             mapping.getChemObject(0).setProperty(CDKConstants.ATOM_ATOM_MAPPING, mappingIndex);
139             mapping.getChemObject(1).setProperty(CDKConstants.ATOM_ATOM_MAPPING, mappingIndex);
140             copyOfReaction.addMapping(mapping);
141             mappingIndex++;
142         }
143 
144     }
145 
labelReaction(IReaction reaction, ICanonicalMoleculeLabeller labeller)146     public IReaction labelReaction(IReaction reaction, ICanonicalMoleculeLabeller labeller) {
147         System.out.println("labelling");
148         IReaction canonReaction = new Reaction();
149 
150         Map<IAtomContainer, int[]> permutationMap = new HashMap<IAtomContainer, int[]>();
151 
152         IAtomContainerSet canonicalProducts = DefaultChemObjectBuilder.getInstance().newInstance(
153                 IAtomContainerSet.class);
154         for (IAtomContainer product : reaction.getProducts().atomContainers()) {
155             IAtomContainer canonicalForm = labeller.getCanonicalMolecule(product);
156             if (fixAtomMappingCastType) {
157                 fixAtomMapping(canonicalForm);
158             }
159             IAtomContainer canonicalMolecule = canonicalForm.getBuilder().newInstance(IAtomContainer.class,
160                     canonicalForm);
161             permutationMap.put(canonicalMolecule, labeller.getCanonicalPermutation(product));
162             canonicalProducts.addAtomContainer(canonicalMolecule);
163         }
164         IAtomContainerSet canonicalReactants = DefaultChemObjectBuilder.getInstance().newInstance(
165                 IAtomContainerSet.class);
166         for (IAtomContainer reactant : reaction.getReactants().atomContainers()) {
167             IAtomContainer canonicalForm = labeller.getCanonicalMolecule(reactant);
168             if (fixAtomMappingCastType) {
169                 fixAtomMapping(canonicalForm);
170             }
171             IAtomContainer canonicalMolecule = canonicalForm.getBuilder().newInstance(IAtomContainer.class,
172                     canonicalForm);
173             permutationMap.put(canonicalMolecule, labeller.getCanonicalPermutation(reactant));
174             canonicalReactants.addAtomContainer(canonicalMolecule);
175         }
176         canonReaction.setProducts(canonicalProducts);
177         canonReaction.setReactants(canonicalReactants);
178         cloneAndSortMappings(reaction, canonReaction, permutationMap);
179         return canonReaction;
180     }
181 
182 }
183