Search in sources :

Example 21 with PlotWindow

use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.

the class BenchmarkSpotFilter method plot.

private void plot(int i, ArrayList<BatchResult[]> batchResults) {
    if (!batchPlot[i])
        return;
    Color[] colors = new Color[] { Color.red, Color.gray, Color.green, Color.blue, Color.magenta };
    String name = batchPlotNames[i];
    String title = TITLE + " Performance " + name;
    Plot plot = new Plot(title, "Relative width", name);
    final double scale = 1.0 / config.getHWHMMin();
    for (BatchResult[] batchResult : batchResults) {
        if (batchResult == null || batchResult.length == 0)
            continue;
        float[][] data = extractData(batchResult, i, scale);
        int colorIndex = batchResult[0].dataFilter.ordinal();
        plot.setColor(colors[colorIndex]);
        colors[colorIndex] = colors[colorIndex].darker();
        plot.addPoints(data[0], data[1], null, (batchResult.length > 1) ? Plot.LINE : Plot.CIRCLE, batchResult[0].getName());
    }
    plot.setColor(Color.black);
    plot.addLegend(null);
    if (name.contains("Time"))
        plot.setAxisYLog(true);
    PlotWindow pw = Utils.display(title, plot);
    // Seems to only work after drawing
    plot.setLimitsToFit(true);
    if (Utils.isNewWindow())
        windowOrganiser.add(pw);
}
Also used : Color(java.awt.Color) Plot(ij.gui.Plot) PlotWindow(ij.gui.PlotWindow) PeakResultPoint(gdsc.smlm.ij.plugins.ResultsMatchCalculator.PeakResultPoint) BasePoint(gdsc.core.match.BasePoint)

Example 22 with PlotWindow

use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.

the class BenchmarkFilterAnalysis method depthAnalysis.

/**
	 * Depth analysis.
	 *
	 * @param allAssignments
	 *            The assignments generated from running the filter (or null)
	 * @param filter
	 *            the filter
	 * @return the assignments
	 */
private ArrayList<FractionalAssignment[]> depthAnalysis(ArrayList<FractionalAssignment[]> allAssignments, DirectFilter filter) {
    if (!depthRecallAnalysis || simulationParameters.fixedDepth)
        return null;
    // Build a histogram of the number of spots at different depths
    final double[] depths = depthStats.getValues();
    double[] limits = Maths.limits(depths);
    //final int bins = Math.max(10, nActual / 100);
    //final int bins = Utils.getBinsSturges(depths.length);
    final int bins = Utils.getBinsSqrt(depths.length);
    double[][] h1 = Utils.calcHistogram(depths, limits[0], limits[1], bins);
    double[][] h2 = Utils.calcHistogram(depthFitStats.getValues(), limits[0], limits[1], bins);
    // manually to get the results that pass.
    if (allAssignments == null)
        allAssignments = getAssignments(filter);
    double[] depths2 = new double[results.size()];
    int count = 0;
    for (FractionalAssignment[] assignments : allAssignments) {
        if (assignments == null)
            continue;
        for (int i = 0; i < assignments.length; i++) {
            final CustomFractionalAssignment c = (CustomFractionalAssignment) assignments[i];
            depths2[count++] = c.peak.error;
        }
    }
    depths2 = Arrays.copyOf(depths2, count);
    // Build a histogram using the same limits
    double[][] h3 = Utils.calcHistogram(depths2, limits[0], limits[1], bins);
    // Convert pixel depth to nm
    for (int i = 0; i < h1[0].length; i++) h1[0][i] *= simulationParameters.a;
    limits[0] *= simulationParameters.a;
    limits[1] *= simulationParameters.a;
    // Produce a histogram of the number of spots at each depth
    String title1 = TITLE + " Depth Histogram";
    Plot2 plot1 = new Plot2(title1, "Depth (nm)", "Frequency");
    plot1.setLimits(limits[0], limits[1], 0, Maths.max(h1[1]));
    plot1.setColor(Color.black);
    plot1.addPoints(h1[0], h1[1], Plot2.BAR);
    plot1.addLabel(0, 0, "Black = Spots; Blue = Fitted; Red = Filtered");
    plot1.setColor(Color.blue);
    plot1.addPoints(h1[0], h2[1], Plot2.BAR);
    plot1.setColor(Color.red);
    plot1.addPoints(h1[0], h3[1], Plot2.BAR);
    plot1.setColor(Color.magenta);
    PlotWindow pw1 = Utils.display(title1, plot1);
    if (Utils.isNewWindow())
        wo.add(pw1);
    // Interpolate
    final double halfBinWidth = (h1[0][1] - h1[0][0]) * 0.5;
    // Remove final value of the histogram as this is at the upper limit of the range (i.e. count zero)
    h1[0] = Arrays.copyOf(h1[0], h1[0].length - 1);
    h1[1] = Arrays.copyOf(h1[1], h1[0].length);
    h2[1] = Arrays.copyOf(h2[1], h1[0].length);
    h3[1] = Arrays.copyOf(h3[1], h1[0].length);
    // TODO : Fix the smoothing since LOESS sometimes does not work.
    // Perhaps allow configuration of the number of histogram bins and the smoothing bandwidth.
    // Use minimum of 3 points for smoothing
    // Ensure we use at least x% of data
    double bandwidth = Math.max(3.0 / h1[0].length, 0.15);
    LoessInterpolator loess = new LoessInterpolator(bandwidth, 1);
    PolynomialSplineFunction spline1 = loess.interpolate(h1[0], h1[1]);
    PolynomialSplineFunction spline2 = loess.interpolate(h1[0], h2[1]);
    PolynomialSplineFunction spline3 = loess.interpolate(h1[0], h3[1]);
    // Use a second interpolator in case the LOESS fails
    LinearInterpolator lin = new LinearInterpolator();
    PolynomialSplineFunction spline1b = lin.interpolate(h1[0], h1[1]);
    PolynomialSplineFunction spline2b = lin.interpolate(h1[0], h2[1]);
    PolynomialSplineFunction spline3b = lin.interpolate(h1[0], h3[1]);
    // Increase the number of points to show a smooth curve
    double[] points = new double[bins * 5];
    limits = Maths.limits(h1[0]);
    final double interval = (limits[1] - limits[0]) / (points.length - 1);
    double[] v = new double[points.length];
    double[] v2 = new double[points.length];
    double[] v3 = new double[points.length];
    for (int i = 0; i < points.length - 1; i++) {
        points[i] = limits[0] + i * interval;
        v[i] = getSplineValue(spline1, spline1b, points[i]);
        v2[i] = getSplineValue(spline2, spline2b, points[i]);
        v3[i] = getSplineValue(spline3, spline3b, points[i]);
        points[i] += halfBinWidth;
    }
    // Final point on the limit of the spline range
    int ii = points.length - 1;
    v[ii] = getSplineValue(spline1, spline1b, limits[1]);
    v2[ii] = getSplineValue(spline2, spline2b, limits[1]);
    v3[ii] = getSplineValue(spline3, spline3b, limits[1]);
    points[ii] = limits[1] + halfBinWidth;
    // Calculate recall
    for (int i = 0; i < v.length; i++) {
        v2[i] = v2[i] / v[i];
        v3[i] = v3[i] / v[i];
    }
    final double halfSummaryDepth = summaryDepth * 0.5;
    String title2 = TITLE + " Depth Histogram (normalised)";
    Plot2 plot2 = new Plot2(title2, "Depth (nm)", "Recall");
    plot2.setLimits(limits[0] + halfBinWidth, limits[1] + halfBinWidth, 0, Maths.min(1, Maths.max(v2)));
    plot2.setColor(Color.black);
    plot2.addLabel(0, 0, "Blue = Fitted; Red = Filtered");
    plot2.setColor(Color.blue);
    plot2.addPoints(points, v2, Plot2.LINE);
    plot2.setColor(Color.red);
    plot2.addPoints(points, v3, Plot2.LINE);
    plot2.setColor(Color.magenta);
    if (-halfSummaryDepth - halfBinWidth >= limits[0]) {
        plot2.drawLine(-halfSummaryDepth, 0, -halfSummaryDepth, getSplineValue(spline3, spline3b, -halfSummaryDepth - halfBinWidth) / getSplineValue(spline1, spline1b, -halfSummaryDepth - halfBinWidth));
    }
    if (halfSummaryDepth - halfBinWidth <= limits[1]) {
        plot2.drawLine(halfSummaryDepth, 0, halfSummaryDepth, getSplineValue(spline3, spline3b, halfSummaryDepth - halfBinWidth) / getSplineValue(spline1, spline1b, halfSummaryDepth - halfBinWidth));
    }
    PlotWindow pw2 = Utils.display(title2, plot2);
    if (Utils.isNewWindow())
        wo.add(pw2);
    return allAssignments;
}
Also used : PlotWindow(ij.gui.PlotWindow) Plot2(ij.gui.Plot2) PolynomialSplineFunction(org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction) LoessInterpolator(org.apache.commons.math3.analysis.interpolation.LoessInterpolator) FractionalAssignment(gdsc.core.match.FractionalAssignment) PeakFractionalAssignment(gdsc.smlm.results.filter.PeakFractionalAssignment) LinearInterpolator(org.apache.commons.math3.analysis.interpolation.LinearInterpolator)

Example 23 with PlotWindow

use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.

the class MeanVarianceTest method run.

/*
	 * (non-Javadoc)
	 * 
	 * @see ij.plugin.PlugIn#run(java.lang.String)
	 */
public void run(String arg) {
    SMLMUsageTracker.recordPlugin(this.getClass(), arg);
    if (Utils.isExtraOptions()) {
        ImagePlus imp = WindowManager.getCurrentImage();
        if (imp.getStackSize() > 1) {
            GenericDialog gd = new GenericDialog(TITLE);
            gd.addMessage("Perform single image analysis on the current image?");
            gd.addNumericField("Bias", _bias, 0);
            gd.showDialog();
            if (gd.wasCanceled())
                return;
            singleImage = true;
            _bias = Math.abs(gd.getNextNumber());
        } else {
            IJ.error(TITLE, "Single-image mode requires a stack");
            return;
        }
    }
    List<ImageSample> images;
    String inputDirectory = "";
    if (singleImage) {
        IJ.showStatus("Loading images...");
        images = getImages();
        if (images.size() == 0) {
            IJ.error(TITLE, "Not enough images for analysis");
            return;
        }
    } else {
        inputDirectory = IJ.getDirectory("Select image series ...");
        if (inputDirectory == null)
            return;
        SeriesOpener series = new SeriesOpener(inputDirectory, false, 0);
        series.setVariableSize(true);
        if (series.getNumberOfImages() < 3) {
            IJ.error(TITLE, "Not enough images in the selected directory");
            return;
        }
        if (!IJ.showMessageWithCancel(TITLE, String.format("Analyse %d images, first image:\n%s", series.getNumberOfImages(), series.getImageList()[0]))) {
            return;
        }
        IJ.showStatus("Loading images");
        images = getImages(series);
        if (images.size() < 3) {
            IJ.error(TITLE, "Not enough images for analysis");
            return;
        }
        if (images.get(0).exposure != 0) {
            IJ.error(TITLE, "First image in series must have exposure 0 (Bias image)");
            return;
        }
    }
    boolean emMode = (arg != null && arg.contains("em"));
    GenericDialog gd = new GenericDialog(TITLE);
    gd.addMessage("Set the output options:");
    gd.addCheckbox("Show_table", showTable);
    gd.addCheckbox("Show_charts", showCharts);
    if (emMode) {
        // Ask the user for the camera gain ...
        gd.addMessage("Estimating the EM-gain requires the camera gain without EM readout enabled");
        gd.addNumericField("Camera_gain (ADU/e-)", cameraGain, 4);
    }
    gd.showDialog();
    if (gd.wasCanceled())
        return;
    showTable = gd.getNextBoolean();
    showCharts = gd.getNextBoolean();
    if (emMode) {
        cameraGain = gd.getNextNumber();
    }
    IJ.showStatus("Computing mean & variance");
    final double nImages = images.size();
    for (int i = 0; i < images.size(); i++) {
        IJ.showStatus(String.format("Computing mean & variance %d/%d", i + 1, images.size()));
        images.get(i).compute(singleImage, i / nImages, (i + 1) / nImages);
    }
    IJ.showProgress(1);
    IJ.showStatus("Computing results");
    // Allow user to input multiple bias images
    int start = 0;
    Statistics biasStats = new Statistics();
    Statistics noiseStats = new Statistics();
    final double bias;
    if (singleImage) {
        bias = _bias;
    } else {
        while (start < images.size()) {
            ImageSample sample = images.get(start);
            if (sample.exposure == 0) {
                biasStats.add(sample.means);
                for (PairSample pair : sample.samples) {
                    noiseStats.add(pair.variance);
                }
                start++;
            } else
                break;
        }
        bias = biasStats.getMean();
    }
    // Get the mean-variance data
    int total = 0;
    for (int i = start; i < images.size(); i++) total += images.get(i).samples.size();
    if (showTable && total > 2000) {
        gd = new GenericDialog(TITLE);
        gd.addMessage("Table output requires " + total + " entries.\n \nYou may want to disable the table.");
        gd.addCheckbox("Show_table", showTable);
        gd.showDialog();
        if (gd.wasCanceled())
            return;
        showTable = gd.getNextBoolean();
    }
    TextWindow results = (showTable) ? createResultsWindow() : null;
    double[] mean = new double[total];
    double[] variance = new double[mean.length];
    Statistics gainStats = (singleImage) ? new StoredDataStatistics(total) : new Statistics();
    final WeightedObservedPoints obs = new WeightedObservedPoints();
    for (int i = (singleImage) ? 0 : start, j = 0; i < images.size(); i++) {
        StringBuilder sb = (showTable) ? new StringBuilder() : null;
        ImageSample sample = images.get(i);
        for (PairSample pair : sample.samples) {
            if (j % 16 == 0)
                IJ.showProgress(j, total);
            mean[j] = pair.getMean();
            variance[j] = pair.variance;
            // Gain is in ADU / e
            double gain = variance[j] / (mean[j] - bias);
            gainStats.add(gain);
            obs.add(mean[j], variance[j]);
            if (emMode) {
                gain /= (2 * cameraGain);
            }
            if (showTable) {
                sb.append(sample.title).append("\t");
                sb.append(sample.exposure).append("\t");
                sb.append(pair.slice1).append("\t");
                sb.append(pair.slice2).append("\t");
                sb.append(IJ.d2s(pair.mean1, 2)).append("\t");
                sb.append(IJ.d2s(pair.mean2, 2)).append("\t");
                sb.append(IJ.d2s(mean[j], 2)).append("\t");
                sb.append(IJ.d2s(variance[j], 2)).append("\t");
                sb.append(Utils.rounded(gain, 4)).append("\n");
            }
            j++;
        }
        if (showTable)
            results.append(sb.toString());
    }
    IJ.showProgress(1);
    if (singleImage) {
        StoredDataStatistics stats = (StoredDataStatistics) gainStats;
        Utils.log(TITLE);
        if (emMode) {
            double[] values = stats.getValues();
            MathArrays.scaleInPlace(0.5, values);
            stats = new StoredDataStatistics(values);
        }
        if (showCharts) {
            // Plot the gain over time
            String title = TITLE + " Gain vs Frame";
            Plot2 plot = new Plot2(title, "Slice", "Gain", Utils.newArray(gainStats.getN(), 1, 1.0), stats.getValues());
            PlotWindow pw = Utils.display(title, plot);
            // Show a histogram
            String label = String.format("Mean = %s, Median = %s", Utils.rounded(stats.getMean()), Utils.rounded(stats.getMedian()));
            int id = Utils.showHistogram(TITLE, stats, "Gain", 0, 1, 100, true, label);
            if (Utils.isNewWindow()) {
                Point point = pw.getLocation();
                point.x = pw.getLocation().x;
                point.y += pw.getHeight();
                WindowManager.getImage(id).getWindow().setLocation(point);
            }
        }
        Utils.log("Single-image mode: %s camera", (emMode) ? "EM-CCD" : "Standard");
        final double gain = stats.getMedian();
        if (emMode) {
            final double totalGain = gain;
            final double emGain = totalGain / cameraGain;
            Utils.log("  Gain = 1 / %s (ADU/e-)", Utils.rounded(cameraGain, 4));
            Utils.log("  EM-Gain = %s", Utils.rounded(emGain, 4));
            Utils.log("  Total Gain = %s (ADU/e-)", Utils.rounded(totalGain, 4));
        } else {
            cameraGain = gain;
            Utils.log("  Gain = 1 / %s (ADU/e-)", Utils.rounded(cameraGain, 4));
        }
    } else {
        IJ.showStatus("Computing fit");
        // Sort
        int[] indices = rank(mean);
        mean = reorder(mean, indices);
        variance = reorder(variance, indices);
        // Compute optimal coefficients.
        // a - b x
        final double[] init = { 0, 1 / gainStats.getMean() };
        final PolynomialCurveFitter fitter = PolynomialCurveFitter.create(2).withStartPoint(init);
        final double[] best = fitter.fit(obs.toList());
        // Construct the polynomial that best fits the data.
        final PolynomialFunction fitted = new PolynomialFunction(best);
        if (showCharts) {
            // Plot mean verses variance. Gradient is gain in ADU/e.
            String title = TITLE + " results";
            Plot2 plot = new Plot2(title, "Mean", "Variance");
            double[] xlimits = Maths.limits(mean);
            double[] ylimits = Maths.limits(variance);
            double xrange = (xlimits[1] - xlimits[0]) * 0.05;
            if (xrange == 0)
                xrange = 0.05;
            double yrange = (ylimits[1] - ylimits[0]) * 0.05;
            if (yrange == 0)
                yrange = 0.05;
            plot.setLimits(xlimits[0] - xrange, xlimits[1] + xrange, ylimits[0] - yrange, ylimits[1] + yrange);
            plot.setColor(Color.blue);
            plot.addPoints(mean, variance, Plot2.CROSS);
            plot.setColor(Color.red);
            plot.addPoints(new double[] { mean[0], mean[mean.length - 1] }, new double[] { fitted.value(mean[0]), fitted.value(mean[mean.length - 1]) }, Plot2.LINE);
            Utils.display(title, plot);
        }
        final double avBiasNoise = Math.sqrt(noiseStats.getMean());
        Utils.log(TITLE);
        Utils.log("  Directory = %s", inputDirectory);
        Utils.log("  Bias = %s +/- %s (ADU)", Utils.rounded(bias, 4), Utils.rounded(avBiasNoise, 4));
        Utils.log("  Variance = %s + %s * mean", Utils.rounded(best[0], 4), Utils.rounded(best[1], 4));
        if (emMode) {
            final double emGain = best[1] / (2 * cameraGain);
            // Noise is standard deviation of the bias image divided by the total gain (in ADU/e-)
            final double totalGain = emGain * cameraGain;
            Utils.log("  Read Noise = %s (e-) [%s (ADU)]", Utils.rounded(avBiasNoise / totalGain, 4), Utils.rounded(avBiasNoise, 4));
            Utils.log("  Gain = 1 / %s (ADU/e-)", Utils.rounded(1 / cameraGain, 4));
            Utils.log("  EM-Gain = %s", Utils.rounded(emGain, 4));
            Utils.log("  Total Gain = %s (ADU/e-)", Utils.rounded(totalGain, 4));
        } else {
            // Noise is standard deviation of the bias image divided by the gain (in ADU/e-)
            cameraGain = best[1];
            final double readNoise = avBiasNoise / cameraGain;
            Utils.log("  Read Noise = %s (e-) [%s (ADU)]", Utils.rounded(readNoise, 4), Utils.rounded(readNoise * cameraGain, 4));
            Utils.log("  Gain = 1 / %s (ADU/e-)", Utils.rounded(1 / cameraGain, 4));
        }
    }
    IJ.showStatus("");
}
Also used : StoredDataStatistics(gdsc.core.utils.StoredDataStatistics) PlotWindow(ij.gui.PlotWindow) PolynomialFunction(org.apache.commons.math3.analysis.polynomials.PolynomialFunction) SeriesOpener(gdsc.smlm.ij.utils.SeriesOpener) Plot2(ij.gui.Plot2) Point(java.awt.Point) ImagePlus(ij.ImagePlus) StoredDataStatistics(gdsc.core.utils.StoredDataStatistics) Statistics(gdsc.core.utils.Statistics) Point(java.awt.Point) PolynomialCurveFitter(org.apache.commons.math3.fitting.PolynomialCurveFitter) WeightedObservedPoints(org.apache.commons.math3.fitting.WeightedObservedPoints) TextWindow(ij.text.TextWindow) GenericDialog(ij.gui.GenericDialog)

Example 24 with PlotWindow

use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.

the class PSFCreator method plotSignalAtSpecifiedSD.

/**
	 * Show a plot of the amount of signal within N x SD for each z position. This indicates
	 * how much the PSF has spread from the original Gaussian shape.
	 * 
	 * @param psf
	 *            The PSF
	 * @param fittedSd
	 *            The width of the PSF (in pixels)
	 * @param factor
	 *            The factor to use
	 * @param slice
	 *            The slice used to create the label
	 */
private void plotSignalAtSpecifiedSD(ImageStack psf, double fittedSd, double factor, int slice) {
    if (signalZ == null) {
        // Get the bounds
        int radius = (int) Math.round(fittedSd * factor);
        int min = FastMath.max(0, psf.getWidth() / 2 - radius);
        int max = FastMath.min(psf.getWidth() - 1, psf.getWidth() / 2 + radius);
        // Create a circle mask of the PSF projection
        ByteProcessor circle = new ByteProcessor(max - min + 1, max - min + 1);
        circle.setColor(255);
        circle.fillOval(0, 0, circle.getWidth(), circle.getHeight());
        final byte[] mask = (byte[]) circle.getPixels();
        // Sum the pixels within the mask for each slice
        signalZ = new double[psf.getSize()];
        signal = new double[psf.getSize()];
        for (int i = 0; i < psf.getSize(); i++) {
            double sum = 0;
            float[] data = (float[]) psf.getProcessor(i + 1).getPixels();
            for (int y = min, ii = 0; y <= max; y++) {
                int index = y * psf.getWidth() + min;
                for (int x = min; x <= max; x++, ii++, index++) {
                    if (mask[ii] != 0 && data[index] > 0)
                        sum += data[index];
                }
            }
            double total = 0;
            for (float f : data) if (f > 0)
                total += f;
            signalZ[i] = i + 1;
            signal[i] = 100 * sum / total;
        }
        signalTitle = String.format("%% PSF signal at %s x SD", Utils.rounded(factor, 3));
        signalLimits = Maths.limits(signal);
    }
    // Plot the sum
    boolean alignWindows = (WindowManager.getFrame(signalTitle) == null);
    final double total = signal[slice - 1];
    Plot2 plot = new Plot2(signalTitle, "z", "Signal", signalZ, signal);
    plot.addLabel(0, 0, String.format("Total = %s. z = %s nm", Utils.rounded(total), Utils.rounded((slice - zCentre) * nmPerSlice)));
    plot.setColor(Color.green);
    plot.drawLine(slice, signalLimits[0], slice, signalLimits[1]);
    plot.setColor(Color.blue);
    PlotWindow plotWindow = Utils.display(signalTitle, plot);
    if (alignWindows && plotWindow != null) {
        if (alignWindows && plotWindow != null) {
            PlotWindow otherWindow = getPlot(TITLE_AMPLITUDE);
            if (otherWindow != null) {
                // Put the two plots tiled together so both are visible
                Point l = plotWindow.getLocation();
                l.x = otherWindow.getLocation().x + otherWindow.getWidth();
                l.y = otherWindow.getLocation().y;
                plotWindow.setLocation(l);
            }
        }
    }
}
Also used : ByteProcessor(ij.process.ByteProcessor) PlotWindow(ij.gui.PlotWindow) Plot2(ij.gui.Plot2) Point(java.awt.Point) BasePoint(gdsc.core.match.BasePoint) Point(java.awt.Point) BasePoint(gdsc.core.match.BasePoint)

Example 25 with PlotWindow

use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.

the class PSFCreator method plotCumulativeSignal.

/**
	 * Show a plot of the cumulative signal vs distance from the centre
	 * 
	 * @param z
	 *            The slice to plot
	 * @param normalise
	 *            normalise the sum to 1
	 * @param resetScale
	 *            Reset the y-axis maximum
	 * @param distanceThreshold
	 *            The distance threshold for the cumulative total shown in the plot label
	 */
private void plotCumulativeSignal(int z, boolean normalise, boolean resetScale, double distanceThreshold) {
    float[] data = (float[]) psf.getProcessor(z).getPixels();
    final int size = psf.getWidth();
    if (indexLookup == null || indexLookup.length != data.length) {
        // Precompute square distances
        double[] d2 = new double[size];
        for (int y = 0, y2 = -size / 2; y < size; y++, y2++) d2[y] = y2 * y2;
        // Precompute distances
        double[] d = new double[data.length];
        for (int y = 0, i = 0; y < size; y++) {
            for (int x = 0; x < size; x++, i++) {
                d[i] = Math.sqrt(d2[y] + d2[x]);
            }
        }
        // Sort
        int[] indices = Utils.newArray(d.length, 0, 1);
        Sort.sort(indices, d, true);
        // The sort is made in descending order so invert
        Sort.reverse(indices);
        Sort.reverse(d);
        // Store a unique cumulative index for each distance
        double lastD = d[0];
        int lastI = 0;
        int counter = 0;
        StoredData distance = new StoredData();
        indexLookup = new int[indices.length];
        for (int i = 0; i < indices.length; i++) {
            if (lastD != d[i]) {
                distance.add(lastD * psfNmPerPixel);
                for (int j = lastI; j < i; j++) {
                    indexLookup[indices[j]] = counter;
                }
                lastD = d[i];
                lastI = i;
                counter++;
            }
        }
        // Do the final distance
        distance.add(lastD * psfNmPerPixel);
        for (int j = lastI; j < indices.length; j++) {
            indexLookup[indices[j]] = counter;
        }
        counter++;
        distances = distance.getValues();
    }
    // Get the signal at each distance
    double[] signal = new double[distances.length];
    for (int i = 0; i < data.length; i++) {
        if (data[i] > 0)
            signal[indexLookup[i]] += data[i];
    }
    // Get the cumulative signal
    for (int i = 1; i < signal.length; i++) signal[i] += signal[i - 1];
    // Get the total up to the distance threshold
    double sum = 0;
    for (int i = 0; i < signal.length; i++) {
        if (distances[i] > distanceThreshold)
            break;
        sum = signal[i];
    }
    if (normalise && distanceThreshold > 0) {
        for (int i = 0; i < signal.length; i++) signal[i] /= sum;
    }
    if (resetScale)
        maxCumulativeSignal = 0;
    maxCumulativeSignal = Maths.maxDefault(maxCumulativeSignal, signal);
    String title = "Cumulative Signal";
    boolean alignWindows = (WindowManager.getFrame(title) == null);
    Plot2 plot = new Plot2(title, "Distance (nm)", "Signal", distances, signal);
    plot.setLimits(0, distances[distances.length - 1], 0, maxCumulativeSignal);
    plot.addLabel(0, 0, String.format("Total = %s (@ %s nm). z = %s nm", Utils.rounded(sum), Utils.rounded(distanceThreshold), Utils.rounded((z - zCentre) * nmPerSlice)));
    plot.setColor(Color.green);
    plot.drawLine(distanceThreshold, 0, distanceThreshold, maxCumulativeSignal);
    plot.setColor(Color.blue);
    PlotWindow plotWindow = Utils.display(title, plot);
    if (alignWindows && plotWindow != null) {
        PlotWindow otherWindow = getPlot(TITLE_PSF_PARAMETERS);
        if (otherWindow != null) {
            // Put the two plots tiled together so both are visible
            Point l = plotWindow.getLocation();
            l.x = otherWindow.getLocation().x + otherWindow.getWidth();
            l.y = otherWindow.getLocation().y + otherWindow.getHeight();
            plotWindow.setLocation(l);
        }
    }
    // Update the PSF to the correct slice
    if (psfImp != null)
        psfImp.setSlice(z);
}
Also used : StoredData(gdsc.core.utils.StoredData) PlotWindow(ij.gui.PlotWindow) Plot2(ij.gui.Plot2) Point(java.awt.Point) BasePoint(gdsc.core.match.BasePoint) Point(java.awt.Point) BasePoint(gdsc.core.match.BasePoint)

Aggregations

PlotWindow (ij.gui.PlotWindow)31 Plot2 (ij.gui.Plot2)17 Plot (ij.gui.Plot)14 Point (java.awt.Point)13 BasePoint (gdsc.core.match.BasePoint)9 PeakResultPoint (gdsc.smlm.ij.plugins.ResultsMatchCalculator.PeakResultPoint)6 WindowOrganiser (uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser)4 FractionalAssignment (gdsc.core.match.FractionalAssignment)3 StoredDataStatistics (gdsc.core.utils.StoredDataStatistics)3 PeakFractionalAssignment (gdsc.smlm.results.filter.PeakFractionalAssignment)3 GenericDialog (ij.gui.GenericDialog)3 WindowOrganiser (ij.plugin.WindowOrganiser)3 LinearInterpolator (org.apache.commons.math3.analysis.interpolation.LinearInterpolator)3 PolynomialSplineFunction (org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction)3 BasePoint (uk.ac.sussex.gdsc.core.match.BasePoint)3 Statistics (gdsc.core.utils.Statistics)2 StoredData (gdsc.core.utils.StoredData)2 ImagePlus (ij.ImagePlus)2 ByteProcessor (ij.process.ByteProcessor)2 TextWindow (ij.text.TextWindow)2