Permalink
Browse files

chiral hash code configuration in HashGeneratorMaker, the configurati…

…on will add both double bond and tetrahedral encoding to the new hash generator

Signed-off-by: Egon Willighagen <egonw@users.sourceforge.net>
  • Loading branch information...
johnmay authored and egonw committed Feb 12, 2013
1 parent bb26ddf commit 5afe53731b8bea21e79abdf1b7b8599086363388
@@ -5,6 +5,11 @@
import org.openscience.cdk.hash.seed.AtomEncoder;
import org.openscience.cdk.hash.seed.BasicAtomEncoder;
import org.openscience.cdk.hash.seed.ConjugatedAtomEncoder;
import org.openscience.cdk.hash.stereo.StereoEncoder;
import org.openscience.cdk.hash.stereo.factory.GeometricDoubleBondEncoderFactory;
import org.openscience.cdk.hash.stereo.factory.GeometricTetrahedralEncoderFactory;
import org.openscience.cdk.hash.stereo.factory.StereoEncoderFactory;
import org.openscience.cdk.interfaces.IAtomContainer;
import java.util.ArrayList;
import java.util.EnumSet;
@@ -65,6 +70,9 @@
private EnumSet<BasicAtomEncoder> encoderSet = EnumSet
.noneOf(BasicAtomEncoder.class);
/* list of stereo encoders */
private List<StereoEncoderFactory> stereoEncoders = new ArrayList<StereoEncoderFactory>();
/**
* Specify the depth of the hash generator. Larger values discriminate more
* molecules.
@@ -149,7 +157,9 @@ public HashGeneratorMaker radical() {
*/
@TestMethod("testChiral")
public HashGeneratorMaker chiral() {
throw new UnsupportedOperationException("not yet supported");
this.stereoEncoders.add(new GeometricTetrahedralEncoderFactory());
this.stereoEncoders.add(new GeometricDoubleBondEncoderFactory());
return this;
}
/**
@@ -183,6 +193,29 @@ public HashGeneratorMaker encode(AtomEncoder encoder) {
return this;
}
/**
* Combines the separate stereo encoder factories into a single factory.
*
* @return a single stereo encoder factory
*/
private StereoEncoderFactory makeStereoEncoderFactory() {
if (stereoEncoders.isEmpty()) {
return StereoEncoderFactory.EMPTY;
} else if (stereoEncoders.size() == 1) {
return stereoEncoders.get(0);
} else {
StereoEncoderFactory factory = new ConjugatedEncoderFactory(stereoEncoders
.get(0),
stereoEncoders
.get(1));
for (int i = 2; i < stereoEncoders.size(); i++) {
factory = new ConjugatedEncoderFactory(factory, stereoEncoders
.get(i));
}
return factory;
}
}
/**
* Given the current configuration create an {@link EnsembleHashGenerator}.
*
@@ -230,7 +263,73 @@ public AtomHashGenerator atomic() {
return new BasicAtomHashGenerator(new SeedGenerator(encoder),
new Xorshift(),
makeStereoEncoderFactory(),
depth);
}
/**
* Help class to combined two stereo encoder factories
*/
private final class ConjugatedEncoderFactory
implements StereoEncoderFactory {
private final StereoEncoderFactory left, right;
/**
* Create a new conjugated encoder factory from the left and right
* factories.
* @param left encoder factory
* @param right encoder factory
*/
private ConjugatedEncoderFactory(StereoEncoderFactory left, StereoEncoderFactory right) {
this.left = left;
this.right = right;
}
/**
* @inheritDoc
*/
@Override
public StereoEncoder create(IAtomContainer container, int[][] graph) {
return new ConjugatedEncoder(left.create(container, graph), right
.create(container, graph));
}
}
/**
* Help class to combined two stereo encoders
*/
private final class ConjugatedEncoder implements StereoEncoder {
private final StereoEncoder left, right;
/**
* Create a new conjugated encoder from a left and right encoder.
* @param left encoder
* @param right encoder
*/
private ConjugatedEncoder(StereoEncoder left, StereoEncoder right) {
this.left = left;
this.right = right;
}
/**
* Encodes using the left and then the right encoder.
* @param current current invariants
* @param next next invariants
* @return whether either encoder modified any values
*/
@Override public boolean encode(long[] current, long[] next) {
boolean modified = left.encode(current, next);
return right.encode(current, next) || modified;
}
/**
* reset the left and right encoders
*/
@Override public void reset() {
left.reset();
right.reset();
}
}
}
@@ -24,16 +24,19 @@
package org.openscience.cdk.hash;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;
import org.openscience.cdk.hash.seed.AtomEncoder;
import org.openscience.cdk.hash.seed.ConjugatedAtomEncoder;
import org.openscience.cdk.hash.stereo.factory.StereoEncoderFactory;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
@@ -95,11 +98,12 @@
Assert.assertThat(encoders.get(0), is((AtomEncoder) ORBITAL_HYBRIDIZATION));
}
@Test(expected = UnsupportedOperationException.class)
public void testChiral() {
new HashGeneratorMaker().depth(0)
.chiral()
.atomic();
@Test public void testChiral() {
AtomHashGenerator generator = new HashGeneratorMaker().depth(0)
.elemental()
.chiral()
.atomic();
assertThat(encoder(generator), is(not(StereoEncoderFactory.EMPTY)));
}
@Test(expected = UnsupportedOperationException.class)
@@ -126,7 +130,7 @@ public void testOrdering() {
}
@Test(expected = NullPointerException.class)
public void testEncode_Null(){
public void testEncode_Null() {
new HashGeneratorMaker().encode(null);
}
@@ -193,6 +197,20 @@ public void testDepth() throws NoSuchFieldException,
assertThat(value, is(5));
}
public static StereoEncoderFactory encoder(AtomHashGenerator generator) {
if (generator instanceof BasicAtomHashGenerator) {
try {
Field f = generator.getClass().getDeclaredField("factory");
f.setAccessible(true);
return (StereoEncoderFactory) f.get(generator);
} catch (NoSuchFieldException e) {
System.err.println(e.getMessage());
} catch (IllegalAccessException e) {
System.err.println(e.getMessage());
}
}
return null;
}
/**
* Extract the AtomEncoders using reflection

0 comments on commit 5afe537

Please sign in to comment.