Search in sources :

Example 1 with PoissonFisherInformationData

use of uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData in project GDSC-SMLM by aherbert.

the class CameraModelFisherInformationAnalysis method plotFromCache.

private static void plotFromCache() {
    // Build a list of curve stored in the cache
    final String[] names = new String[cache.size()];
    final PoissonFisherInformationData[] datas = new PoissonFisherInformationData[cache.size()];
    int count = 0;
    for (final Entry<FiKey, PoissonFisherInformationData> e : cache.entrySet()) {
        names[count] = e.getKey().toString();
        datas[count] = e.getValue();
        count++;
    }
    final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
    gd.addChoice("Fisher_information", names, cachePlot);
    gd.addChoice("Plot_point", POINT_OPTION, pointOption);
    gd.showDialog();
    if (gd.wasCanceled()) {
        return;
    }
    final int index = gd.getNextChoiceIndex();
    pointOption = gd.getNextChoiceIndex();
    cachePlot = names[index];
    final PoissonFisherInformationData data = datas[index];
    final FiKey key = new FiKey(data);
    count = 0;
    final double[] exp = new double[data.getAlphaSampleCount()];
    final double[] alpha = new double[data.getAlphaSampleCount()];
    for (final AlphaSample s : data.getAlphaSampleList()) {
        exp[count] = s.getLog10Mean();
        alpha[count] = s.getAlpha();
        count++;
    }
    // Just in case
    // Sort.sortArrays(alpha, exp, true);
    // Test if we can use ImageJ support for a X log scale
    final boolean logScaleX = ((float) Math.pow(10, exp[0]) != 0);
    double[] x = exp;
    String xTitle = "log10(photons)";
    if (logScaleX) {
        final double[] photons = new double[exp.length];
        for (int i = 0; i < photons.length; i++) {
            photons[i] = Math.pow(10, exp[i]);
        }
        x = photons;
        xTitle = "photons";
    }
    // Get interpolation for alpha. Convert to base e.
    final double[] logU = exp.clone();
    final double scale = Math.log(10);
    for (int i = 0; i < logU.length; i++) {
        logU[i] *= scale;
    }
    final BasePoissonFisherInformation if1 = getInterpolatedPoissonFisherInformation(key.getType(), logU, alpha, null);
    // Interpolate with 5 points per sample for smooth curve
    final int n = 5;
    final TDoubleArrayList iexp = new TDoubleArrayList();
    final TDoubleArrayList iphotons = new TDoubleArrayList();
    for (int i = 1; i < exp.length; i++) {
        final int i_1 = i - 1;
        final double h = (exp[i] - exp[i_1]) / n;
        for (int j = 0; j < n; j++) {
            final double e = exp[i_1] + j * h;
            iexp.add(e);
            iphotons.add(Math.pow(10, e));
        }
    }
    iexp.add(exp[exp.length - 1]);
    iphotons.add(Math.pow(10, exp[exp.length - 1]));
    final double[] photons = iphotons.toArray();
    final double[] ix = (logScaleX) ? photons : iexp.toArray();
    final double[] ialpha1 = getAlpha(if1, photons);
    final int pointShape = getPointShape(pointOption);
    final String title = "Cached Relative Fisher Information";
    final Plot plot = new Plot(title, xTitle, "Noise coefficient (alpha)");
    plot.setLimits(x[0], x[x.length - 1], -0.05, 1.05);
    if (logScaleX) {
        plot.setLogScaleX();
    }
    plot.setColor(Color.blue);
    plot.addPoints(ix, ialpha1, Plot.LINE);
    // Option to show nodes
    if (pointShape != -1) {
        plot.addPoints(x, alpha, pointShape);
    }
    plot.setColor(Color.BLACK);
    plot.addLabel(0, 0, cachePlot);
    ImageJUtils.display(title, plot);
}
Also used : Plot(ij.gui.Plot) AlphaSample(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.AlphaSample) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) PoissonFisherInformationData(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData) TDoubleArrayList(gnu.trove.list.array.TDoubleArrayList) BasePoissonFisherInformation(uk.ac.sussex.gdsc.smlm.function.BasePoissonFisherInformation)

Example 2 with PoissonFisherInformationData

use of uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData in project GDSC-SMLM by aherbert.

the class CameraModelFisherInformationAnalysis method loadData.

/**
 * Load the Poisson Fisher information data 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 data (or null)
 */
public static PoissonFisherInformationData loadData(CameraType type, double gain, double noise, double relativeError) {
    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;
                    }
                }
            }
        }
    }
    return data;
}
Also used : PoissonFisherInformationData(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData)

Example 3 with PoissonFisherInformationData

use of uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData in project GDSC-SMLM by aherbert.

the class CameraModelFisherInformationAnalysis method getAlpha.

private double[] getAlpha(final double[] photons, double[] exp, final BasePoissonFisherInformation fi, FiKey key) {
    final CameraType type = key.getType();
    final double[] alpha = new double[photons.length];
    if (!type.isFast()) {
        final int[] index;
        // Try and load from the cache
        final PoissonFisherInformationData data = load(key);
        if (data != null) {
            // Dump the samples
            final TDoubleArrayList meanList = new TDoubleArrayList(data.getAlphaSampleCount());
            final TDoubleArrayList alphalist = new TDoubleArrayList(data.getAlphaSampleCount());
            for (final AlphaSample sample : data.getAlphaSampleList()) {
                meanList.add(sample.getLog10Mean());
                alphalist.add(sample.getAlpha());
            }
            final double[] exp2 = meanList.toArray();
            final double[] alphas = alphalist.toArray();
            SortUtils.sortData(alphas, exp2, true, false);
            // Find any exponent not in the array
            final TIntArrayList list = new TIntArrayList(exp.length);
            for (int i = 0; i < exp.length; i++) {
                // Assume exp2 is sorted
                final int j = Arrays.binarySearch(exp2, exp[i]);
                if (j < 0) {
                    // Add to indices to compute
                    list.add(i);
                } else {
                    // Get alpha
                    alpha[i] = alphas[j];
                }
            }
            index = list.toArray();
        } else {
            // Compute all
            index = SimpleArrayUtils.natural(alpha.length);
        }
        if (index.length > 0) {
            IJ.showStatus("Computing " + getName(key));
            final int nThreads = Prefs.getThreads();
            if (es == null) {
                es = Executors.newFixedThreadPool(nThreads);
            }
            final Ticker ticker = ImageJUtils.createTicker(index.length, nThreads);
            final int nPerThread = (int) Math.ceil((double) index.length / nThreads);
            final LocalList<Future<?>> futures = new LocalList<>(nThreads);
            for (int i = 0; i < index.length; i += nPerThread) {
                final int start = i;
                final int end = Math.min(index.length, i + nPerThread);
                futures.add(es.submit(() -> {
                    final BasePoissonFisherInformation fi2 = fi.copy();
                    for (int ii = start; ii < end; ii++) {
                        final int j = index[ii];
                        alpha[j] = fi2.getAlpha(photons[j]);
                        ticker.tick();
                    }
                }));
            }
            ConcurrencyUtils.waitForCompletionUnchecked(futures);
            ImageJUtils.finished();
            save(key, exp, alpha);
        }
    } else {
        // Simple single threaded method.
        for (int i = 0; i < alpha.length; i++) {
            alpha[i] = fi.getAlpha(photons[i]);
        }
    }
    return alpha;
}
Also used : Ticker(uk.ac.sussex.gdsc.core.logging.Ticker) AlphaSample(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.AlphaSample) TIntArrayList(gnu.trove.list.array.TIntArrayList) PoissonFisherInformationData(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) TDoubleArrayList(gnu.trove.list.array.TDoubleArrayList) BasePoissonFisherInformation(uk.ac.sussex.gdsc.smlm.function.BasePoissonFisherInformation) Future(java.util.concurrent.Future)

Example 4 with PoissonFisherInformationData

use of uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData in project GDSC-SMLM by aherbert.

the class CameraModelFisherInformationAnalysis method save.

/**
 * Save the data to the cache.
 *
 * @param key the key
 * @param log10photons the log 10 photons
 * @param alpha the alpha
 */
private static void save(FiKey key, double[] log10photons, double[] alpha) {
    final CameraType type = key.getType();
    if (type.isFast()) {
        return;
    }
    PoissonFisherInformationData data = cache.get(key);
    if (data != null) {
        // This should only be called if new values have been computed.
        // so assume we must merge the lists.
        // Note: The lists must be sorted.
        final AlphaSample[] list1 = data.getAlphaSampleList().toArray(new AlphaSample[0]);
        final LocalList<AlphaSample> list = new LocalList<>(list1.length + log10photons.length);
        int i1 = 0;
        int i2 = 0;
        final AlphaSample.Builder a2 = AlphaSample.newBuilder();
        while (i1 < list1.length && i2 < log10photons.length) {
            final AlphaSample a1 = list1[i1];
            final double mean = log10photons[i2];
            if (a1.getLog10Mean() == mean) {
                list.add(a1);
                i1++;
                i2++;
            } else if (a1.getLog10Mean() < mean) {
                list.add(a1);
                i1++;
            } else {
                // (a1.getLog10Mean() > mean)
                a2.setLog10Mean(mean);
                a2.setAlpha(alpha[i2++]);
                list.add(a2.build());
            }
        }
        while (i1 < list1.length) {
            list.add(list1[i1++]);
        }
        while (i2 < log10photons.length) {
            a2.setLog10Mean(log10photons[i2]);
            a2.setAlpha(alpha[i2++]);
            list.add(a2.build());
        }
        final PoissonFisherInformationData.Builder b = data.toBuilder();
        b.clearAlphaSample();
        b.addAllAlphaSample(list);
        data = b.build();
    } else {
        final PoissonFisherInformationData.Builder b = PoissonFisherInformationData.newBuilder();
        final AlphaSample.Builder sample = AlphaSample.newBuilder();
        b.setType(key.type);
        b.setGain(key.gain);
        b.setNoise(key.noise);
        for (int i = 0; i < log10photons.length; i++) {
            sample.setLog10Mean(log10photons[i]);
            sample.setAlpha(alpha[i]);
            b.addAlphaSample(sample);
        }
        data = b.build();
    }
    cache.put(key, data);
    // Also save EM-CCD data to file
    if (type == CameraType.EM_CCD) {
        final int t = type.ordinal();
        // Get the EM-CCD keys
        final LocalList<FiKey> list = new LocalList<>(cache.size());
        for (final FiKey k : cache.keySet()) {
            if (k.type == t) {
                list.add(k);
            }
        }
        if (list.size() > MAX_DATA_TO_FILE) {
            // Sort by age - Youngest first
            list.sort((o1, o2) -> Long.compare(o2.timeStamp, o1.timeStamp));
        }
        final PoissonFisherInformationCache.Builder cacheData = PoissonFisherInformationCache.newBuilder();
        for (int i = Math.min(list.size(), MAX_DATA_TO_FILE); i-- > 0; ) {
            cacheData.addData(cache.get(list.unsafeGet(i)));
        }
        SettingsManager.writeSettings(cacheData);
    }
}
Also used : AlphaSample(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.AlphaSample) PoissonFisherInformationData(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) PoissonFisherInformationCache(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationCache)

Example 5 with PoissonFisherInformationData

use of uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData 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);
}
Also used : TDoubleArrayList(gnu.trove.list.array.TDoubleArrayList) BasePoissonFisherInformation(uk.ac.sussex.gdsc.smlm.function.BasePoissonFisherInformation) AlphaSample(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.AlphaSample) InterpolatedPoissonFisherInformation(uk.ac.sussex.gdsc.smlm.function.InterpolatedPoissonFisherInformation) PoissonFisherInformationData(uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData) HalfPoissonFisherInformation(uk.ac.sussex.gdsc.smlm.function.HalfPoissonFisherInformation)

Aggregations

PoissonFisherInformationData (uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationData)5 AlphaSample (uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.AlphaSample)4 TDoubleArrayList (gnu.trove.list.array.TDoubleArrayList)3 BasePoissonFisherInformation (uk.ac.sussex.gdsc.smlm.function.BasePoissonFisherInformation)3 LocalList (uk.ac.sussex.gdsc.core.utils.LocalList)2 TIntArrayList (gnu.trove.list.array.TIntArrayList)1 Plot (ij.gui.Plot)1 Future (java.util.concurrent.Future)1 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)1 NonBlockingExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog)1 Ticker (uk.ac.sussex.gdsc.core.logging.Ticker)1 PoissonFisherInformationCache (uk.ac.sussex.gdsc.smlm.data.config.FisherProtos.PoissonFisherInformationCache)1 HalfPoissonFisherInformation (uk.ac.sussex.gdsc.smlm.function.HalfPoissonFisherInformation)1 InterpolatedPoissonFisherInformation (uk.ac.sussex.gdsc.smlm.function.InterpolatedPoissonFisherInformation)1