Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Symmetry of heavy atoms (skeleton) independent of explicit hydrogens.
Signed-off-by: Egon Willighagen <egonw@users.sourceforge.net>
  • Loading branch information
johnmay authored and egonw committed Jul 15, 2014
1 parent 17a518e commit d7f8a2c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 10 deletions.
Expand Up @@ -85,13 +85,14 @@ public final class Canon {
* invariants.
*
* @param g a graph (adjacency list representation)
* @param hydrogens binary vector of terminal hydrogens
* @param partition an initial partition of the vertices
*/
private Canon(int[][] g, long[] partition, boolean symOnly) {
private Canon(int[][] g, long[] partition, boolean[] hydrogens, boolean symOnly) {
this.g = g;
this.symOnly = symOnly;
labelling = partition.clone();
symmetry = refine(labelling);
symmetry = refine(labelling, hydrogens);
}

/**
Expand Down Expand Up @@ -134,7 +135,10 @@ public static long[] label(IAtomContainer container, int[][] g) {
public static long[] label(IAtomContainer container, int[][] g, long[] invariants) {
if (invariants.length != g.length)
throw new IllegalArgumentException("number of invariants != number of atoms");
return new Canon(g, invariants, false).labelling;
return new Canon(g,
invariants,
terminalHydrogens(container, g),
false).labelling;
}

/**
Expand All @@ -150,7 +154,10 @@ public static long[] label(IAtomContainer container, int[][] g, long[] invariant
* @see EquivalentClassPartitioner
*/
public static long[] symmetry(IAtomContainer container, int[][] g) {
return new Canon(g, basicInvariants(container, g), true).symmetry;
return new Canon(g,
basicInvariants(container, g),
terminalHydrogens(container, g),
true).symmetry;
}

/**
Expand All @@ -159,9 +166,10 @@ public static long[] symmetry(IAtomContainer container, int[][] g) {
*
* @param invariants the invariants to refine (canonical labelling gets
* written here)
* @param hydrogens binary vector of terminal hydrogens
* @return the symmetry classes
*/
private long[] refine(long[] invariants) {
private long[] refine(long[] invariants, boolean[] hydrogens) {

int ord = g.length;

Expand Down Expand Up @@ -199,13 +207,22 @@ private long[] refine(long[] invariants) {
for (int i = 0; i < ord && nextVs[i] >= 0; i++) {
int v = nextVs[i];
currVs[nnu++] = v;
curr[v] = primeProduct(g[v], prev);
curr[v] = hydrogens[v] ? prev[v]
: primeProduct(g[v], prev, hydrogens);
}
m = n;
}

if (symmetry == null)
if (symmetry == null) {
for (int i = 0; i < g.length; i++) {
if (hydrogens[i]) {
curr[i] = prev[g[i][0]];
hydrogens[i] = false;
}
}
n = ranker.rank(currVs, nextVs, nnu, curr, prev);
symmetry = Arrays.copyOf(prev, ord);
}

// partition is discrete or only symmetry classes are needed
if (symOnly || n == ord)
Expand Down Expand Up @@ -234,10 +251,13 @@ private long[] refine(long[] invariants) {
* @param ranks invariant ranks
* @return the prime product
*/
private long primeProduct(int[] ws, long[] ranks) {
private long primeProduct(int[] ws, long[] ranks, boolean[] hydrogens) {
long prod = 1;
for (int w : ws)
prod *= PRIMES[(int) ranks[w]];
for (int w : ws) {
if (!hydrogens[w]) {
prod *= PRIMES[(int) ranks[w]];
}
}
return prod;
}

Expand Down
Expand Up @@ -30,6 +30,8 @@
import org.openscience.cdk.silent.SilentChemObjectBuilder;
import org.openscience.cdk.smiles.SmilesParser;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Arrays;

import static org.hamcrest.CoreMatchers.is;
Expand Down Expand Up @@ -107,6 +109,18 @@ public class CanonTest {
}


@Test public void explicitHydrogensOfEthanolHaveSymmetry() throws Exception {
IAtomContainer m = smi("C([H])([H])C([H])([H])O");
long[] symmetry = Canon.symmetry(m, GraphUtil.toAdjList(m));
assertThat(symmetry, is(new long[]{6, 1, 1, 7, 3, 3, 5}));
}

@Test public void explicitHydrogensDoNotAffectHeavySymmetry() throws Exception {
IAtomContainer m = smi("CC=C(C)C[H]");
long[] symmetry = Canon.symmetry(m, GraphUtil.toAdjList(m));
assertThat(symmetry, is(new long[]{4, 2, 3, 5, 5, 1}));
}

static final SmilesParser sp = new SmilesParser(SilentChemObjectBuilder.getInstance());

static IAtomContainer smi(String smi) throws Exception {
Expand Down

0 comments on commit d7f8a2c

Please sign in to comment.