Search in sources :

Example 1 with IntDoubleMinHeap

use of uk.ac.sussex.gdsc.core.trees.heaps.IntDoubleMinHeap in project GDSC-SMLM by aherbert.

the class FailCountManager method analyseData.

private void analyseData() {
    final LocalList<FailCountData> failCountData = failCountDataRef.get();
    if (failCountData.isEmpty()) {
        IJ.error(TITLE, "No fail count data in memory");
        return;
    }
    if (!showAnalysisDialog()) {
        return;
    }
    final int maxCons = getMaxConsecutiveFailCount(failCountData);
    final int maxFail = getMaxFailCount(failCountData);
    // Create a set of fail counters
    final LocalList<FailCounter> counters = new LocalList<>();
    final TByteArrayList type = new TByteArrayList();
    for (int i = 0; i <= maxCons; i++) {
        counters.add(ConsecutiveFailCounter.create(i));
    }
    fill(type, counters, 0);
    // The other counters are user configured.
    // Ideally this would be a search to optimise the best parameters
    // for each counter as any enumeration may be way off the mark.
    // Note that 0 failures in a window can be scored using the consecutive fail counter.
    int max = Math.min(maxFail, settings.getRollingCounterMaxAllowedFailures());
    for (int fail = MathUtils.clip(1, maxFail, settings.getRollingCounterMinAllowedFailures()); fail <= max; fail++) {
        // Note that n-1 failures in window n can be scored using the consecutive fail counter.
        for (int window = Math.max(fail + 2, settings.getRollingCounterMinWindow()); window <= settings.getRollingCounterMaxWindow(); window++) {
            counters.add(RollingWindowFailCounter.create(fail, window));
        }
        switch(checkCounters(counters)) {
            case ANALYSE:
                break;
            case CONTINUE:
                break;
            case RETURN:
                return;
            default:
                throw new IllegalStateException();
        }
    }
    fill(type, counters, 1);
    max = Math.min(maxFail, settings.getWeightedCounterMaxAllowedFailures());
    for (int fail = MathUtils.min(maxFail, settings.getWeightedCounterMinAllowedFailures()); fail <= max; fail++) {
        for (int w = settings.getWeightedCounterMinPassDecrement(); w <= settings.getWeightedCounterMaxPassDecrement(); w++) {
            counters.add(WeightedFailCounter.create(fail, 1, w));
        }
        switch(checkCounters(counters)) {
            case ANALYSE:
                break;
            case CONTINUE:
                break;
            case RETURN:
                return;
            default:
                throw new IllegalStateException();
        }
    }
    fill(type, counters, 2);
    max = Math.min(maxFail, settings.getResettingCounterMaxAllowedFailures());
    for (int fail = MathUtils.min(maxFail, settings.getResettingCounterMinAllowedFailures()); fail <= max; fail++) {
        for (double f = settings.getResettingCounterMinResetFraction(); f <= settings.getResettingCounterMaxResetFraction(); f += settings.getResettingCounterIncResetFraction()) {
            counters.add(ResettingFailCounter.create(fail, f));
        }
        switch(checkCounters(counters)) {
            case ANALYSE:
                break;
            case CONTINUE:
                break;
            case RETURN:
                return;
            default:
                throw new IllegalStateException();
        }
    }
    fill(type, counters, 3);
    for (int count = settings.getPassRateCounterMinAllowedCounts(); count <= settings.getPassRateCounterMaxAllowedCounts(); count++) {
        for (double f = settings.getPassRateCounterMinPassRate(); f <= settings.getPassRateCounterMaxPassRate(); f += settings.getPassRateCounterIncPassRate()) {
            counters.add(PassRateFailCounter.create(count, f));
        }
        switch(checkCounters(counters)) {
            case ANALYSE:
                break;
            case CONTINUE:
                break;
            case RETURN:
                return;
            default:
                throw new IllegalStateException();
        }
    }
    fill(type, counters, 4);
    counters.trimToSize();
    // Score each of a set of standard fail counters against each frame using how
    // close they are to the target.
    final double[] score = new double[counters.size()];
    final double targetPassFraction = settings.getTargetPassFraction();
    final int nThreads = Prefs.getThreads();
    final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
    final LocalList<Future<?>> futures = new LocalList<>(nThreads);
    final Ticker ticker = ImageJUtils.createTicker(failCountData.size(), nThreads);
    IJ.showStatus("Analysing " + TextUtils.pleural(counters.size(), "counter"));
    for (int i = 0; i < failCountData.size(); i++) {
        final FailCountData data = failCountData.unsafeGet(i);
        futures.add(executor.submit(() -> {
            if (IJ.escapePressed()) {
                return;
            }
            // TODO - Ideally this plugin should be run on benchmark data with ground truth.
            // The target could be to ensure all the correct results are fit
            // and false positives are excluded from incrementing the pass counter.
            // This could be done by saving the results from a benchmarking scoring
            // plugin to memory as the current dataset.
            data.initialiseAnalysis(targetPassFraction);
            // Score in blocks and then do a synchronized write to the combined score
            final Thread t = Thread.currentThread();
            final double[] s = new double[8192];
            int index = 0;
            while (index < counters.size()) {
                if (t.isInterrupted()) {
                    break;
                }
                final int block = Math.min(8192, counters.size() - index);
                for (int j = 0; j < block; j++) {
                    final FailCounter counter = counters.unsafeGet(index + j).newCounter();
                    s[j] = data.score(counter);
                }
                // Write to the combined score
                synchronized (score) {
                    for (int j = 0; j < block; j++) {
                        score[index + j] += s[j];
                    }
                }
                index += block;
            }
            ticker.tick();
        }));
    }
    executor.shutdown();
    ConcurrencyUtils.waitForCompletionUnchecked(futures);
    IJ.showProgress(1);
    if (IJ.escapePressed()) {
        IJ.showStatus("");
        IJ.error(TITLE, "Cancelled analysis");
        return;
    }
    IJ.showStatus("Summarising results ...");
    // TODO - check if the top filter is at the bounds of the range
    final int minIndex = SimpleArrayUtils.findMinIndex(score);
    ImageJUtils.log(TITLE + " Analysis : Best counter = %s (Score = %f)", counters.unsafeGet(minIndex).getDescription(), score[minIndex]);
    // Show a table of results for the top N for each type
    final int topN = Math.min(settings.getTableTopN(), score.length);
    if (topN > 0) {
        final byte[] types = type.toArray();
        final byte maxType = types[types.length - 1];
        final TextWindow resultsWindow = createTable();
        for (byte b = 0; b <= maxType; b++) {
            int[] indices;
            // Use a heap to avoid a full sort
            final IntDoubleMinHeap heap = new IntDoubleMinHeap(topN);
            for (int i = 0; i < score.length; i++) {
                if (types[i] == b) {
                    heap.offer(score[i], i);
                }
            }
            if (heap.getSize() == 0) {
                continue;
            }
            indices = heap.getItems();
            // Ensure sorted
            SortUtils.sortIndices(indices, score, false);
            final StringBuilder sb = new StringBuilder();
            try (final BufferedTextWindow tw = new BufferedTextWindow(resultsWindow)) {
                for (int i = 0; i < topN; i++) {
                    sb.setLength(0);
                    final int j = indices[i];
                    sb.append(i + 1).append('\t');
                    sb.append(counters.unsafeGet(j).getDescription()).append('\t');
                    sb.append(score[j]);
                    tw.append(sb.toString());
                }
            }
        }
    }
    // TODO - Save the best fail counter to the current fit configuration.
    IJ.showStatus("");
}
Also used : RollingWindowFailCounter(uk.ac.sussex.gdsc.smlm.results.count.RollingWindowFailCounter) FailCounter(uk.ac.sussex.gdsc.smlm.results.count.FailCounter) ResettingFailCounter(uk.ac.sussex.gdsc.smlm.results.count.ResettingFailCounter) ConsecutiveFailCounter(uk.ac.sussex.gdsc.smlm.results.count.ConsecutiveFailCounter) WeightedFailCounter(uk.ac.sussex.gdsc.smlm.results.count.WeightedFailCounter) PassRateFailCounter(uk.ac.sussex.gdsc.smlm.results.count.PassRateFailCounter) TByteArrayList(gnu.trove.list.array.TByteArrayList) BufferedTextWindow(uk.ac.sussex.gdsc.core.ij.BufferedTextWindow) Ticker(uk.ac.sussex.gdsc.core.logging.Ticker) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) TextWindow(ij.text.TextWindow) BufferedTextWindow(uk.ac.sussex.gdsc.core.ij.BufferedTextWindow) IntDoubleMinHeap(uk.ac.sussex.gdsc.core.trees.heaps.IntDoubleMinHeap) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future)

Aggregations

TByteArrayList (gnu.trove.list.array.TByteArrayList)1 TextWindow (ij.text.TextWindow)1 ExecutorService (java.util.concurrent.ExecutorService)1 Future (java.util.concurrent.Future)1 BufferedTextWindow (uk.ac.sussex.gdsc.core.ij.BufferedTextWindow)1 Ticker (uk.ac.sussex.gdsc.core.logging.Ticker)1 IntDoubleMinHeap (uk.ac.sussex.gdsc.core.trees.heaps.IntDoubleMinHeap)1 LocalList (uk.ac.sussex.gdsc.core.utils.LocalList)1 ConsecutiveFailCounter (uk.ac.sussex.gdsc.smlm.results.count.ConsecutiveFailCounter)1 FailCounter (uk.ac.sussex.gdsc.smlm.results.count.FailCounter)1 PassRateFailCounter (uk.ac.sussex.gdsc.smlm.results.count.PassRateFailCounter)1 ResettingFailCounter (uk.ac.sussex.gdsc.smlm.results.count.ResettingFailCounter)1 RollingWindowFailCounter (uk.ac.sussex.gdsc.smlm.results.count.RollingWindowFailCounter)1 WeightedFailCounter (uk.ac.sussex.gdsc.smlm.results.count.WeightedFailCounter)1