|
41 | 41 | import org.openscience.cdk.isomorphism.mcss.RNode; |
42 | 42 | import org.openscience.cdk.tools.manipulator.BondManipulator; |
43 | 43 |
|
44 | | -import java.util.*; |
| 44 | +import java.util.ArrayList; |
| 45 | +import java.util.BitSet; |
| 46 | +import java.util.HashMap; |
| 47 | +import java.util.Iterator; |
| 48 | +import java.util.List; |
| 49 | +import java.util.Map; |
45 | 50 |
|
46 | 51 | /** |
47 | 52 | * This class implements a multipurpose structure comparison tool. |
|
85 | 90 | * It is possible to add a special treatment for this special query. |
86 | 91 | * Be reminded that this algorithm matches bonds only. |
87 | 92 | * </p> |
| 93 | + * <p> |
| 94 | + * <b>Note</b>While most isomorphism queries involve a multi-atom query structure |
| 95 | + * there may be cases in which the query atom is a single atom. In such a case |
| 96 | + * a mapping of target bonds to query bonds is not feasible. In such a case, the RMap objects |
| 97 | + * correspond to atom indices rather than bond indices. In general, this will not affect user |
| 98 | + * code and the same sequence of method calls for matching multi-atom query structures will |
| 99 | + * work for single atom query structures as well. |
| 100 | + * </p> |
88 | 101 | * |
89 | 102 | * @author Stephane Werner from IXELIS mail@ixelis.net |
90 | 103 | * @cdk.created 2002-07-17 |
@@ -218,9 +231,18 @@ public static List<List<RMap>> getIsomorphMaps(IAtomContainer g1, IAtomContainer |
218 | 231 | * Returns all the subgraph 'bond mappings' found for g2 in g1. |
219 | 232 | * This is an ArrayList of ArrayLists of RMap objects. |
220 | 233 | * |
| 234 | + * Note that if the query molecule is a single atom, then bond mappings |
| 235 | + * cannot be defined. In such a case, the RMap object refers directly to |
| 236 | + * atom - atom mappings. Thus RMap.id1 is the index of the target atom |
| 237 | + * and RMap.id2 is the index of the matching query atom (in this case, |
| 238 | + * it will always be 0). Note that in such a case, there is no need |
| 239 | + * to call makeAtomsMapsofBondsMaps, though if it is called, then the |
| 240 | + * return value is simply the same as the return value of this method. |
| 241 | + * |
221 | 242 | * @param g1 first molecule. Must not be an IQueryAtomContainer. |
222 | 243 | * @param g2 second molecule. May be an IQueryAtomContainer. |
223 | 244 | * @return the list of all the 'mappings' found projected of g1 |
| 245 | + * @see #makeAtomsMapsOfBondsMaps(java.util.List, org.openscience.cdk.interfaces.IAtomContainer, org.openscience.cdk.interfaces.IAtomContainer) |
224 | 246 | */ |
225 | 247 | public static List<List<RMap>> getSubgraphMaps(IAtomContainer g1, IAtomContainer g2) throws CDKException{ |
226 | 248 | return search(g1, g2, new BitSet(), getBitSet(g2), true, true); |
@@ -414,6 +436,20 @@ public static RGraph buildRGraph(IAtomContainer g1, IAtomContainer g2) throws C |
414 | 436 | public static List<List<RMap>> search(IAtomContainer g1, IAtomContainer g2, BitSet c1, |
415 | 437 | BitSet c2, boolean findAllStructure, boolean findAllMap) throws CDKException{ |
416 | 438 |
|
| 439 | + // handle single query atom case separately |
| 440 | + if (g2.getAtomCount() == 1) { |
| 441 | + List<List<RMap>> matches = new ArrayList<List<RMap>>(); |
| 442 | + IQueryAtom queryAtom = (IQueryAtom) g2.getAtom(0); |
| 443 | + for (IAtom atom : g1.atoms()) { |
| 444 | + if (queryAtom.matches(atom)) { |
| 445 | + List<RMap> lmap = new ArrayList<RMap>(); |
| 446 | + lmap.add(new RMap(g1.getAtomNumber(atom), 0)); |
| 447 | + matches.add(lmap); |
| 448 | + } |
| 449 | + } |
| 450 | + return matches; |
| 451 | + } |
| 452 | + |
417 | 453 | // reset result |
418 | 454 | List<List<RMap>> rMapsList = new ArrayList<List<RMap>>(); |
419 | 455 |
|
@@ -602,16 +638,17 @@ public static List<RMap> checkSingleAtomCases(IAtomContainer g1, IAtomContainer |
602 | 638 | * @param g2 The second one (first and second as in getMap). May be an QueryAtomContaienr. |
603 | 639 | * @return A Vector of Vectors of RMap objects of matching Atoms. |
604 | 640 | */ |
605 | | - public static List<List<RMap>> makeAtomsMapsOfBondsMaps(List<List<RMap>> l, IAtomContainer g1, IAtomContainer g2) { |
606 | | - if(l==null) { |
607 | | - return l; |
608 | | - } |
609 | | - List<List<RMap>> result = new ArrayList<List<RMap>>(); |
| 641 | + public static List<List<RMap>> makeAtomsMapsOfBondsMaps(List<List<RMap>> l, IAtomContainer g1, IAtomContainer g2) { |
| 642 | + if (l == null) { |
| 643 | + return l; |
| 644 | + } |
| 645 | + if (g2.getAtomCount() == 1) return l; // since the RMap is already an atom-atom mapping |
| 646 | + List<List<RMap>> result = new ArrayList<List<RMap>>(); |
610 | 647 | for (List<RMap> l2 : l) { |
611 | 648 | result.add(makeAtomsMapOfBondsMap(l2, g1, g2)); |
612 | 649 | } |
613 | | - return result; |
614 | | - } |
| 650 | + return result; |
| 651 | + } |
615 | 652 |
|
616 | 653 | /** |
617 | 654 | * This makes a map of matching atoms out of a map of matching bonds as produced by the get(Subgraph|Ismorphism)Map methods. |
|
0 commit comments