Skip to content

Commit

Permalink
Merge pull request #204 from cdk/patch/reactonsmarts
Browse files Browse the repository at this point in the history
Patch/reactonsmarts
  • Loading branch information
egonw committed Jun 5, 2016
2 parents cf70611 + 4d2e5d3 commit 40eea14
Show file tree
Hide file tree
Showing 18 changed files with 836 additions and 71 deletions.
16 changes: 16 additions & 0 deletions base/core/src/main/java/org/openscience/cdk/CDKConstants.java
Expand Up @@ -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 *
* **************************************
Expand Down
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2016 John May <jwmay@users.sf.net>
*
* Contact: cdk-devel@lists.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version. All we ask is that proper credit is given
* for our work, which includes - but is not limited to - adding the above
* copyright notice to the beginning of your source code files, and to any
* copyright notice that you may distribute with programs based on this work.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 U
*/

package org.openscience.cdk;

public enum ReactionRole {
Reactant,
Agent,
Product,
None
};
11 changes: 5 additions & 6 deletions base/isomorphism/pom.xml
Expand Up @@ -47,6 +47,11 @@
<artifactId>cdk-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>cdk-standard</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>cdk-data</artifactId>
Expand All @@ -67,12 +72,6 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>cdk-standard</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>cdk-silent</artifactId>
Expand Down
Expand Up @@ -25,6 +25,7 @@
package org.openscience.cdk.isomorphism;

import com.google.common.base.Predicate;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.graph.ConnectedComponents;
import org.openscience.cdk.graph.GraphUtil;
import org.openscience.cdk.interfaces.IAtomContainer;
Expand Down Expand Up @@ -65,8 +66,7 @@ public final class ComponentGrouping implements Predicate<int[]> {
/** The required (query) and the targetComponents of the target. */
private final int[] queryComponents, targetComponents;

/** Connected components of the target. */
private final ConnectedComponents cc;
private final int maxComponentIdx;

/**
* Create a predicate to match components for the provided query and target.
Expand All @@ -78,21 +78,31 @@ public final class ComponentGrouping implements Predicate<int[]> {
* @param target target structure
*/
public ComponentGrouping(IAtomContainer query, IAtomContainer target) {
this(query, GraphUtil.toAdjList(target));
this(query.getProperty(KEY, int[].class),
query.getProperty(KEY) != null ? determineComponents(target) : null);
}

/**
* Create a predicate to match components for the provided query and target.
* The target is pre-converted to an adjacency list ({@link
* GraphUtil#toAdjList(IAtomContainer)}) and the query components extracted
* from the property {@link #KEY} in the query.
*
* @param query query structure
* @param target target structure
*/
public ComponentGrouping(IAtomContainer query, int[][] target) {
this(query.getProperty(KEY, int[].class), query.getProperty(KEY) != null ? new ConnectedComponents(target)
: null);
private static int[] determineComponents(IAtomContainer target) {
int[] components = null;
// no atoms -> no components
if (target.isEmpty())
components = new int[0];
// defined by reaction grouping
if (components == null && target.getAtom(0).getProperty(CDKConstants.REACTION_GROUP) != null) {
components = new int[target.getAtomCount()];
for (int i = 0; i < target.getAtomCount(); i++) {
Integer grp = target.getAtom(i).getProperty(CDKConstants.REACTION_GROUP);
if (grp == null) {
components = null;
break;
}
components[i] = grp;
}
}
// calculate from connection table
if (components == null)
components = new ConnectedComponents(GraphUtil.toAdjList(target)).components();
return components;
}

/**
Expand All @@ -102,10 +112,16 @@ public ComponentGrouping(IAtomContainer query, int[][] target) {
* @param grouping query grouping
* @param cc connected component of the target
*/
public ComponentGrouping(int[] grouping, ConnectedComponents cc) {
this.queryComponents = grouping;
this.cc = cc;
this.targetComponents = cc != null ? cc.components() : null;
public ComponentGrouping(int[] grouping, int[] targetComponents) {
this.queryComponents = grouping;
this.targetComponents = targetComponents;
int max = 0;
if (targetComponents != null) {
for (int i = 0; i < targetComponents.length; i++)
if (targetComponents[i] > max)
max = targetComponents[i];
}
this.maxComponentIdx = max;
}

/**
Expand All @@ -123,7 +139,7 @@ public boolean apply(final int[] mapping) {

// bidirectional map of query/target components, last index
// of query components holds the count
int[] usedBy = new int[cc.nComponents() + 1];
int[] usedBy = new int[maxComponentIdx+1];
int[] usedIn = new int[queryComponents[mapping.length] + 1];

// verify we don't have any collisions
Expand Down
Expand Up @@ -25,6 +25,8 @@
package org.openscience.cdk.isomorphism;

import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IReaction;
import org.openscience.cdk.tools.manipulator.ReactionManipulator;

/**
* A structural pattern for finding an exact matching in a target compound.
Expand Down Expand Up @@ -75,6 +77,26 @@ public final boolean matches(IAtomContainer target) {
return match(target).length > 0;
}

/**
* Determine if there is a mapping of this pattern in the {@code target}
* reaction.
*
* <blockquote><pre>
* Pattern pattern = ...; // create pattern
* for (IReaction r : rs) {
* if (pattern.matches(r)) {
* // found mapping!
* }
* }
* </pre></blockquote>
*
* @param target the reaction to search for the pattern in
* @return the mapping from the pattern to the target
*/
public final boolean matches(IReaction target) {
return matches(ReactionManipulator.toMolecule(target));
}

/**
* Find all mappings of this pattern in the {@code target}. Stereochemistry
* should not be checked to allow filtering with {@link
Expand Down Expand Up @@ -108,6 +130,31 @@ public final boolean matches(IAtomContainer target) {
*/
public abstract Mappings matchAll(IAtomContainer target);

/**
* Find all mappings of this pattern in the {@code target} reaction.
*
* <blockquote><pre>
* Pattern pattern = Pattern.findSubstructure(query);
* for (IReaction r : rs) {
* for (int[] mapping : pattern.matchAll(r)) {
* // found mapping
* }
* }
* </pre></blockquote>
*
* The reaction is inlined into a molecule and vs mapped id's correspond
* to the absolute atom index in the reaction when considered as reactants, agents,
* products {@see ReactionManipulator#toMolecule}.
*
* @param target the reaction to search for the pattern in
* @return the mapping from the pattern to the target
* @see Mappings
* @see ReactionManipulator#toMolecule(IReaction)
*/
public final Mappings matchAll(IReaction target) {
return matchAll(ReactionManipulator.toMolecule(target));
}

/**
* Create a pattern which can be used to find molecules which contain the
* {@code query} structure. The default structure search implementation is
Expand Down
Expand Up @@ -1544,6 +1544,7 @@ public boolean isEmpty() {

@Override
public void setStereoElements(List<IStereoElement> elements) {
throw new UnsupportedOperationException();
this.stereoElements.clear();
this.stereoElements.addAll(elements);
}
}
Expand Up @@ -111,7 +111,7 @@ static IAtomContainer ethylAlcoholHydrate() {
}

static ComponentGrouping create(int[] grouping, IAtomContainer container) {
return new ComponentGrouping(grouping, new ConnectedComponents(GraphUtil.toAdjList(container)));
return new ComponentGrouping(grouping, new ConnectedComponents(GraphUtil.toAdjList(container)).components());
}

}

0 comments on commit 40eea14

Please sign in to comment.