Search in sources :

Example 1 with ClassificationResult

use of uk.ac.sussex.gdsc.core.match.ClassificationResult in project GDSC-SMLM by aherbert.

the class SpotFinderPreview method run.

private void run(ImageProcessor ip, MaximaSpotFilter filter) {
    if (refreshing) {
        return;
    }
    currentSlice = imp.getCurrentSlice();
    final Rectangle bounds = ip.getRoi();
    // Crop to the ROI
    FloatProcessor fp = ip.crop().toFloat(0, null);
    float[] data = (float[]) fp.getPixels();
    final int width = fp.getWidth();
    final int height = fp.getHeight();
    // Store the mean bias and gain of the region data.
    // This is used to correctly overlay the filtered data on the original image.
    double bias = 0;
    double gain = 1;
    boolean adjust = false;
    // Set weights
    final CameraModel cameraModel = fitConfig.getCameraModel();
    if (!(cameraModel instanceof FakePerPixelCameraModel)) {
        // This should be done on the normalised data
        final float[] w = cameraModel.getNormalisedWeights(bounds);
        filter.setWeights(w, width, height);
        data = data.clone();
        if (data.length < ip.getPixelCount()) {
            adjust = true;
            bias = MathUtils.sum(cameraModel.getBias(bounds)) / data.length;
            gain = MathUtils.sum(cameraModel.getGain(bounds)) / data.length;
        }
        cameraModel.removeBiasAndGain(bounds, data);
    }
    final Spot[] spots = filter.rank(data, width, height);
    data = filter.getPreprocessedData();
    final int size = spots.length;
    if (topNScrollBar != null) {
        topNScrollBar.setMaximum(size);
        selectScrollBar.setMaximum(size);
    }
    fp = new FloatProcessor(width, height, data);
    final FloatProcessor out = new FloatProcessor(ip.getWidth(), ip.getHeight());
    out.copyBits(ip, 0, 0, Blitter.COPY);
    if (adjust) {
        fp.multiply(gain);
        fp.add(bias);
    }
    out.insert(fp, bounds.x, bounds.y);
    final double min = fp.getMin();
    final double max = fp.getMax();
    out.setMinAndMax(min, max);
    final Overlay o = new Overlay();
    o.add(new ImageRoi(0, 0, out));
    if (label != null) {
        // Get results for frame
        final Coordinate[] actual = ResultsMatchCalculator.getCoordinates(actualCoordinates, imp.getCurrentSlice());
        final Coordinate[] predicted = new Coordinate[size];
        for (int i = 0; i < size; i++) {
            predicted[i] = new BasePoint(spots[i].x + bounds.x, spots[i].y + bounds.y);
        }
        // Compute assignments
        final LocalList<FractionalAssignment> fractionalAssignments = new LocalList<>(3 * predicted.length);
        final double matchDistance = settings.distance * fitConfig.getInitialPeakStdDev();
        final RampedScore score = RampedScore.of(matchDistance, matchDistance * settings.lowerDistance / 100, false);
        final double dmin = matchDistance * matchDistance;
        final int nActual = actual.length;
        final int nPredicted = predicted.length;
        for (int j = 0; j < nPredicted; j++) {
            // Centre in the middle of the pixel
            final float x = predicted[j].getX() + 0.5f;
            final float y = predicted[j].getY() + 0.5f;
            // Any spots that match
            for (int i = 0; i < nActual; i++) {
                final double dx = (x - actual[i].getX());
                final double dy = (y - actual[i].getY());
                final double d2 = dx * dx + dy * dy;
                if (d2 <= dmin) {
                    final double d = Math.sqrt(d2);
                    final double s = score.score(d);
                    if (s == 0) {
                        continue;
                    }
                    double distance = 1 - s;
                    if (distance == 0) {
                        // In the case of a match below the distance thresholds
                        // the distance will be 0. To distinguish between candidates all below
                        // the thresholds just take the closest.
                        // We know d2 is below dmin so we subtract the delta.
                        distance -= (dmin - d2);
                    }
                    // Store the match
                    fractionalAssignments.add(new ImmutableFractionalAssignment(i, j, distance, s));
                }
            }
        }
        final FractionalAssignment[] assignments = fractionalAssignments.toArray(new FractionalAssignment[0]);
        // Compute matches
        final RankedScoreCalculator calc = RankedScoreCalculator.create(assignments, nActual - 1, nPredicted - 1);
        final boolean save = settings.showTP || settings.showFP;
        final double[] calcScore = calc.score(nPredicted, settings.multipleMatches, save);
        final ClassificationResult result = RankedScoreCalculator.toClassificationResult(calcScore, nActual);
        // Compute AUC and max jaccard (and plot)
        final double[][] curve = RankedScoreCalculator.getPrecisionRecallCurve(assignments, nActual, nPredicted);
        final double[] precision = curve[0];
        final double[] recall = curve[1];
        final double[] jaccard = curve[2];
        final double auc = AucCalculator.auc(precision, recall);
        // Show scores
        final String scoreLabel = String.format("Slice=%d, AUC=%s, R=%s, Max J=%s", imp.getCurrentSlice(), MathUtils.rounded(auc), MathUtils.rounded(result.getRecall()), MathUtils.rounded(MathUtils.maxDefault(0, jaccard)));
        setLabel(scoreLabel);
        // Plot
        String title = TITLE + " Performance";
        Plot plot = new Plot(title, "Spot Rank", "");
        final double[] rank = SimpleArrayUtils.newArray(precision.length, 0, 1.0);
        plot.setLimits(0, nPredicted, 0, 1.05);
        plot.setColor(Color.blue);
        plot.addPoints(rank, precision, Plot.LINE);
        plot.setColor(Color.red);
        plot.addPoints(rank, recall, Plot.LINE);
        plot.setColor(Color.black);
        plot.addPoints(rank, jaccard, Plot.LINE);
        plot.setColor(Color.black);
        plot.addLabel(0, 0, scoreLabel);
        final WindowOrganiser windowOrganiser = new WindowOrganiser();
        ImageJUtils.display(title, plot, 0, windowOrganiser);
        title = TITLE + " Precision-Recall";
        plot = new Plot(title, "Recall", "Precision");
        plot.setLimits(0, 1, 0, 1.05);
        plot.setColor(Color.red);
        plot.addPoints(recall, precision, Plot.LINE);
        plot.drawLine(recall[recall.length - 1], precision[recall.length - 1], recall[recall.length - 1], 0);
        plot.setColor(Color.black);
        plot.addLabel(0, 0, scoreLabel);
        ImageJUtils.display(title, plot, 0, windowOrganiser);
        windowOrganiser.tile();
        // Create Rois for TP and FP
        if (save) {
            final double[] matchScore = RankedScoreCalculator.getMatchScore(calc.getScoredAssignments(), nPredicted);
            int matches = 0;
            for (int i = 0; i < matchScore.length; i++) {
                if (matchScore[i] != 0) {
                    matches++;
                }
            }
            if (settings.showTP) {
                final float[] x = new float[matches];
                final float[] y = new float[x.length];
                int count = 0;
                for (int i = 0; i < matchScore.length; i++) {
                    if (matchScore[i] != 0) {
                        final BasePoint p = (BasePoint) predicted[i];
                        x[count] = p.getX() + 0.5f;
                        y[count] = p.getY() + 0.5f;
                        count++;
                    }
                }
                addRoi(0, o, x, y, count, Color.green);
            }
            if (settings.showFP) {
                final float[] x = new float[nPredicted - matches];
                final float[] y = new float[x.length];
                int count = 0;
                for (int i = 0; i < matchScore.length; i++) {
                    if (matchScore[i] == 0) {
                        final BasePoint p = (BasePoint) predicted[i];
                        x[count] = p.getX() + 0.5f;
                        y[count] = p.getY() + 0.5f;
                        count++;
                    }
                }
                addRoi(0, o, x, y, count, Color.red);
            }
        }
    } else {
        final WindowOrganiser wo = new WindowOrganiser();
        // Option to show the number of neighbours within a set pixel box radius
        final int[] count = spotFilterHelper.countNeighbours(spots, width, height, settings.neighbourRadius);
        // Show as histogram the totals...
        new HistogramPlotBuilder(TITLE, StoredData.create(count), "Neighbours").setIntegerBins(true).setPlotLabel("Radius = " + settings.neighbourRadius).show(wo);
        // TODO - Draw n=0, n=1 on the image overlay
        final LUT lut = LutHelper.createLut(LutColour.FIRE_LIGHT);
        // These are copied by the ROI
        final float[] x = new float[1];
        final float[] y = new float[1];
        // Plot the intensity
        final double[] intensity = new double[size];
        final double[] rank = SimpleArrayUtils.newArray(size, 1, 1.0);
        final int top = (settings.topN > 0) ? settings.topN : size;
        final int size_1 = size - 1;
        for (int i = 0; i < size; i++) {
            intensity[i] = spots[i].intensity;
            if (i < top) {
                x[0] = spots[i].x + bounds.x + 0.5f;
                y[0] = spots[i].y + bounds.y + 0.5f;
                final Color c = LutHelper.getColour(lut, size_1 - i, size);
                addRoi(0, o, x, y, 1, c, 2, 1);
            }
        }
        final String title = TITLE + " Intensity";
        final Plot plot = new Plot(title, "Rank", "Intensity");
        plot.setColor(Color.blue);
        plot.addPoints(rank, intensity, Plot.LINE);
        if (settings.topN > 0 && settings.topN < size) {
            plot.setColor(Color.magenta);
            plot.drawLine(settings.topN, 0, settings.topN, intensity[settings.topN - 1]);
        }
        if (settings.select > 0 && settings.select < size) {
            plot.setColor(Color.yellow);
            final int index = settings.select - 1;
            final double in = intensity[index];
            plot.drawLine(settings.select, 0, settings.select, in);
            x[0] = spots[index].x + bounds.x + 0.5f;
            y[0] = spots[index].y + bounds.y + 0.5f;
            final Color c = LutHelper.getColour(lut, size_1 - settings.select, size);
            addRoi(0, o, x, y, 1, c, 3, 3);
            plot.setColor(Color.black);
            plot.addLabel(0, 0, "Selected spot intensity = " + MathUtils.rounded(in));
        }
        ImageJUtils.display(title, plot, 0, wo);
        wo.tile();
    }
    imp.setOverlay(o);
}
Also used : FakePerPixelCameraModel(uk.ac.sussex.gdsc.smlm.model.camera.FakePerPixelCameraModel) CameraModel(uk.ac.sussex.gdsc.smlm.model.camera.CameraModel) Spot(uk.ac.sussex.gdsc.smlm.filters.Spot) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) Rectangle(java.awt.Rectangle) HistogramPlotBuilder(uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder) RankedScoreCalculator(uk.ac.sussex.gdsc.core.match.RankedScoreCalculator) ImageRoi(ij.gui.ImageRoi) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) FractionalAssignment(uk.ac.sussex.gdsc.core.match.FractionalAssignment) ImmutableFractionalAssignment(uk.ac.sussex.gdsc.core.match.ImmutableFractionalAssignment) ImmutableFractionalAssignment(uk.ac.sussex.gdsc.core.match.ImmutableFractionalAssignment) Overlay(ij.gui.Overlay) FloatProcessor(ij.process.FloatProcessor) Plot(ij.gui.Plot) Color(java.awt.Color) ClassificationResult(uk.ac.sussex.gdsc.core.match.ClassificationResult) LUT(ij.process.LUT) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) FakePerPixelCameraModel(uk.ac.sussex.gdsc.smlm.model.camera.FakePerPixelCameraModel) Coordinate(uk.ac.sussex.gdsc.core.match.Coordinate) RampedScore(uk.ac.sussex.gdsc.core.utils.RampedScore)

Example 2 with ClassificationResult

use of uk.ac.sussex.gdsc.core.match.ClassificationResult in project GDSC-SMLM by aherbert.

the class FilterAnalysis method runAnalysis.

private int runAnalysis(Consumer<String> output, FilterSet filterSet, List<MemoryPeakResults> resultsList, int count, final int total) {
    final double[] xValues = (isHeadless) ? null : new double[filterSet.size()];
    final double[] yValues = (isHeadless) ? null : new double[filterSet.size()];
    int index = 0;
    filterSet.sort();
    // Track if all the filters are the same type. If so then we can calculate the sensitivity of
    // each parameter.
    String type = null;
    boolean allSameType = true;
    Filter maxFilter = null;
    double maxScore = -1;
    for (final Filter filter : filterSet.getFilters()) {
        if (count++ % 16 == 0) {
            IJ.showProgress(count, total);
        }
        final ClassificationResult s = runFilter(output, filter, resultsList);
        if (type == null) {
            type = filter.getType();
        } else if (!type.equals(filter.getType())) {
            allSameType = false;
        }
        final double jaccard = s.getJaccard();
        if (maxScore < jaccard) {
            maxScore = jaccard;
            maxFilter = filter;
        }
        if (xValues != null && yValues != null) {
            xValues[index] = filter.getNumericalValue();
            yValues[index++] = jaccard;
        }
    }
    if (allSameType && settings.calculateSensitivity) {
        final FilterScore filterScore = bestFilter.get(type);
        if (filterScore != null) {
            if (filterScore.score < maxScore) {
                filterScore.update(maxFilter, maxScore);
            }
        } else {
            bestFilter.put(type, new FilterScore(maxFilter, maxScore));
            bestFilterOrder.add(type);
        }
    }
    // Add spacer at end of each result set
    if (settings.showResultsTable) {
        output.accept("");
    }
    if (!isHeadless && settings.plotTopN > 0 && xValues != null) {
        // Check the xValues are unique. Since the filters have been sorted by their
        // numeric value we only need to compare adjacent entries.
        boolean unique = true;
        for (int ii = 0; ii < xValues.length - 1; ii++) {
            if (xValues[ii] == xValues[ii + 1]) {
                unique = false;
                break;
            }
        }
        String xAxisName = filterSet.getValueName();
        // Check the values all refer to the same property
        for (final Filter filter : filterSet.getFilters()) {
            if (!xAxisName.equals(filter.getNumericalValueName())) {
                unique = false;
                break;
            }
        }
        if (!unique) {
            // If not unique then renumber them and use an arbitrary label
            xAxisName = "Filter";
            for (int ii = 0; ii < xValues.length; ii++) {
                xValues[ii] = ii + 1.0;
            }
        }
        final String title = filterSet.getName();
        // Check if a previous filter set had the same name, update if necessary
        final NamedPlot plot = getNamedPlot(title);
        if (plot == null) {
            plots.add(new NamedPlot(title, xAxisName, xValues, yValues));
        } else {
            plot.updateValues(xAxisName, xValues, yValues);
        }
        if (plots.size() > settings.plotTopN) {
            Collections.sort(plots, NamedPlot::compare);
            plots.remove(plots.size() - 1);
        }
    }
    return count;
}
Also used : Filter(uk.ac.sussex.gdsc.smlm.results.filter.Filter) AndFilter(uk.ac.sussex.gdsc.smlm.results.filter.AndFilter) PrecisionFilter(uk.ac.sussex.gdsc.smlm.results.filter.PrecisionFilter) SnrHysteresisFilter(uk.ac.sussex.gdsc.smlm.results.filter.SnrHysteresisFilter) WidthFilter(uk.ac.sussex.gdsc.smlm.results.filter.WidthFilter) SnrFilter(uk.ac.sussex.gdsc.smlm.results.filter.SnrFilter) OrFilter(uk.ac.sussex.gdsc.smlm.results.filter.OrFilter) PrecisionHysteresisFilter(uk.ac.sussex.gdsc.smlm.results.filter.PrecisionHysteresisFilter) TraceFilter(uk.ac.sussex.gdsc.smlm.results.filter.TraceFilter) ClassificationResult(uk.ac.sussex.gdsc.core.match.ClassificationResult)

Example 3 with ClassificationResult

use of uk.ac.sussex.gdsc.core.match.ClassificationResult in project GDSC-SMLM by aherbert.

the class FilterAnalysis method runFilter.

private ClassificationResult runFilter(Consumer<String> output, Filter filter, List<MemoryPeakResults> resultsList) {
    final ClassificationResult s = filter.score(resultsList);
    if (settings.showResultsTable) {
        final StringBuilder sb = new StringBuilder();
        sb.append(filter.getName()).append('\t');
        sb.append(s.getTruePositives() + s.getFalsePositives()).append('\t');
        sb.append(s.getTruePositives()).append('\t');
        sb.append(s.getFalsePositives()).append('\t');
        sb.append(s.getTrueNegatives()).append('\t');
        sb.append(s.getFalseNegatives()).append('\t');
        sb.append(s.getJaccard()).append('\t');
        sb.append(s.getPrecision()).append('\t');
        sb.append(s.getRecall()).append('\t');
        sb.append(s.getF1Score());
        output.accept(sb.toString());
    }
    return s;
}
Also used : ClassificationResult(uk.ac.sussex.gdsc.core.match.ClassificationResult)

Example 4 with ClassificationResult

use of uk.ac.sussex.gdsc.core.match.ClassificationResult in project GDSC-SMLM by aherbert.

the class FilterAnalysis method calculateSensitivity.

private void calculateSensitivity(List<MemoryPeakResults> resultsList) {
    if (!settings.calculateSensitivity) {
        return;
    }
    if (!bestFilter.isEmpty()) {
        IJ.showStatus("Calculating sensitivity ...");
        final Consumer<String> output = createSensitivityWindow();
        int currentIndex = 0;
        for (final String type : bestFilterOrder) {
            IJ.showProgress(currentIndex++, bestFilter.size());
            final Filter filter = bestFilter.get(type).filter;
            final ClassificationResult s = filter.score(resultsList);
            final String message = type + "\t\t\t" + MathUtils.rounded(s.getJaccard(), 4) + "\t\t" + MathUtils.rounded(s.getPrecision(), 4) + "\t\t" + MathUtils.rounded(s.getRecall(), 4);
            output.accept(message);
            // List all the parameters that can be adjusted.
            final int parameters = filter.getNumberOfParameters();
            for (int index = 0; index < parameters; index++) {
                // For each parameter compute as upward + downward delta and get the average gradient
                final Filter higher = filter.adjustParameter(index, settings.delta);
                final Filter lower = filter.adjustParameter(index, -settings.delta);
                final ClassificationResult sHigher = higher.score(resultsList);
                final ClassificationResult sLower = lower.score(resultsList);
                final StringBuilder sb = new StringBuilder();
                sb.append('\t').append(filter.getParameterName(index)).append('\t');
                sb.append(MathUtils.rounded(filter.getParameterValue(index), 4)).append('\t');
                final double dx1 = higher.getParameterValue(index) - filter.getParameterValue(index);
                final double dx2 = filter.getParameterValue(index) - lower.getParameterValue(index);
                addSensitivityScore(sb, s.getJaccard(), sHigher.getJaccard(), sLower.getJaccard(), dx1, dx2);
                addSensitivityScore(sb, s.getPrecision(), sHigher.getPrecision(), sLower.getPrecision(), dx1, dx2);
                addSensitivityScore(sb, s.getRecall(), sHigher.getRecall(), sLower.getRecall(), dx1, dx2);
                output.accept(sb.toString());
            }
        }
        output.accept("-=-=-=-");
        ImageJUtils.finished();
    }
}
Also used : Filter(uk.ac.sussex.gdsc.smlm.results.filter.Filter) AndFilter(uk.ac.sussex.gdsc.smlm.results.filter.AndFilter) PrecisionFilter(uk.ac.sussex.gdsc.smlm.results.filter.PrecisionFilter) SnrHysteresisFilter(uk.ac.sussex.gdsc.smlm.results.filter.SnrHysteresisFilter) WidthFilter(uk.ac.sussex.gdsc.smlm.results.filter.WidthFilter) SnrFilter(uk.ac.sussex.gdsc.smlm.results.filter.SnrFilter) OrFilter(uk.ac.sussex.gdsc.smlm.results.filter.OrFilter) PrecisionHysteresisFilter(uk.ac.sussex.gdsc.smlm.results.filter.PrecisionHysteresisFilter) TraceFilter(uk.ac.sussex.gdsc.smlm.results.filter.TraceFilter) ClassificationResult(uk.ac.sussex.gdsc.core.match.ClassificationResult)

Example 5 with ClassificationResult

use of uk.ac.sussex.gdsc.core.match.ClassificationResult in project GDSC-SMLM by aherbert.

the class BenchmarkFilterAnalysis method createResult.

private StringBuilder createResult(DirectFilter filter, FractionClassificationResult result, String resultsPrefix2) {
    final StringBuilder sb = new StringBuilder(resultsPrefix);
    sb.append(filter.getName()).append(resultsPrefix2).append(fitResultData.resultsPrefix3);
    int index = 0;
    // Integer results
    if (settings.requireIntegerResults) {
        final ClassificationResult r2 = createIntegerResult(result);
        add(sb, r2.getTruePositives(), index++);
        add(sb, r2.getFalsePositives(), index++);
        add(sb, r2.getFalseNegatives(), index++);
        add(sb, r2.getPrecision(), index++);
        add(sb, r2.getRecall(), index++);
        add(sb, r2.getF1Score(), index++);
        add(sb, r2.getJaccard(), index++);
    } else {
        index += 7;
    }
    addCount(sb, result.getTruePositives(), index++);
    addCount(sb, result.getFalsePositives(), index++);
    addCount(sb, result.getFalseNegatives(), index++);
    add(sb, result.getPrecision(), index++);
    add(sb, result.getRecall(), index++);
    add(sb, result.getF1Score(), index++);
    add(sb, result.getJaccard(), index);
    return sb;
}
Also used : FractionClassificationResult(uk.ac.sussex.gdsc.core.match.FractionClassificationResult) ClassificationResult(uk.ac.sussex.gdsc.core.match.ClassificationResult)

Aggregations

ClassificationResult (uk.ac.sussex.gdsc.core.match.ClassificationResult)9 FractionClassificationResult (uk.ac.sussex.gdsc.core.match.FractionClassificationResult)5 XStreamOmitField (com.thoughtworks.xstream.annotations.XStreamOmitField)3 List (java.util.List)3 Nullable (uk.ac.sussex.gdsc.core.annotation.Nullable)3 SimpleArrayUtils (uk.ac.sussex.gdsc.core.utils.SimpleArrayUtils)3 Chromosome (uk.ac.sussex.gdsc.smlm.ga.Chromosome)3 MemoryPeakResults (uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)3 PeakResult (uk.ac.sussex.gdsc.smlm.results.PeakResult)3 Counter (uk.ac.sussex.gdsc.smlm.results.count.Counter)3 FrameCounter (uk.ac.sussex.gdsc.smlm.results.count.FrameCounter)3 PeakResultProcedure (uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure)3 AndFilter (uk.ac.sussex.gdsc.smlm.results.filter.AndFilter)2 Filter (uk.ac.sussex.gdsc.smlm.results.filter.Filter)2 OrFilter (uk.ac.sussex.gdsc.smlm.results.filter.OrFilter)2 PrecisionFilter (uk.ac.sussex.gdsc.smlm.results.filter.PrecisionFilter)2 PrecisionHysteresisFilter (uk.ac.sussex.gdsc.smlm.results.filter.PrecisionHysteresisFilter)2 SnrFilter (uk.ac.sussex.gdsc.smlm.results.filter.SnrFilter)2 SnrHysteresisFilter (uk.ac.sussex.gdsc.smlm.results.filter.SnrHysteresisFilter)2 TraceFilter (uk.ac.sussex.gdsc.smlm.results.filter.TraceFilter)2