Search in sources :

Example 1 with MultiFilter2

use of gdsc.smlm.results.filter.MultiFilter2 in project GDSC-SMLM by aherbert.

the class FreeFilterResults method logDemoFilters.

public static void logDemoFilters(String title) {
    comment(title + " example filters");
    IJ.log("");
    comment("Filters are described using XML");
    comment("Multiple filters can be combined using AND/OR filters");
    IJ.log("");
    comment("Single filters");
    IJ.log("");
    demo(new WidthFilter(2));
    demo(new WidthFilter2(0.7, 2));
    demo(new SBRFilter(15));
    demo(new ShiftFilter(0.7));
    demo(new EShiftFilter(0.8));
    demo(new SignalFilter(1000));
    demo(new SNRFilter(10));
    demo(new SNRFilter2(10, 0.7, 2));
    demo(new ANRFilter(11));
    demo(new ANRFilter2(11, 0.75, 1.95));
    demo(new PrecisionFilter(30));
    demo(new PrecisionFilter2(30));
    demo(new SNRHysteresisFilter(50, 1, 2, 1, 10, 20));
    demo(new PrecisionHysteresisFilter(2, 0, 1, 0, 20, 30));
    demo(new TraceFilter(0.5, 1));
    demo(new CoordinateFilter(15.5f, 234.5f, 80.99f, 133f));
    demo(new MultiFilter(30, 45f, 0.7, 1.5, 0.5, 0.6, 45));
    demo(new MultiFilter2(30, 45f, 0.7, 1.5, 0.5, 0.6, 45));
    demo(new MultiHysteresisFilter(2, 0, 1, 0, 20, 10, 40f, 20f, 0.8, 0.2, 1.2, 0.4, 0.3, 0.8, 20, 30));
    demo(new MultiHysteresisFilter2(2, 0, 2, 1, 20, 10, 40f, 20f, 0.8, 0.2, 1.2, 0.4, 0.3, 0.8, 20, 30));
    comment("Combined filters");
    IJ.log("");
    demo(new AndFilter(new SNRFilter(10), new WidthFilter(2)));
    demo(new OrFilter(new SNRFilter(10), new PrecisionFilter(30)));
    demo(new OrFilter(new AndFilter(new SNRFilter(10), new PrecisionFilter(30)), new TraceFilter(0.5, 1)));
}
Also used : PrecisionFilter(gdsc.smlm.results.filter.PrecisionFilter) MultiHysteresisFilter2(gdsc.smlm.results.filter.MultiHysteresisFilter2) OrFilter(gdsc.smlm.results.filter.OrFilter) MultiFilter(gdsc.smlm.results.filter.MultiFilter) WidthFilter(gdsc.smlm.results.filter.WidthFilter) SNRFilter2(gdsc.smlm.results.filter.SNRFilter2) SBRFilter(gdsc.smlm.results.filter.SBRFilter) AndFilter(gdsc.smlm.results.filter.AndFilter) EShiftFilter(gdsc.smlm.results.filter.EShiftFilter) ANRFilter(gdsc.smlm.results.filter.ANRFilter) WidthFilter2(gdsc.smlm.results.filter.WidthFilter2) SNRHysteresisFilter(gdsc.smlm.results.filter.SNRHysteresisFilter) MultiFilter2(gdsc.smlm.results.filter.MultiFilter2) SNRFilter(gdsc.smlm.results.filter.SNRFilter) PrecisionHysteresisFilter(gdsc.smlm.results.filter.PrecisionHysteresisFilter) PrecisionFilter2(gdsc.smlm.results.filter.PrecisionFilter2) TraceFilter(gdsc.smlm.results.filter.TraceFilter) SignalFilter(gdsc.smlm.results.filter.SignalFilter) ANRFilter2(gdsc.smlm.results.filter.ANRFilter2) CoordinateFilter(gdsc.smlm.results.filter.CoordinateFilter) EShiftFilter(gdsc.smlm.results.filter.EShiftFilter) ShiftFilter(gdsc.smlm.results.filter.ShiftFilter) MultiHysteresisFilter(gdsc.smlm.results.filter.MultiHysteresisFilter)

Example 2 with MultiFilter2

use of gdsc.smlm.results.filter.MultiFilter2 in project GDSC-SMLM by aherbert.

the class FitConfiguration method getDefaultSmartFilter.

/**
	 * This returns the representation of this object as a smart filter. This ignores any current smart filter and
	 * only uses the standard filtering settings.
	 * 
	 * @return the smart filter if using this object as a smart filter.
	 */
public DirectFilter getDefaultSmartFilter() {
    double signal = getMinPhotons();
    float snr = (float) getSignalStrength();
    double minWidth = getMinWidthFactor();
    double maxWidth = getWidthFactor();
    double shift = getCoordinateShiftFactor();
    double eshift = 0;
    double precision = getPrecisionThreshold();
    DirectFilter f = (isPrecisionUsingBackground()) ? new MultiFilter2(signal, snr, minWidth, maxWidth, shift, eshift, precision) : new MultiFilter(signal, snr, minWidth, maxWidth, shift, eshift, precision);
    return f;
}
Also used : MultiFilter2(gdsc.smlm.results.filter.MultiFilter2) IDirectFilter(gdsc.smlm.results.filter.IDirectFilter) DirectFilter(gdsc.smlm.results.filter.DirectFilter) MultiFilter(gdsc.smlm.results.filter.MultiFilter)

Example 3 with MultiFilter2

use of gdsc.smlm.results.filter.MultiFilter2 in project GDSC-SMLM by aherbert.

the class BenchmarkSpotFit method summariseResults.

private void summariseResults(TIntObjectHashMap<FilterCandidates> filterCandidates, long runTime, final PreprocessedPeakResult[] preprocessedPeakResults, int nUniqueIDs) {
    createTable();
    // Summarise the fitting results. N fits, N failures. 
    // Optimal match statistics if filtering is perfect (since fitting is not perfect).
    StoredDataStatistics distanceStats = new StoredDataStatistics();
    StoredDataStatistics depthStats = new StoredDataStatistics();
    // Get stats for all fitted results and those that match 
    // Signal, SNR, Width, xShift, yShift, Precision
    createFilterCriteria();
    StoredDataStatistics[][] stats = new StoredDataStatistics[3][filterCriteria.length];
    for (int i = 0; i < stats.length; i++) for (int j = 0; j < stats[i].length; j++) stats[i][j] = new StoredDataStatistics();
    final double nmPerPixel = simulationParameters.a;
    double tp = 0, fp = 0;
    int failcTP = 0, failcFP = 0;
    int cTP = 0, cFP = 0;
    int[] singleStatus = null, multiStatus = null, doubletStatus = null, multiDoubletStatus = null;
    singleStatus = new int[FitStatus.values().length];
    multiStatus = new int[singleStatus.length];
    doubletStatus = new int[singleStatus.length];
    multiDoubletStatus = new int[singleStatus.length];
    // Easier to materialise the values since we have a lot of non final variables to manipulate
    final int[] frames = new int[filterCandidates.size()];
    final FilterCandidates[] candidates = new FilterCandidates[filterCandidates.size()];
    final int[] counter = new int[1];
    filterCandidates.forEachEntry(new TIntObjectProcedure<FilterCandidates>() {

        public boolean execute(int a, FilterCandidates b) {
            frames[counter[0]] = a;
            candidates[counter[0]] = b;
            counter[0]++;
            return true;
        }
    });
    for (FilterCandidates result : candidates) {
        // Count the number of fit results that matched (tp) and did not match (fp)
        tp += result.tp;
        fp += result.fp;
        for (int i = 0; i < result.fitResult.length; i++) {
            if (result.spots[i].match)
                cTP++;
            else
                cFP++;
            final MultiPathFitResult fitResult = result.fitResult[i];
            if (singleStatus != null && result.spots[i].match) {
                // Debugging reasons for fit failure
                addStatus(singleStatus, fitResult.getSingleFitResult());
                addStatus(multiStatus, fitResult.getMultiFitResult());
                addStatus(doubletStatus, fitResult.getDoubletFitResult());
                addStatus(multiDoubletStatus, fitResult.getMultiDoubletFitResult());
            }
            if (noMatch(fitResult)) {
                if (result.spots[i].match)
                    failcTP++;
                else
                    failcFP++;
            }
            // We have multi-path results.
            // We want statistics for:
            // [0] all fitted spots
            // [1] fitted spots that match a result
            // [2] fitted spots that do not match a result
            addToStats(fitResult.getSingleFitResult(), stats);
            addToStats(fitResult.getMultiFitResult(), stats);
            addToStats(fitResult.getDoubletFitResult(), stats);
            addToStats(fitResult.getMultiDoubletFitResult(), stats);
        }
        // Statistics on spots that fit an actual result
        for (int i = 0; i < result.match.length; i++) {
            if (!result.match[i].isFitResult())
                // For now just ignore the candidates that matched
                continue;
            FitMatch fitMatch = (FitMatch) result.match[i];
            distanceStats.add(fitMatch.d * nmPerPixel);
            depthStats.add(fitMatch.z * nmPerPixel);
        }
    }
    // Store data for computing correlation
    double[] i1 = new double[depthStats.getN()];
    double[] i2 = new double[i1.length];
    double[] is = new double[i1.length];
    int ci = 0;
    for (FilterCandidates result : candidates) {
        for (int i = 0; i < result.match.length; i++) {
            if (!result.match[i].isFitResult())
                // For now just ignore the candidates that matched
                continue;
            FitMatch fitMatch = (FitMatch) result.match[i];
            ScoredSpot spot = result.spots[fitMatch.i];
            i1[ci] = fitMatch.predictedSignal;
            i2[ci] = fitMatch.actualSignal;
            is[ci] = spot.spot.intensity;
            ci++;
        }
    }
    // We want to compute the Jaccard against the spot metric
    // Filter the results using the multi-path filter
    ArrayList<MultiPathFitResults> multiPathResults = new ArrayList<MultiPathFitResults>(filterCandidates.size());
    for (int i = 0; i < frames.length; i++) {
        int frame = frames[i];
        MultiPathFitResult[] multiPathFitResults = candidates[i].fitResult;
        int totalCandidates = candidates[i].spots.length;
        int nActual = actualCoordinates.get(frame).size();
        multiPathResults.add(new MultiPathFitResults(frame, multiPathFitResults, totalCandidates, nActual));
    }
    // Score the results and count the number returned
    List<FractionalAssignment[]> assignments = new ArrayList<FractionalAssignment[]>();
    final TIntHashSet set = new TIntHashSet(nUniqueIDs);
    FractionScoreStore scoreStore = new FractionScoreStore() {

        public void add(int uniqueId) {
            set.add(uniqueId);
        }
    };
    MultiPathFitResults[] multiResults = multiPathResults.toArray(new MultiPathFitResults[multiPathResults.size()]);
    // Filter with no filter
    MultiPathFilter mpf = new MultiPathFilter(new SignalFilter(0), null, multiFilter.residualsThreshold);
    FractionClassificationResult fractionResult = mpf.fractionScoreSubset(multiResults, Integer.MAX_VALUE, this.results.size(), assignments, scoreStore, CoordinateStoreFactory.create(imp.getWidth(), imp.getHeight(), fitConfig.getDuplicateDistance()));
    double nPredicted = fractionResult.getTP() + fractionResult.getFP();
    final double[][] matchScores = new double[set.size()][];
    int count = 0;
    for (int i = 0; i < assignments.size(); i++) {
        FractionalAssignment[] a = assignments.get(i);
        if (a == null)
            continue;
        for (int j = 0; j < a.length; j++) {
            final PreprocessedPeakResult r = ((PeakFractionalAssignment) a[j]).peakResult;
            set.remove(r.getUniqueId());
            final double precision = Math.sqrt(r.getLocationVariance());
            final double signal = r.getSignal();
            final double snr = r.getSNR();
            final double width = r.getXSDFactor();
            final double xShift = r.getXRelativeShift2();
            final double yShift = r.getYRelativeShift2();
            // Since these two are combined for filtering and the max is what matters.
            final double shift = (xShift > yShift) ? Math.sqrt(xShift) : Math.sqrt(yShift);
            final double eshift = Math.sqrt(xShift + yShift);
            final double[] score = new double[8];
            score[FILTER_SIGNAL] = signal;
            score[FILTER_SNR] = snr;
            score[FILTER_MIN_WIDTH] = width;
            score[FILTER_MAX_WIDTH] = width;
            score[FILTER_SHIFT] = shift;
            score[FILTER_ESHIFT] = eshift;
            score[FILTER_PRECISION] = precision;
            score[FILTER_PRECISION + 1] = a[j].getScore();
            matchScores[count++] = score;
        }
    }
    // Add the rest
    set.forEach(new CustomTIntProcedure(count) {

        public boolean execute(int uniqueId) {
            // This should not be null or something has gone wrong
            PreprocessedPeakResult r = preprocessedPeakResults[uniqueId];
            if (r == null)
                throw new RuntimeException("Missing result: " + uniqueId);
            final double precision = Math.sqrt(r.getLocationVariance());
            final double signal = r.getSignal();
            final double snr = r.getSNR();
            final double width = r.getXSDFactor();
            final double xShift = r.getXRelativeShift2();
            final double yShift = r.getYRelativeShift2();
            // Since these two are combined for filtering and the max is what matters.
            final double shift = (xShift > yShift) ? Math.sqrt(xShift) : Math.sqrt(yShift);
            final double eshift = Math.sqrt(xShift + yShift);
            final double[] score = new double[8];
            score[FILTER_SIGNAL] = signal;
            score[FILTER_SNR] = snr;
            score[FILTER_MIN_WIDTH] = width;
            score[FILTER_MAX_WIDTH] = width;
            score[FILTER_SHIFT] = shift;
            score[FILTER_ESHIFT] = eshift;
            score[FILTER_PRECISION] = precision;
            matchScores[c++] = score;
            return true;
        }
    });
    // Debug the reasons the fit failed
    if (singleStatus != null) {
        String name = PeakFit.getSolverName(fitConfig);
        if (fitConfig.getFitSolver() == FitSolver.MLE && fitConfig.isModelCamera())
            name += " Camera";
        System.out.println("Failure counts: " + name);
        printFailures("Single", singleStatus);
        printFailures("Multi", multiStatus);
        printFailures("Doublet", doubletStatus);
        printFailures("Multi doublet", multiDoubletStatus);
    }
    StringBuilder sb = new StringBuilder(300);
    // Add information about the simulation
    //(simulationParameters.minSignal + simulationParameters.maxSignal) * 0.5;
    final double signal = simulationParameters.signalPerFrame;
    final int n = results.size();
    sb.append(imp.getStackSize()).append("\t");
    final int w = imp.getWidth();
    final int h = imp.getHeight();
    sb.append(w).append("\t");
    sb.append(h).append("\t");
    sb.append(n).append("\t");
    double density = ((double) n / imp.getStackSize()) / (w * h) / (simulationParameters.a * simulationParameters.a / 1e6);
    sb.append(Utils.rounded(density)).append("\t");
    sb.append(Utils.rounded(signal)).append("\t");
    sb.append(Utils.rounded(simulationParameters.s)).append("\t");
    sb.append(Utils.rounded(simulationParameters.a)).append("\t");
    sb.append(Utils.rounded(simulationParameters.depth)).append("\t");
    sb.append(simulationParameters.fixedDepth).append("\t");
    sb.append(Utils.rounded(simulationParameters.gain)).append("\t");
    sb.append(Utils.rounded(simulationParameters.readNoise)).append("\t");
    sb.append(Utils.rounded(simulationParameters.b)).append("\t");
    sb.append(Utils.rounded(simulationParameters.b2)).append("\t");
    // Compute the noise
    double noise = simulationParameters.b2;
    if (simulationParameters.emCCD) {
        // The b2 parameter was computed without application of the EM-CCD noise factor of 2.
        //final double b2 = backgroundVariance + readVariance
        //                = simulationParameters.b + readVariance
        // This should be applied only to the background variance.
        final double readVariance = noise - simulationParameters.b;
        noise = simulationParameters.b * 2 + readVariance;
    }
    if (simulationParameters.fullSimulation) {
    // The total signal is spread over frames
    }
    sb.append(Utils.rounded(signal / Math.sqrt(noise))).append("\t");
    sb.append(Utils.rounded(simulationParameters.s / simulationParameters.a)).append("\t");
    sb.append(spotFilter.getDescription());
    // nP and nN is the fractional score of the spot candidates 
    addCount(sb, nP + nN);
    addCount(sb, nP);
    addCount(sb, nN);
    addCount(sb, fP);
    addCount(sb, fN);
    String name = PeakFit.getSolverName(fitConfig);
    if (fitConfig.getFitSolver() == FitSolver.MLE && fitConfig.isModelCamera())
        name += " Camera";
    add(sb, name);
    add(sb, config.getFitting());
    resultPrefix = sb.toString();
    // Q. Should I add other fit configuration here?
    // The fraction of positive and negative candidates that were included
    add(sb, (100.0 * cTP) / nP);
    add(sb, (100.0 * cFP) / nN);
    // Score the fitting results compared to the original simulation.
    // Score the candidate selection:
    add(sb, cTP + cFP);
    add(sb, cTP);
    add(sb, cFP);
    // TP are all candidates that can be matched to a spot
    // FP are all candidates that cannot be matched to a spot
    // FN = The number of missed spots
    FractionClassificationResult m = new FractionClassificationResult(cTP, cFP, 0, simulationParameters.molecules - cTP);
    add(sb, m.getRecall());
    add(sb, m.getPrecision());
    add(sb, m.getF1Score());
    add(sb, m.getJaccard());
    // Score the fitting results:
    add(sb, failcTP);
    add(sb, failcFP);
    // TP are all fit results that can be matched to a spot
    // FP are all fit results that cannot be matched to a spot
    // FN = The number of missed spots
    add(sb, tp);
    add(sb, fp);
    m = new FractionClassificationResult(tp, fp, 0, simulationParameters.molecules - tp);
    add(sb, m.getRecall());
    add(sb, m.getPrecision());
    add(sb, m.getF1Score());
    add(sb, m.getJaccard());
    // Do it again but pretend we can perfectly filter all the false positives
    //add(sb, tp);
    m = new FractionClassificationResult(tp, 0, 0, simulationParameters.molecules - tp);
    // Recall is unchanged
    // Precision will be 100%
    add(sb, m.getF1Score());
    add(sb, m.getJaccard());
    // The mean may be subject to extreme outliers so use the median
    double median = distanceStats.getMedian();
    add(sb, median);
    WindowOrganiser wo = new WindowOrganiser();
    String label = String.format("Recall = %s. n = %d. Median = %s nm. SD = %s nm", Utils.rounded(m.getRecall()), distanceStats.getN(), Utils.rounded(median), Utils.rounded(distanceStats.getStandardDeviation()));
    int id = Utils.showHistogram(TITLE, distanceStats, "Match Distance (nm)", 0, 0, 0, label);
    if (Utils.isNewWindow())
        wo.add(id);
    median = depthStats.getMedian();
    add(sb, median);
    // Sort by spot intensity and produce correlation
    int[] indices = Utils.newArray(i1.length, 0, 1);
    if (showCorrelation)
        Sort.sort(indices, is, rankByIntensity);
    double[] r = (showCorrelation) ? new double[i1.length] : null;
    double[] sr = (showCorrelation) ? new double[i1.length] : null;
    double[] rank = (showCorrelation) ? new double[i1.length] : null;
    ci = 0;
    FastCorrelator fastCorrelator = new FastCorrelator();
    ArrayList<Ranking> pc1 = new ArrayList<Ranking>();
    ArrayList<Ranking> pc2 = new ArrayList<Ranking>();
    for (int ci2 : indices) {
        fastCorrelator.add((long) Math.round(i1[ci2]), (long) Math.round(i2[ci2]));
        pc1.add(new Ranking(i1[ci2], ci));
        pc2.add(new Ranking(i2[ci2], ci));
        if (showCorrelation) {
            r[ci] = fastCorrelator.getCorrelation();
            sr[ci] = Correlator.correlation(rank(pc1), rank(pc2));
            if (rankByIntensity)
                rank[ci] = is[0] - is[ci];
            else
                rank[ci] = ci;
        }
        ci++;
    }
    final double pearsonCorr = fastCorrelator.getCorrelation();
    final double rankedCorr = Correlator.correlation(rank(pc1), rank(pc2));
    // Get the regression
    SimpleRegression regression = new SimpleRegression(false);
    for (int i = 0; i < pc1.size(); i++) regression.addData(pc1.get(i).value, pc2.get(i).value);
    //final double intercept = regression.getIntercept();
    final double slope = regression.getSlope();
    if (showCorrelation) {
        String title = TITLE + " Intensity";
        Plot plot = new Plot(title, "Candidate", "Spot");
        double[] limits1 = Maths.limits(i1);
        double[] limits2 = Maths.limits(i2);
        plot.setLimits(limits1[0], limits1[1], limits2[0], limits2[1]);
        label = String.format("Correlation=%s; Ranked=%s; Slope=%s", Utils.rounded(pearsonCorr), Utils.rounded(rankedCorr), Utils.rounded(slope));
        plot.addLabel(0, 0, label);
        plot.setColor(Color.red);
        plot.addPoints(i1, i2, Plot.DOT);
        if (slope > 1)
            plot.drawLine(limits1[0], limits1[0] * slope, limits1[1], limits1[1] * slope);
        else
            plot.drawLine(limits2[0] / slope, limits2[0], limits2[1] / slope, limits2[1]);
        PlotWindow pw = Utils.display(title, plot);
        if (Utils.isNewWindow())
            wo.add(pw);
        title = TITLE + " Correlation";
        plot = new Plot(title, "Spot Rank", "Correlation");
        double[] xlimits = Maths.limits(rank);
        double[] ylimits = Maths.limits(r);
        ylimits = Maths.limits(ylimits, sr);
        plot.setLimits(xlimits[0], xlimits[1], ylimits[0], ylimits[1]);
        plot.setColor(Color.red);
        plot.addPoints(rank, r, Plot.LINE);
        plot.setColor(Color.blue);
        plot.addPoints(rank, sr, Plot.LINE);
        plot.setColor(Color.black);
        plot.addLabel(0, 0, label);
        pw = Utils.display(title, plot);
        if (Utils.isNewWindow())
            wo.add(pw);
    }
    add(sb, pearsonCorr);
    add(sb, rankedCorr);
    add(sb, slope);
    label = String.format("n = %d. Median = %s nm", depthStats.getN(), Utils.rounded(median));
    id = Utils.showHistogram(TITLE, depthStats, "Match Depth (nm)", 0, 1, 0, label);
    if (Utils.isNewWindow())
        wo.add(id);
    // Plot histograms of the stats on the same window
    double[] lower = new double[filterCriteria.length];
    double[] upper = new double[lower.length];
    min = new double[lower.length];
    max = new double[lower.length];
    for (int i = 0; i < stats[0].length; i++) {
        double[] limits = showDoubleHistogram(stats, i, wo, matchScores, nPredicted);
        lower[i] = limits[0];
        upper[i] = limits[1];
        min[i] = limits[2];
        max[i] = limits[3];
    }
    // Reconfigure some of the range limits
    // Make this a bit bigger
    upper[FILTER_SIGNAL] *= 2;
    // Make this a bit bigger
    upper[FILTER_SNR] *= 2;
    double factor = 0.25;
    if (lower[FILTER_MIN_WIDTH] != 0)
        // (assuming lower is less than 1)
        upper[FILTER_MIN_WIDTH] = 1 - Math.max(0, factor * (1 - lower[FILTER_MIN_WIDTH]));
    if (upper[FILTER_MIN_WIDTH] != 0)
        // (assuming upper is more than 1)
        lower[FILTER_MAX_WIDTH] = 1 + Math.max(0, factor * (upper[FILTER_MAX_WIDTH] - 1));
    // Round the ranges
    final double[] interval = new double[stats[0].length];
    interval[FILTER_SIGNAL] = SignalFilter.DEFAULT_INCREMENT;
    interval[FILTER_SNR] = SNRFilter.DEFAULT_INCREMENT;
    interval[FILTER_MIN_WIDTH] = WidthFilter2.DEFAULT_MIN_INCREMENT;
    interval[FILTER_MAX_WIDTH] = WidthFilter.DEFAULT_INCREMENT;
    interval[FILTER_SHIFT] = ShiftFilter.DEFAULT_INCREMENT;
    interval[FILTER_ESHIFT] = EShiftFilter.DEFAULT_INCREMENT;
    interval[FILTER_PRECISION] = PrecisionFilter.DEFAULT_INCREMENT;
    interval[FILTER_ITERATIONS] = 0.1;
    interval[FILTER_EVALUATIONS] = 0.1;
    // Create a range increment
    double[] increment = new double[lower.length];
    for (int i = 0; i < increment.length; i++) {
        lower[i] = Maths.floor(lower[i], interval[i]);
        upper[i] = Maths.ceil(upper[i], interval[i]);
        double range = upper[i] - lower[i];
        // Allow clipping if the range is small compared to the min increment
        double multiples = range / interval[i];
        // Use 8 multiples for the equivalent of +/- 4 steps around the centre
        if (multiples < 8) {
            multiples = Math.ceil(multiples);
        } else
            multiples = 8;
        increment[i] = Maths.ceil(range / multiples, interval[i]);
        if (i == FILTER_MIN_WIDTH)
            // Requires clipping based on the upper limit
            lower[i] = upper[i] - increment[i] * multiples;
        else
            upper[i] = lower[i] + increment[i] * multiples;
    }
    for (int i = 0; i < stats[0].length; i++) {
        lower[i] = Maths.round(lower[i]);
        upper[i] = Maths.round(upper[i]);
        min[i] = Maths.round(min[i]);
        max[i] = Maths.round(max[i]);
        increment[i] = Maths.round(increment[i]);
        sb.append("\t").append(min[i]).append(':').append(lower[i]).append('-').append(upper[i]).append(':').append(max[i]);
    }
    // Disable some filters
    increment[FILTER_SIGNAL] = Double.POSITIVE_INFINITY;
    //increment[FILTER_SHIFT] = Double.POSITIVE_INFINITY;
    increment[FILTER_ESHIFT] = Double.POSITIVE_INFINITY;
    wo.tile();
    sb.append("\t").append(Utils.timeToString(runTime / 1000000.0));
    summaryTable.append(sb.toString());
    if (saveFilterRange) {
        GlobalSettings gs = SettingsManager.loadSettings();
        FilterSettings filterSettings = gs.getFilterSettings();
        String filename = (silent) ? filterSettings.filterSetFilename : Utils.getFilename("Filter_range_file", filterSettings.filterSetFilename);
        if (filename == null)
            return;
        // Remove extension to store the filename
        filename = Utils.replaceExtension(filename, ".xml");
        filterSettings.filterSetFilename = filename;
        // Create a filter set using the ranges
        ArrayList<Filter> filters = new ArrayList<Filter>(3);
        filters.add(new MultiFilter2(lower[0], (float) lower[1], lower[2], lower[3], lower[4], lower[5], lower[6]));
        filters.add(new MultiFilter2(upper[0], (float) upper[1], upper[2], upper[3], upper[4], upper[5], upper[6]));
        filters.add(new MultiFilter2(increment[0], (float) increment[1], increment[2], increment[3], increment[4], increment[5], increment[6]));
        if (saveFilters(filename, filters))
            SettingsManager.saveSettings(gs);
        // Create a filter set using the min/max and the initial bounds.
        // Set sensible limits
        min[FILTER_SIGNAL] = Math.max(min[FILTER_SIGNAL], 30);
        max[FILTER_PRECISION] = Math.min(max[FILTER_PRECISION], 100);
        // Commented this out so that the 4-set filters are the same as the 3-set filters.
        // The difference leads to differences when optimising.
        //			// Use half the initial bounds (hoping this is a good starting guess for the optimum)
        //			final boolean[] limitToLower = new boolean[min.length];
        //			limitToLower[FILTER_SIGNAL] = true;
        //			limitToLower[FILTER_SNR] = true;
        //			limitToLower[FILTER_MIN_WIDTH] = true;
        //			limitToLower[FILTER_MAX_WIDTH] = false;
        //			limitToLower[FILTER_SHIFT] = false;
        //			limitToLower[FILTER_ESHIFT] = false;
        //			limitToLower[FILTER_PRECISION] = true;
        //			for (int i = 0; i < limitToLower.length; i++)
        //			{
        //				final double range = (upper[i] - lower[i]) / 2;
        //				if (limitToLower[i])
        //					upper[i] = lower[i] + range;
        //				else
        //					lower[i] = upper[i] - range;
        //			}
        filters = new ArrayList<Filter>(4);
        filters.add(new MultiFilter2(min[0], (float) min[1], min[2], min[3], min[4], min[5], min[6]));
        filters.add(new MultiFilter2(lower[0], (float) lower[1], lower[2], lower[3], lower[4], lower[5], lower[6]));
        filters.add(new MultiFilter2(upper[0], (float) upper[1], upper[2], upper[3], upper[4], upper[5], upper[6]));
        filters.add(new MultiFilter2(max[0], (float) max[1], max[2], max[3], max[4], max[5], max[6]));
        saveFilters(Utils.replaceExtension(filename, ".4.xml"), filters);
    }
}
Also used : ArrayList(java.util.ArrayList) TIntHashSet(gnu.trove.set.hash.TIntHashSet) MultiPathFitResult(gdsc.smlm.results.filter.MultiPathFitResult) FractionalAssignment(gdsc.core.match.FractionalAssignment) PeakFractionalAssignment(gdsc.smlm.results.filter.PeakFractionalAssignment) ImmutableFractionalAssignment(gdsc.core.match.ImmutableFractionalAssignment) FractionClassificationResult(gdsc.core.match.FractionClassificationResult) BasePreprocessedPeakResult(gdsc.smlm.results.filter.BasePreprocessedPeakResult) PreprocessedPeakResult(gdsc.smlm.results.filter.PreprocessedPeakResult) SignalFilter(gdsc.smlm.results.filter.SignalFilter) FilterSettings(gdsc.smlm.ij.settings.FilterSettings) ScoredSpot(gdsc.smlm.ij.plugins.BenchmarkSpotFilter.ScoredSpot) FastCorrelator(gdsc.core.utils.FastCorrelator) Plot(ij.gui.Plot) StoredDataStatistics(gdsc.core.utils.StoredDataStatistics) PlotWindow(ij.gui.PlotWindow) GlobalSettings(gdsc.smlm.ij.settings.GlobalSettings) WindowOrganiser(ij.plugin.WindowOrganiser) PeakResultPoint(gdsc.smlm.ij.plugins.ResultsMatchCalculator.PeakResultPoint) BasePoint(gdsc.core.match.BasePoint) PeakFractionalAssignment(gdsc.smlm.results.filter.PeakFractionalAssignment) FractionScoreStore(gdsc.smlm.results.filter.MultiPathFilter.FractionScoreStore) SimpleRegression(org.apache.commons.math3.stat.regression.SimpleRegression) SignalFilter(gdsc.smlm.results.filter.SignalFilter) DirectFilter(gdsc.smlm.results.filter.DirectFilter) ShiftFilter(gdsc.smlm.results.filter.ShiftFilter) PrecisionFilter(gdsc.smlm.results.filter.PrecisionFilter) Filter(gdsc.smlm.results.filter.Filter) EShiftFilter(gdsc.smlm.results.filter.EShiftFilter) WidthFilter(gdsc.smlm.results.filter.WidthFilter) SNRFilter(gdsc.smlm.results.filter.SNRFilter) MultiPathFilter(gdsc.smlm.results.filter.MultiPathFilter) MaximaSpotFilter(gdsc.smlm.filters.MaximaSpotFilter) MultiFilter2(gdsc.smlm.results.filter.MultiFilter2) MultiPathFitResults(gdsc.smlm.results.filter.MultiPathFitResults) MultiPathFilter(gdsc.smlm.results.filter.MultiPathFilter)

Aggregations

MultiFilter2 (gdsc.smlm.results.filter.MultiFilter2)3 DirectFilter (gdsc.smlm.results.filter.DirectFilter)2 EShiftFilter (gdsc.smlm.results.filter.EShiftFilter)2 MultiFilter (gdsc.smlm.results.filter.MultiFilter)2 PrecisionFilter (gdsc.smlm.results.filter.PrecisionFilter)2 SNRFilter (gdsc.smlm.results.filter.SNRFilter)2 ShiftFilter (gdsc.smlm.results.filter.ShiftFilter)2 SignalFilter (gdsc.smlm.results.filter.SignalFilter)2 WidthFilter (gdsc.smlm.results.filter.WidthFilter)2 BasePoint (gdsc.core.match.BasePoint)1 FractionClassificationResult (gdsc.core.match.FractionClassificationResult)1 FractionalAssignment (gdsc.core.match.FractionalAssignment)1 ImmutableFractionalAssignment (gdsc.core.match.ImmutableFractionalAssignment)1 FastCorrelator (gdsc.core.utils.FastCorrelator)1 StoredDataStatistics (gdsc.core.utils.StoredDataStatistics)1 MaximaSpotFilter (gdsc.smlm.filters.MaximaSpotFilter)1 ScoredSpot (gdsc.smlm.ij.plugins.BenchmarkSpotFilter.ScoredSpot)1 PeakResultPoint (gdsc.smlm.ij.plugins.ResultsMatchCalculator.PeakResultPoint)1 FilterSettings (gdsc.smlm.ij.settings.FilterSettings)1 GlobalSettings (gdsc.smlm.ij.settings.GlobalSettings)1