use of uk.ac.sussex.gdsc.smlm.function.HalfPoissonFisherInformation in project GDSC-SMLM by aherbert.
the class CameraModelFisherInformationAnalysis method loadFunction.
/**
* Load the Poisson Fisher information for the camera type from the cache.
*
* @param type the type
* @param gain the gain
* @param noise the noise
* @param relativeError the relative error (used to compare the gain and noise)
* @return the poisson fisher information (or null)
*/
public static InterpolatedPoissonFisherInformation loadFunction(CameraType type, double gain, double noise, double relativeError) {
if (type == null || type.isFast()) {
return null;
}
final FiKey key = new FiKey(type, gain, noise);
PoissonFisherInformationData data = load(key);
if (data == null && relativeError > 0 && relativeError < 0.1) {
// Fuzzy matching
double error = 1;
for (final PoissonFisherInformationData d : cache.values()) {
final double e1 = DoubleEquality.relativeError(gain, d.getGain());
if (e1 < relativeError) {
final double e2 = DoubleEquality.relativeError(noise, d.getNoise());
if (e2 < relativeError) {
// Combined error - Euclidean distance
final double e = e1 * e1 + e2 * e2;
if (error > e) {
error = e;
data = d;
}
}
}
}
}
if (data == null) {
return null;
}
// Dump the samples. Convert to base e.
final double scale = Math.log(10);
final TDoubleArrayList meanList = new TDoubleArrayList(data.getAlphaSampleCount());
final TDoubleArrayList alphalist = new TDoubleArrayList(data.getAlphaSampleCount());
for (final AlphaSample sample : data.getAlphaSampleList()) {
meanList.add(sample.getLog10Mean() * scale);
alphalist.add(sample.getAlpha());
}
final double[] means = meanList.toArray();
final double[] alphas = alphalist.toArray();
SortUtils.sortData(alphas, means, true, false);
final BasePoissonFisherInformation upperf = (type == CameraType.EM_CCD) ? new HalfPoissonFisherInformation() : createPoissonGaussianApproximationFisherInformation(noise / gain);
return new InterpolatedPoissonFisherInformation(means, alphas, type.isLowerFixedI(), upperf);
}
use of uk.ac.sussex.gdsc.smlm.function.HalfPoissonFisherInformation in project GDSC-SMLM by aherbert.
the class UnivariateLikelihoodFisherInformationCalculatorTest method computePoissonFisherInformation.
private static void computePoissonFisherInformation(UniformRandomProvider rng, Model model) {
// Create function
final Gaussian2DFunction func = GaussianFunctionFactory.create2D(1, 10, 10, GaussianFunctionFactory.FIT_ERF_CIRCLE, null);
final double[] params = new double[1 + Gaussian2DFunction.PARAMETERS_PER_PEAK];
params[Gaussian2DFunction.BACKGROUND] = nextUniform(rng, 0.1, 0.3);
params[Gaussian2DFunction.SIGNAL] = nextUniform(rng, 100, 300);
params[Gaussian2DFunction.X_POSITION] = nextUniform(rng, 4, 6);
params[Gaussian2DFunction.Y_POSITION] = nextUniform(rng, 4, 6);
params[Gaussian2DFunction.X_SD] = nextUniform(rng, 1, 1.3);
Gradient1Function f1 = func;
FisherInformation fi;
switch(model) {
// Get a variance
case POISSON_GAUSSIAN:
final double var = 0.9 + 0.2 * rng.nextDouble();
fi = new PoissonGaussianApproximationFisherInformation(Math.sqrt(var));
f1 = (Gradient1Function) OffsetFunctionFactory.wrapFunction(func, SimpleArrayUtils.newDoubleArray(func.size(), var));
break;
case POISSON:
fi = new PoissonFisherInformation();
break;
case HALF_POISSON:
fi = new HalfPoissonFisherInformation();
break;
default:
throw new IllegalStateException();
}
// This introduces a dependency on a different package, and relies on that
// computing the correct answer. However that code predates this and so the
// test ensures that the FisherInformationCalculator functions correctly.
final PoissonGradientProcedure p1 = PoissonGradientProcedureUtils.create(f1);
p1.computeFisherInformation(params);
final double[] e = p1.getLinear();
final FisherInformationCalculator calc = new UnivariateLikelihoodFisherInformationCalculator(func, fi);
final FisherInformationMatrix I = calc.compute(params);
final double[] o = I.getMatrix().data;
final boolean emCcd = model == Model.HALF_POISSON;
if (emCcd) {
// Assumes half the poisson fisher information
SimpleArrayUtils.multiply(e, 0.5);
}
Assertions.assertArrayEquals(e, o, 1e-6);
final DoubleDoubleBiPredicate predicate = TestHelper.doublesAreClose(5e-2, 0);
if (model == Model.POISSON || model == Model.HALF_POISSON) {
// Get the Mortensen approximation for fitting Poisson data with a Gaussian.
// Set a to 100 for the square pixel adjustment.
final double a = 100;
final double s = params[Gaussian2DFunction.X_SD] * a;
final double N = params[Gaussian2DFunction.SIGNAL];
final double b2 = params[Gaussian2DFunction.BACKGROUND];
double var = Gaussian2DPeakResultHelper.getMLVarianceX(a, s, N, b2, emCcd);
// Convert expected variance to pixels
var /= (a * a);
// Get the limits by inverting the Fisher information
final double[] crlb = I.crlb();
TestAssertions.assertTest(var, crlb[2], predicate);
TestAssertions.assertTest(var, crlb[3], predicate);
}
}
Aggregations