Phase II of Stratification manager

-- Renamed and reorganized infrastructure
-- StratificationManager now a Map from List<Object> -> V.  All key functions are implemented.  Less commonly used TODO
-- Ready for hookup to VE
This commit is contained in:
Mark DePristo 2012-03-28 14:18:56 -04:00
parent 9f1cd0ff66
commit 8971b54b21
6 changed files with 285 additions and 121 deletions

View File

@ -1,101 +0,0 @@
/*
* Copyright (c) 2012, The Broad Institute
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications;
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;
import java.util.*;
/**
* Represents the full state space of all stratification combinations
*
* @author Mark DePristo
* @since 3/27/12
*/
public class StratificationStates<T extends SetOfStates> {
private final StratNode<T> root;
public StratificationStates(final List<T> strats) {
this.root = buildStratificationTree(new LinkedList<T>(strats));
assignKeys(root, 0);
}
private StratNode<T> buildStratificationTree(final Queue<T> strats) {
final T first = strats.poll();
if ( first == null ) {
// we are at a leaf
return new StratNode<T>();
} else {
// we are in the middle of the tree
final Collection<Object> states = first.getAllStates();
final LinkedHashMap<Object, StratNode<T>> subNodes = new LinkedHashMap<Object, StratNode<T>>(states.size());
for ( final Object state : states ) {
// have to copy because poll modifies the queue
final Queue<T> copy = new LinkedList<T>(strats);
subNodes.put(state, buildStratificationTree(copy));
}
return new StratNode<T>(first, subNodes);
}
}
public int getNStates() {
return root.size();
}
public StratNode<T> getRoot() {
return root;
}
public int getKey(final List<Object> states) {
return root.find(states, 0);
}
public Set<Integer> getKeys(final List<List<Object>> allStates) {
final HashSet<Integer> keys = new HashSet<Integer>();
root.find(allStates, 0, keys);
return keys;
}
private void assignKeys(final StratNode<T> root, int key) {
for ( final StratNode<T> node : root ) {
if ( node.isLeaf() )
node.setKey(key++);
}
}
public static List<List<Object>> combineStates(final List<Object> first, final List<Object> second) {
List<List<Object>> combined = new ArrayList<List<Object>>(first.size());
for ( int i = 0; i < first.size(); i++ ) {
final Object firstI = first.get(i);
final Object secondI = second.get(i);
if ( firstI.equals(secondI) )
combined.add(Collections.singletonList(firstI));
else
combined.add(Arrays.asList(firstI, secondI));
}
return combined;
}
}

View File

@ -22,7 +22,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications;
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manager;
import java.util.List;

View File

@ -22,7 +22,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications;
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manager;
import com.google.java.contract.Ensures;
import com.google.java.contract.Invariant;
@ -62,6 +62,7 @@ import java.util.*;
class StratNode<T extends SetOfStates> implements Iterable<StratNode<T>> {
int key = -1;
final T stratifier;
// TODO -- track state key that maps to root node
final Map<Object, StratNode<T>> subnodes;
protected StratNode() {
@ -93,7 +94,7 @@ class StratNode<T extends SetOfStates> implements Iterable<StratNode<T>> {
final Object state = states.get(offset);
StratNode<T> subnode = subnodes.get(state);
if ( subnode == null )
throw new ReviewedStingException("Couldn't find state for " + state + " at node " + this);
return -1;
else
return subnode.find(states, offset+1);
}

View File

@ -22,7 +22,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications;
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manager;
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2012, The Broad Institute
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manager;
import com.google.java.contract.Ensures;
import com.google.java.contract.Requires;
import org.broadinstitute.sting.utils.exceptions.ReviewedStingException;
import java.util.*;
/**
* Represents the full state space of all stratification combinations
*
* @author Mark DePristo
* @since 3/27/12
*/
public class StratificationManager<K extends SetOfStates, V> implements Map<List<Object>, V> {
private final StratNode<K> root;
private final int size;
private final ArrayList<V> values;
// -------------------------------------------------------------------------------------
//
// creating the manager
//
// -------------------------------------------------------------------------------------
@Requires("!strats.isEmpty()")
public StratificationManager(final List<K> strats) {
this.root = buildStratificationTree(new LinkedList<K>(strats));
assignKeys(root);
this.size = root.size();
if ( this.size == 0 )
throw new ReviewedStingException("Size == 0 in StratificationManager");
this.values = new ArrayList<V>(size());
for ( int i = 0; i < size(); i++ )
this.values().add(null);
}
private StratNode<K> buildStratificationTree(final Queue<K> strats) {
final K first = strats.poll();
if ( first == null ) {
// we are at a leaf
return new StratNode<K>();
} else {
// we are in the middle of the tree
final Collection<Object> states = first.getAllStates();
if ( states.isEmpty() )
throw new ReviewedStingException("State " + first + " is empty!");
final LinkedHashMap<Object, StratNode<K>> subNodes = new LinkedHashMap<Object, StratNode<K>>(states.size());
for ( final Object state : states ) {
// have to copy because poll modifies the queue
final Queue<K> copy = new LinkedList<K>(strats);
subNodes.put(state, buildStratificationTree(copy));
}
return new StratNode<K>(first, subNodes);
}
}
@Requires("root == this.root")
private void assignKeys(final StratNode<K> root) {
int key = 0;
for ( final StratNode<K> node : root ) {
if ( node.isLeaf() )
node.setKey(key++);
}
}
// -------------------------------------------------------------------------------------
//
// simple accessors
//
// -------------------------------------------------------------------------------------
@Ensures("result >= 0")
public int size() {
return size;
}
@Ensures("result != null")
public StratNode<K> getRoot() {
return root;
}
// -------------------------------------------------------------------------------------
//
// mapping from states -> keys
//
// -------------------------------------------------------------------------------------
@Requires("states != null")
@Ensures("result >= -1")
public int getKey(final List<Object> states) {
return root.find(states, 0);
}
@Requires("allStates != null")
@Ensures("result != null")
public Set<Integer> getKeys(final List<List<Object>> allStates) {
final HashSet<Integer> keys = new HashSet<Integer>();
root.find(allStates, 0, keys);
return keys;
}
// -------------------------------------------------------------------------------------
//
// values
//
// -------------------------------------------------------------------------------------
@Override
@Ensures("result != null")
public ArrayList<V> values() {
return values;
}
@Requires("key >= 0 && key <= size()")
@Ensures("get(key) == value")
public void set(final int key, final V value) {
values.set(key, value);
}
@Requires("key >= 0 && key <= size()")
public V get(final int key) {
return values.get(key);
}
@Requires("getKey(states) != -1")
public V get(final List<Object> states) {
return get(getKey(states));
}
@Override
public V get(final Object o) {
return get((List<Object>)o);
}
@Override
public boolean isEmpty() {
return false;
}
public boolean containsKey(final List<Object> o) {
return getKey(o) != -1;
}
@Override
public boolean containsKey(final Object o) {
return containsKey((List<Object>)o);
}
@Override
public boolean containsValue(final Object o) {
throw new ReviewedStingException("containsValue() not implemented for StratificationManager");
}
@Override
public V put(final List<Object> objects, final V v) {
throw new ReviewedStingException("put() not implemented for StratificationManager");
}
@Override
public V remove(final Object o) {
throw new ReviewedStingException("remove() not implemented for StratificationManager");
}
@Override
public void putAll(final Map<? extends List<Object>, ? extends V> map) {
throw new ReviewedStingException("clear() not implemented for StratificationManager");
}
@Override
public void clear() {
throw new ReviewedStingException("clear() not implemented for StratificationManager");
}
@Override
public Set<List<Object>> keySet() {
throw new ReviewedStingException("Not yet implemented");
}
@Override
public Set<Entry<List<Object>, V>> entrySet() {
throw new ReviewedStingException("Not yet implemented");
}
// -------------------------------------------------------------------------------------
//
// utilities
//
// -------------------------------------------------------------------------------------
public static List<List<Object>> combineStates(final List<Object> first, final List<Object> second) {
List<List<Object>> combined = new ArrayList<List<Object>>(first.size());
for ( int i = 0; i < first.size(); i++ ) {
final Object firstI = first.get(i);
final Object secondI = second.get(i);
if ( firstI.equals(secondI) )
combined.add(Collections.singletonList(firstI));
else
combined.add(Arrays.asList(firstI, secondI));
}
return combined;
}
}

View File

@ -23,7 +23,7 @@
*/
// our package
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications;
package org.broadinstitute.sting.gatk.walkers.varianteval.stratifications.manager;
// the imports for unit testing.
@ -40,7 +40,7 @@ import java.io.FileNotFoundException;
import java.util.*;
public class StratificationStatesUnitTest extends BaseTest {
public class StratificationManagerUnitTest extends BaseTest {
@BeforeClass
public void init() throws FileNotFoundException {
}
@ -83,6 +83,13 @@ public class StratificationStatesUnitTest extends BaseTest {
return asSetOfStates;
}
public ArrayList<Integer> values() {
final ArrayList<Integer> l = new ArrayList<Integer>();
for ( int i = 0; i < nStates; i++ )
l.add(i);
return l;
}
public Queue<List<Object>> getAllCombinations() {
return getAllCombinations(new LinkedList<List<Object>>(allStates));
}
@ -136,15 +143,26 @@ public class StratificationStatesUnitTest extends BaseTest {
new StratificationStatesTestProvider(Arrays.asList(0, 1), Arrays.asList(2, 3), Arrays.asList(4, 5), Arrays.asList(6, 7));
return StratificationStatesTestProvider.getTests(StratificationStatesTestProvider.class);
}
private final StratificationManager<ListAsSetOfStates, Integer> createManager(StratificationStatesTestProvider cfg) {
final StratificationManager<ListAsSetOfStates, Integer> manager = new StratificationManager<ListAsSetOfStates, Integer>(cfg.getStateSpaceList());
List<Integer> values = cfg.values();
for ( int i = 0; i < cfg.nStates; i++ )
manager.set(i, values.get(i));
Assert.assertEquals(manager.values(), values, "Values not equal");
return manager;
}
@Test(dataProvider = "StratificationStatesTestProvider")
public void testLeafCount(StratificationStatesTestProvider cfg) {
final StratificationStates<ListAsSetOfStates> stratificationStates = new StratificationStates<ListAsSetOfStates>(cfg.getStateSpaceList());
Assert.assertEquals(stratificationStates.getNStates(), cfg.nStates);
final StratificationManager<ListAsSetOfStates, Integer> stratificationManager = createManager(cfg);
Assert.assertEquals(stratificationManager.size(), cfg.nStates);
int nLeafs = 0;
for ( final StratNode node : stratificationStates.getRoot() ) {
for ( final StratNode node : stratificationManager.getRoot() ) {
if ( node.isLeaf() )
nLeafs++;
}
@ -153,9 +171,9 @@ public class StratificationStatesUnitTest extends BaseTest {
@Test(dataProvider = "StratificationStatesTestProvider")
public void testKeys(StratificationStatesTestProvider cfg) {
final StratificationStates<ListAsSetOfStates> stratificationStates = new StratificationStates<ListAsSetOfStates>(cfg.getStateSpaceList());
final StratificationManager<ListAsSetOfStates, Integer> stratificationManager = createManager(cfg);
final Set<Integer> seenKeys = new HashSet<Integer>(cfg.nStates);
for ( final StratNode node : stratificationStates.getRoot() ) {
for ( final StratNode node : stratificationManager.getRoot() ) {
if ( node.isLeaf() ) {
Assert.assertFalse(seenKeys.contains(node.getKey()), "Already seen the key");
seenKeys.add(node.getKey());
@ -165,20 +183,29 @@ public class StratificationStatesUnitTest extends BaseTest {
@Test(dataProvider = "StratificationStatesTestProvider")
public void testFindSingleKeys(StratificationStatesTestProvider cfg) {
final StratificationStates<ListAsSetOfStates> stratificationStates = new StratificationStates<ListAsSetOfStates>(cfg.getStateSpaceList());
final StratificationManager<ListAsSetOfStates, Integer> stratificationManager = createManager(cfg);
final Set<Integer> seenKeys = new HashSet<Integer>(cfg.nStates);
for ( List<Object> state : cfg.getAllCombinations() ) {
final int key = stratificationStates.getKey(state);
final int key = stratificationManager.getKey(state);
Assert.assertFalse(seenKeys.contains(key), "Already saw state mapping to this key");
Assert.assertTrue(stratificationManager.containsKey(state));
seenKeys.add(key);
// test value
Assert.assertEquals(stratificationManager.get(key), cfg.values().get(key));
Assert.assertEquals(stratificationManager.get(state), cfg.values().get(key));
state.set(0, 12345); // not present
Assert.assertEquals(stratificationManager.getKey(state), -1);
Assert.assertFalse(stratificationManager.containsKey(state));
}
}
@Test(dataProvider = "StratificationStatesTestProvider")
public void testFindMultipleKeys(StratificationStatesTestProvider cfg) {
final StratificationStates<ListAsSetOfStates> stratificationStates = new StratificationStates<ListAsSetOfStates>(cfg.getStateSpaceList());
final StratificationManager<ListAsSetOfStates, Integer> stratificationManager = createManager(cfg);
final List<List<Object>> states = new ArrayList<List<Object>>(cfg.allStates);
final Set<Integer> keys = stratificationStates.getKeys(states);
final Set<Integer> keys = stratificationManager.getKeys(states);
Assert.assertEquals(keys.size(), cfg.nStates, "Find all states didn't find all of the expected unique keys");
final Queue<List<Object>> combinations = cfg.getAllCombinations();
@ -186,12 +213,12 @@ public class StratificationStatesUnitTest extends BaseTest {
List<Object> first = combinations.poll();
List<Object> second = combinations.peek();
if ( second != null ) {
List<List<Object>> combined = StratificationStates.combineStates(first, second);
List<List<Object>> combined = StratificationManager.combineStates(first, second);
int nExpectedKeys = Utils.nCombinations(combined);
final int key1 = stratificationStates.getKey(first);
final int key2 = stratificationStates.getKey(second);
final Set<Integer> keysCombined = stratificationStates.getKeys(combined);
final int key1 = stratificationManager.getKey(first);
final int key2 = stratificationManager.getKey(second);
final Set<Integer> keysCombined = stratificationManager.getKeys(combined);
Assert.assertTrue(keysCombined.contains(key1), "couldn't find key in data set");
Assert.assertTrue(keysCombined.contains(key2), "couldn't find key in data set");
@ -200,4 +227,11 @@ public class StratificationStatesUnitTest extends BaseTest {
}
}
}
@Test(dataProvider = "StratificationStatesTestProvider")
public void testMapSet(StratificationStatesTestProvider cfg) {
final StratificationManager<ListAsSetOfStates, Integer> stratificationManager = createManager(cfg);
stratificationManager.set(0, -1);
Assert.assertEquals((int)stratificationManager.get(0), -1);
}
}