VisualizeAdaptiveTree now considers only leaf nodes when computing max/min penalty

This commit is contained in:
Mark DePristo 2012-08-07 08:38:16 -04:00
parent 15085bf03e
commit 982c735c76
1 changed files with 25 additions and 10 deletions

View File

@ -169,10 +169,10 @@ public class RecalDatumNode<T extends RecalDatum> {
* The maximum penalty among all nodes * The maximum penalty among all nodes
* @return * @return
*/ */
public double maxPenalty() { public double maxPenalty(final boolean leafOnly) {
double max = getPenalty(); double max = ! leafOnly || isLeaf() ? getPenalty() : Double.MIN_VALUE;
for ( final RecalDatumNode<T> sub : subnodes ) for ( final RecalDatumNode<T> sub : subnodes )
max = Math.max(max, sub.maxPenalty()); max = Math.max(max, sub.maxPenalty(leafOnly));
return max; return max;
} }
@ -180,10 +180,10 @@ public class RecalDatumNode<T extends RecalDatum> {
* The minimum penalty among all nodes * The minimum penalty among all nodes
* @return * @return
*/ */
public double minPenalty() { public double minPenalty(final boolean leafOnly) {
double min = getPenalty(); double min = ! leafOnly || isLeaf() ? getPenalty() : Double.MAX_VALUE;
for ( final RecalDatumNode<T> sub : subnodes ) for ( final RecalDatumNode<T> sub : subnodes )
min = Math.min(min, sub.minPenalty()); min = Math.min(min, sub.minPenalty(leafOnly));
return min; return min;
} }
@ -251,7 +251,7 @@ public class RecalDatumNode<T extends RecalDatum> {
* @return the chi2 penalty, or 0.0 if it cannot be calculated * @return the chi2 penalty, or 0.0 if it cannot be calculated
*/ */
private double calcPenalty() { private double calcPenalty() {
if ( isLeaf() ) if ( isLeaf() || freeToMerge() )
return 0.0; return 0.0;
else if ( subnodes.size() == 1 ) else if ( subnodes.size() == 1 )
// only one value, so its free to merge away // only one value, so its free to merge away
@ -277,6 +277,22 @@ public class RecalDatumNode<T extends RecalDatum> {
} }
} }
/**
* Is this node free to merge because its rounded Q score is the same as all nodes below
* @return
*/
private boolean freeToMerge() {
if ( isLeaf() ) // leaves are free to merge
return true;
else {
final byte myQual = getRecalDatum().getEmpiricalQualityAsByte();
for ( final RecalDatumNode<T> sub : subnodes )
if ( sub.getRecalDatum().getEmpiricalQualityAsByte() != myQual )
return false;
return true;
}
}
/** /**
* Calculate the penalty of this interval, given the overall error rate for the interval * Calculate the penalty of this interval, given the overall error rate for the interval
* *
@ -346,8 +362,6 @@ public class RecalDatumNode<T extends RecalDatum> {
while ( root.size() > maxElements ) { while ( root.size() > maxElements ) {
// remove the lowest penalty element, and continue // remove the lowest penalty element, and continue
root = root.removeLowestPenaltyNode(); root = root.removeLowestPenaltyNode();
if ( logger.isDebugEnabled() )
logger.debug("pruneByPenalty root size is now " + root.size() + " of max " + maxElements);
} }
// our size is below the target, so we are good, return // our size is below the target, so we are good, return
@ -363,7 +377,8 @@ public class RecalDatumNode<T extends RecalDatum> {
*/ */
private RecalDatumNode<T> removeLowestPenaltyNode() { private RecalDatumNode<T> removeLowestPenaltyNode() {
final Pair<RecalDatumNode<T>, Double> nodeToRemove = getMinPenaltyAboveLeafNode(); final Pair<RecalDatumNode<T>, Double> nodeToRemove = getMinPenaltyAboveLeafNode();
//logger.info("Removing " + nodeToRemove.getFirst() + " with penalty " + nodeToRemove.getSecond()); if ( logger.isDebugEnabled() )
logger.debug("Removing " + nodeToRemove.getFirst() + " with penalty " + nodeToRemove.getSecond());
final Pair<RecalDatumNode<T>, Boolean> result = removeNode(nodeToRemove.getFirst()); final Pair<RecalDatumNode<T>, Boolean> result = removeNode(nodeToRemove.getFirst());