Final edge case bug fixes to QualityUtil routines

-- log10 functions in QualityUtils allow -Infinity to allow log10(0.0) values
-- Fix edge condition of log10OneMinusX failing with Double.MIN_VALUE
-- Fix another edge condition of log10OneMinusX failing with a small but not min_value double
This commit is contained in:
Mark DePristo 2013-02-11 12:42:50 -08:00
parent b393c27f07
commit 3b67aa8aee
3 changed files with 34 additions and 6 deletions

View File

@ -1244,11 +1244,23 @@ public class MathUtils {
/**
* Checks that the result is a well-formed log10 probability
*
* @param result a supposedly well-formed log10 probability value
* @param result a supposedly well-formed log10 probability value. By default allows
* -Infinity values, as log10(0.0) == -Infinity.
* @return true if result is really well formed
*/
public static boolean goodLog10Probability(final double result) {
return result <= 0.0 && ! Double.isInfinite(result) && ! Double.isNaN(result);
return goodLog10Probability(result, true);
}
/**
* Checks that the result is a well-formed log10 probability
*
* @param result a supposedly well-formed log10 probability value
* @param allowNegativeInfinity should we consider a -Infinity value ok?
* @return true if result is really well formed
*/
public static boolean goodLog10Probability(final double result, final boolean allowNegativeInfinity) {
return result <= 0.0 && result != Double.POSITIVE_INFINITY && (allowNegativeInfinity || result != Double.NEGATIVE_INFINITY) && ! Double.isNaN(result);
}
/**
@ -1779,7 +1791,9 @@ public class MathUtils {
return Double.NEGATIVE_INFINITY;
else if ( x == 0.0 )
return 0.0;
else
return Math.log10(1 / x - 1) + Math.log10(x);
else {
final double d = Math.log10(1 / x - 1) + Math.log10(x);
return Double.isInfinite(d) || d > 0.0 ? 0.0 : d;
}
}
}

View File

@ -312,7 +312,8 @@ public class QualityUtils {
* This is a very generic method, that simply computes a phred-scaled double quality
* score given an error rate. It has the same precision as a normal double operation
*
* @param trueRateLog10 the probability of being right (0.0-1.0)
* @param trueRateLog10 the log10 probability of being right (0.0-1.0). Can be -Infinity to indicate
* that the result is impossible in which MIN_PHRED_SCALED_QUAL is returned
* @return a phred-scaled version of the error rate implied by trueRate
*/
@Ensures("result >= 0.0")
@ -340,7 +341,8 @@ public class QualityUtils {
* This is a very generic method, that simply computes a phred-scaled double quality
* score given an error rate. It has the same precision as a normal double operation
*
* @param errorRateLog10 the log10 probability of being wrong (0.0-1.0)
* @param errorRateLog10 the log10 probability of being wrong (0.0-1.0). Can be -Infinity, in which case
* the result is MIN_PHRED_SCALED_QUAL
* @return a phred-scaled version of the error rate
*/
@Ensures("result >= 0.0")

View File

@ -101,6 +101,18 @@ public class QualityUtilsUnitTest extends BaseTest {
}
}
@Test
public void testTrueProbWithMinDouble() {
final byte actual = QualityUtils.trueProbToQual(Double.MIN_VALUE);
Assert.assertEquals(actual, 1, "Failed to convert true prob of min double to 1 qual");
}
@Test
public void testTrueProbWithVerySmallValue() {
final byte actual = QualityUtils.trueProbToQual(1.7857786272673852E-19);
Assert.assertEquals(actual, 1, "Failed to convert true prob of very small value 1.7857786272673852E-19 to 1 qual");
}
@Test
public void testQualCaches() {
Assert.assertEquals(QualityUtils.qualToErrorProb((byte) 20), 0.01, 1e-6);