package gdsc.smlm.results;
import org.junit.Assert;
import org.junit.Test;
import gdsc.core.utils.DoubleEquality;
public class PeakResultTest
{
double[] test_a = { 100, 130, 160 };
double[] test_s = { 80, 100, 140 };
double[] test_N = { 1, 10, 30, 100, 1000 };
double[] test_b2 = { 0, 1, 2, 4, 8 };
int minPoints = 3, maxPoints = 20;
@Test
public void canCalculateMaximumLikelihoodVariance()
{
for (double a : test_a)
for (double s : test_s)
for (double N : test_N)
for (double b2 : test_b2)
for (int points = 3; points <= 20; points++)
{
PeakResult.getMLVarianceX(a, s, N, b2, true, points);
}
}
@Test
public void lowerIntegrationPointsApproximateMaximumLikelihoodVariance()
{
double[] sum = new double[maxPoints + 1];
int count = 0;
for (double a : test_a)
for (double s : test_s)
for (double N : test_N)
for (double b2 : test_b2)
{
count++;
double e = PeakResult.getMLVarianceX(a, s, N, b2, true, 30);
for (int points = minPoints; points <= maxPoints; points++)
{
double o = PeakResult.getMLVarianceX(a, s, N, b2, true, points);
double error = DoubleEquality.relativeError(e, o);
sum[points] += error;
if (error > 1e-2)
{
String msg = String.format("a=%f, s=%f, N=%f, b2=%f, points=%d : %f != %f : %f\n", a, s,
N, b2, points, e, o, error);
Assert.assertTrue(msg, false);
}
}
}
for (int points = minPoints; points <= maxPoints; points++)
{
System.out.printf("Points = %d, Av error = %f\n", points, sum[points] / count);
}
}
@Test
public void runSpeedTest()
{
// Test with realistic parameters
// Warm-up
for (double a : new double[] { 108 })
for (double s : new double[] { 120 })
for (double N : new double[] { 50, 100, 300 })
for (double b2 : new double[] { 0.5, 1, 2 })
for (int points = 3; points <= 20; points++)
{
PeakResult.getMLVarianceX(a, s, N, b2, true, points);
}
// Get average performance
double[] sum = new double[maxPoints + 1];
double[] sum2 = new double[sum.length];
long[] time = new long[sum.length];
long count = 0, count2 = 0;
for (double a : new double[] { 108 })
for (double s : new double[] { 120 })
for (double N : new double[] { 50, 100, 300 })
for (double b2 : new double[] { 0.5, 1, 2 })
{
long min = Long.MAX_VALUE;
for (int points = 3; points <= 20; points++)
{
long t = System.nanoTime();
for (int i = 0; i < 1000; i++)
PeakResult.getMLVarianceX(a, s, N, b2, true, points);
t = time[points] = System.nanoTime() - t;
if (min > t)
min = t;
}
// Proportional weighting to the calculation that takes the longest
count++;
count2 += min;
// Store relative performance
double factor = 1.0 / min;
for (int points = 3; points <= 20; points++)
{
sum[points] += time[points] * factor;
sum2[points] += time[points];
}
}
for (int points = minPoints; points <= maxPoints; points++)
{
System.out.printf("Points = %d, Av relative time = %f, Slow down factor = %f\n", points,
sum[points] / count, sum2[points] / count2);
}
}
@Test
public void canConvertLocalBackgroundToNoise()
{
double gain = 6;
double[] photons = { 0, 1, 2, 4, 10, 50, 100 };
// CCD
for (double p : photons)
{
// Assuming a Poisson distribution N photons should have a noise of sqrt(N).
// However the input and output are in ADU counts so we apply the gain.
double n = PeakResult.localBackgroundToNoise(p * gain, gain, false);
Assert.assertEquals("CCD " + p, Math.sqrt(p) * gain, n, 0);
}
// EM-CCD
for (double p : photons)
{
// Assuming a Poisson distribution N photons should have a noise of sqrt(N * 2)
// (due to the EM-CCD noise factor of 2).
// However the input and output are in ADU counts so we apply the gain.
double n = PeakResult.localBackgroundToNoise(p * gain, gain, true);
Assert.assertEquals("EM-CCD " + p, Math.sqrt(2 * p) * gain, n, 0);
}
}
@Test
public void canConvertLocalBackgroundToNoiseAndBack()
{
double gain = 6;
double[] photons = { 0, 1, 2, 4, 10, 50, 100 };
for (boolean emCCD : new boolean[] { false, true })
{
for (double p : photons)
{
double b = p * gain;
double n = PeakResult.localBackgroundToNoise(b, gain, emCCD);
double b2 = PeakResult.noiseToLocalBackground(n, gain, emCCD);
Assert.assertEquals(emCCD + " " + p, b, b2, 1e-6);
}
}
}
}