diff --git a/public/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java b/public/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java index e792a808d..a0b3f2b0a 100644 --- a/public/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java +++ b/public/java/src/org/broadinstitute/sting/utils/recalibration/RecalDatumNode.java @@ -169,10 +169,10 @@ public class RecalDatumNode { * The maximum penalty among all nodes * @return */ - public double maxPenalty() { - double max = getPenalty(); + public double maxPenalty(final boolean leafOnly) { + double max = ! leafOnly || isLeaf() ? getPenalty() : Double.MIN_VALUE; for ( final RecalDatumNode sub : subnodes ) - max = Math.max(max, sub.maxPenalty()); + max = Math.max(max, sub.maxPenalty(leafOnly)); return max; } @@ -180,10 +180,10 @@ public class RecalDatumNode { * The minimum penalty among all nodes * @return */ - public double minPenalty() { - double min = getPenalty(); + public double minPenalty(final boolean leafOnly) { + double min = ! leafOnly || isLeaf() ? getPenalty() : Double.MAX_VALUE; for ( final RecalDatumNode sub : subnodes ) - min = Math.min(min, sub.minPenalty()); + min = Math.min(min, sub.minPenalty(leafOnly)); return min; } @@ -251,7 +251,7 @@ public class RecalDatumNode { * @return the chi2 penalty, or 0.0 if it cannot be calculated */ private double calcPenalty() { - if ( isLeaf() ) + if ( isLeaf() || freeToMerge() ) return 0.0; else if ( subnodes.size() == 1 ) // only one value, so its free to merge away @@ -277,6 +277,22 @@ public class RecalDatumNode { } } + /** + * 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 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 * @@ -346,8 +362,6 @@ public class RecalDatumNode { while ( root.size() > maxElements ) { // remove the lowest penalty element, and continue 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 @@ -363,7 +377,8 @@ public class RecalDatumNode { */ private RecalDatumNode removeLowestPenaltyNode() { final Pair, 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, Boolean> result = removeNode(nodeToRemove.getFirst());