Search in sources :

Example 36 with Line

use of org.apache.commons.math3.geometry.euclidean.twod.Line in project GDSC-SMLM by aherbert.

the class SpotInspector method run.

@Override
public void run(String arg) {
    SmlmUsageTracker.recordPlugin(this.getClass(), arg);
    if (MemoryPeakResults.isMemoryEmpty()) {
        IJ.error(TITLE, "No localisations in memory");
        return;
    }
    if (!showDialog()) {
        return;
    }
    // Load the results
    results = ResultsManager.loadInputResults(settings.inputOption, false, DistanceUnit.PIXEL, null);
    if (MemoryPeakResults.isEmpty(results)) {
        IJ.error(TITLE, "No results could be loaded");
        IJ.showStatus("");
        return;
    }
    // Check if the original image is open
    ImageSource source = results.getSource();
    if (source == null) {
        IJ.error(TITLE, "Unknown original source image");
        return;
    }
    source = source.getOriginal();
    source.setReadHint(ReadHint.NONSEQUENTIAL);
    if (!source.open()) {
        IJ.error(TITLE, "Cannot open original source image: " + source.toString());
        return;
    }
    final float stdDevMax = getStandardDeviation(results);
    if (stdDevMax < 0) {
        // TODO - Add dialog to get the initial peak width
        IJ.error(TITLE, "Fitting configuration (for initial peak width) is not available");
        return;
    }
    // Rank spots
    rankedResults = new ArrayList<>(results.size());
    // Data for the sorting
    final PrecisionResultProcedure pp;
    if (settings.sortOrderIndex == 1) {
        pp = new PrecisionResultProcedure(results);
        pp.getPrecision();
    } else {
        pp = null;
    }
    // Build procedures to get:
    // Shift = position in pixels - originXY
    final StandardResultProcedure sp;
    if (settings.sortOrderIndex == 9) {
        sp = new StandardResultProcedure(results, DistanceUnit.PIXEL);
        sp.getXyr();
    } else {
        sp = null;
    }
    // SD = gaussian widths only for Gaussian PSFs
    final WidthResultProcedure wp;
    if (settings.sortOrderIndex >= 6 && settings.sortOrderIndex <= 8) {
        wp = new WidthResultProcedure(results, DistanceUnit.PIXEL);
        wp.getWxWy();
    } else {
        wp = null;
    }
    // Amplitude for Gaussian PSFs
    final HeightResultProcedure hp;
    if (settings.sortOrderIndex == 2) {
        hp = new HeightResultProcedure(results, IntensityUnit.PHOTON);
        hp.getH();
    } else {
        hp = null;
    }
    final Counter c = new Counter();
    results.forEach((PeakResultProcedure) result -> {
        final float[] score = getScore(result, c.getAndIncrement(), pp, sp, wp, hp, stdDevMax);
        rankedResults.add(new PeakResultRank(result, score[0], score[1]));
    });
    Collections.sort(rankedResults, PeakResultRank::compare);
    // Prepare results table
    final ImageJTablePeakResults table = new ImageJTablePeakResults(false, results.getName(), true);
    table.copySettings(results);
    table.setTableTitle(TITLE);
    table.setAddCounter(true);
    table.setShowZ(results.is3D());
    // TODO - Add to settings
    table.setShowFittingData(true);
    table.setShowNoiseData(true);
    if (settings.showCalibratedValues) {
        table.setDistanceUnit(DistanceUnit.NM);
        table.setIntensityUnit(IntensityUnit.PHOTON);
    } else {
        table.setDistanceUnit(DistanceUnit.PIXEL);
        table.setIntensityUnit(IntensityUnit.COUNT);
    }
    table.begin();
    // Add a mouse listener to jump to the frame for the clicked line
    textPanel = table.getResultsWindow().getTextPanel();
    // We must ignore old instances of this class from the mouse listeners
    id = currentId.incrementAndGet();
    textPanel.addMouseListener(new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent event) {
            SpotInspector.this.mouseClicked(event);
        }
    });
    // Add results to the table
    int count = 0;
    for (final PeakResultRank rank : rankedResults) {
        rank.rank = count++;
        table.add(rank.peakResult);
    }
    table.end();
    if (settings.plotScore || settings.plotHistogram) {
        // Get values for the plots
        float[] xValues = null;
        float[] yValues = null;
        double yMin;
        double yMax;
        int spotNumber = 0;
        xValues = new float[rankedResults.size()];
        yValues = new float[xValues.length];
        for (final PeakResultRank rank : rankedResults) {
            xValues[spotNumber] = spotNumber + 1;
            yValues[spotNumber++] = recoverScore(rank.score);
        }
        // Set the min and max y-values using 1.5 x IQR
        final DescriptiveStatistics stats = new DescriptiveStatistics();
        for (final float v : yValues) {
            stats.addValue(v);
        }
        if (settings.removeOutliers) {
            final double lower = stats.getPercentile(25);
            final double upper = stats.getPercentile(75);
            final double iqr = upper - lower;
            yMin = Math.max(lower - iqr, stats.getMin());
            yMax = Math.min(upper + iqr, stats.getMax());
            IJ.log(String.format("Data range: %f - %f. Plotting 1.5x IQR: %f - %f", stats.getMin(), stats.getMax(), yMin, yMax));
        } else {
            yMin = stats.getMin();
            yMax = stats.getMax();
            IJ.log(String.format("Data range: %f - %f", yMin, yMax));
        }
        plotScore(xValues, yValues, yMin, yMax);
        plotHistogram(yValues);
    }
    // Extract spots into a stack
    final int w = source.getWidth();
    final int h = source.getHeight();
    final int size = 2 * settings.radius + 1;
    final ImageStack spots = new ImageStack(size, size, rankedResults.size());
    // To assist the extraction of data from the image source, process them in time order to allow
    // frame caching. Then set the appropriate slice in the result stack
    Collections.sort(rankedResults, (o1, o2) -> Integer.compare(o1.peakResult.getFrame(), o2.peakResult.getFrame()));
    for (final PeakResultRank rank : rankedResults) {
        final PeakResult r = rank.peakResult;
        // Extract image
        // Note that the coordinates are relative to the middle of the pixel (0.5 offset)
        // so do not round but simply convert to int
        final int x = (int) (r.getXPosition());
        final int y = (int) (r.getYPosition());
        // Extract a region but crop to the image bounds
        int minX = x - settings.radius;
        int minY = y - settings.radius;
        final int maxX = Math.min(x + settings.radius + 1, w);
        final int maxY = Math.min(y + settings.radius + 1, h);
        int padX = 0;
        int padY = 0;
        if (minX < 0) {
            padX = -minX;
            minX = 0;
        }
        if (minY < 0) {
            padY = -minY;
            minY = 0;
        }
        final int sizeX = maxX - minX;
        final int sizeY = maxY - minY;
        float[] data = source.get(r.getFrame(), new Rectangle(minX, minY, sizeX, sizeY));
        // Prevent errors with missing data
        if (data == null) {
            data = new float[sizeX * sizeY];
        }
        ImageProcessor spotIp = new FloatProcessor(sizeX, sizeY, data, null);
        // Pad if necessary, i.e. the crop is too small for the stack
        if (padX > 0 || padY > 0 || sizeX < size || sizeY < size) {
            final ImageProcessor spotIp2 = spotIp.createProcessor(size, size);
            spotIp2.insert(spotIp, padX, padY);
            spotIp = spotIp2;
        }
        final int slice = rank.rank + 1;
        spots.setPixels(spotIp.getPixels(), slice);
        spots.setSliceLabel(MathUtils.rounded(rank.originalScore), slice);
    }
    source.close();
    // Reset to the rank order
    Collections.sort(rankedResults, PeakResultRank::compare);
    final ImagePlus imp = ImageJUtils.display(TITLE, spots);
    imp.setRoi((PointRoi) null);
    // Make bigger
    for (int i = 10; i-- > 0; ) {
        imp.getWindow().getCanvas().zoomIn(imp.getWidth() / 2, imp.getHeight() / 2);
    }
}
Also used : HeightResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.HeightResultProcedure) PrecisionResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PrecisionResultProcedure) Rectangle(java.awt.Rectangle) Point2D(java.awt.geom.Point2D) ImageProcessor(ij.process.ImageProcessor) HistogramPlotBuilder(uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder) PSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF) WindowManager(ij.WindowManager) PeakResult(uk.ac.sussex.gdsc.smlm.results.PeakResult) IntensityUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.IntensityUnit) ImageSource(uk.ac.sussex.gdsc.smlm.results.ImageSource) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) PointRoi(ij.gui.PointRoi) HashSet(java.util.HashSet) XyResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.XyResultProcedure) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) ReadHint(uk.ac.sussex.gdsc.smlm.results.ImageSource.ReadHint) MouseAdapter(java.awt.event.MouseAdapter) PeakResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure) MathUtils(uk.ac.sussex.gdsc.core.utils.MathUtils) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration) TextPanel(ij.text.TextPanel) HeightResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.HeightResultProcedure) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) InputSource(uk.ac.sussex.gdsc.smlm.ij.plugins.ResultsManager.InputSource) OffsetPointRoi(uk.ac.sussex.gdsc.core.ij.gui.OffsetPointRoi) DistanceUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit) WidthResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.WidthResultProcedure) Plot(ij.gui.Plot) MouseEvent(java.awt.event.MouseEvent) ImageJTablePeakResults(uk.ac.sussex.gdsc.smlm.ij.results.ImageJTablePeakResults) ImagePlus(ij.ImagePlus) FloatProcessor(ij.process.FloatProcessor) List(java.util.List) Counter(uk.ac.sussex.gdsc.smlm.results.count.Counter) ImageJUtils(uk.ac.sussex.gdsc.core.ij.ImageJUtils) IJ(ij.IJ) DescriptiveStatistics(org.apache.commons.math3.stat.descriptive.DescriptiveStatistics) ImageStack(ij.ImageStack) PsfHelper(uk.ac.sussex.gdsc.smlm.data.config.PsfHelper) PlugIn(ij.plugin.PlugIn) Collections(java.util.Collections) TypeConverter(uk.ac.sussex.gdsc.core.data.utils.TypeConverter) StandardResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.StandardResultProcedure) DescriptiveStatistics(org.apache.commons.math3.stat.descriptive.DescriptiveStatistics) MouseEvent(java.awt.event.MouseEvent) ImageStack(ij.ImageStack) FloatProcessor(ij.process.FloatProcessor) ImageJTablePeakResults(uk.ac.sussex.gdsc.smlm.ij.results.ImageJTablePeakResults) MouseAdapter(java.awt.event.MouseAdapter) Rectangle(java.awt.Rectangle) WidthResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.WidthResultProcedure) PrecisionResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PrecisionResultProcedure) ImagePlus(ij.ImagePlus) ReadHint(uk.ac.sussex.gdsc.smlm.results.ImageSource.ReadHint) PeakResult(uk.ac.sussex.gdsc.smlm.results.PeakResult) ImageProcessor(ij.process.ImageProcessor) Counter(uk.ac.sussex.gdsc.smlm.results.count.Counter) StandardResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.StandardResultProcedure) ImageSource(uk.ac.sussex.gdsc.smlm.results.ImageSource)

Example 37 with Line

use of org.apache.commons.math3.geometry.euclidean.twod.Line in project GDSC-SMLM by aherbert.

the class Fire method runQEstimation.

@SuppressWarnings("null")
private void runQEstimation() {
    IJ.showStatus(pluginTitle + " ...");
    if (!showQEstimationInputDialog()) {
        return;
    }
    MemoryPeakResults inputResults = ResultsManager.loadInputResults(settings.inputOption, false, null, null);
    if (MemoryPeakResults.isEmpty(inputResults)) {
        IJ.error(pluginTitle, "No results could be loaded");
        return;
    }
    if (inputResults.getCalibration() == null) {
        IJ.error(pluginTitle, "The results are not calibrated");
        return;
    }
    inputResults = cropToRoi(inputResults);
    if (inputResults.size() < 2) {
        IJ.error(pluginTitle, "No results within the crop region");
        return;
    }
    initialise(inputResults, null);
    // We need localisation precision.
    // Build a histogram of the localisation precision.
    // Get the initial mean and SD and plot as a Gaussian.
    final PrecisionHistogram histogram = calculatePrecisionHistogram();
    if (histogram == null) {
        IJ.error(pluginTitle, "No localisation precision available.\n \nPlease choose " + PrecisionMethod.FIXED + " and enter a precision mean and SD.");
        return;
    }
    final StoredDataStatistics precision = histogram.precision;
    final double fourierImageScale = Settings.scaleValues[settings.imageScaleIndex];
    final int imageSize = Settings.imageSizeValues[settings.imageSizeIndex];
    // Create the image and compute the numerator of FRC.
    // Do not use the signal so results.size() is the number of localisations.
    IJ.showStatus("Computing FRC curve ...");
    final FireImages images = createImages(fourierImageScale, imageSize, false);
    // DEBUGGING - Save the two images to disk. Load the images into the Matlab
    // code that calculates the Q-estimation and make this plugin match the functionality.
    // IJ.save(new ImagePlus("i1", images.ip1), "/scratch/i1.tif");
    // IJ.save(new ImagePlus("i2", images.ip2), "/scratch/i2.tif");
    final Frc frc = new Frc();
    frc.setTrackProgress(progress);
    frc.setFourierMethod(fourierMethod);
    frc.setSamplingMethod(samplingMethod);
    frc.setPerimeterSamplingFactor(settings.perimeterSamplingFactor);
    final FrcCurve frcCurve = frc.calculateFrcCurve(images.ip1, images.ip2, images.nmPerPixel);
    if (frcCurve == null) {
        IJ.error(pluginTitle, "Failed to compute FRC curve");
        return;
    }
    IJ.showStatus("Running Q-estimation ...");
    // Note:
    // The method implemented here is based on Matlab code provided by Bernd Rieger.
    // The idea is to compute the spurious correlation component of the FRC Numerator
    // using an initial estimate of distribution of the localisation precision (assumed
    // to be Gaussian). This component is the contribution of repeat localisations of
    // the same molecule to the numerator and is modelled as an exponential decay
    // (exp_decay). The component is scaled by the Q-value which
    // is the average number of times a molecule is seen in addition to the first time.
    // At large spatial frequencies the scaled component should match the numerator,
    // i.e. at high resolution (low FIRE number) the numerator is made up of repeat
    // localisations of the same molecule and not actual structure in the image.
    // The best fit is where the numerator equals the scaled component, i.e. num / (q*exp_decay) ==
    // 1.
    // The FRC Numerator is plotted and Q can be determined by
    // adjusting Q and the precision mean and SD to maximise the cost function.
    // This can be done interactively by the user with the effect on the FRC curve
    // dynamically updated and displayed.
    // Compute the scaled FRC numerator
    final double qNorm = (1 / frcCurve.mean1 + 1 / frcCurve.mean2);
    final double[] frcnum = new double[frcCurve.getSize()];
    for (int i = 0; i < frcnum.length; i++) {
        final FrcCurveResult r = frcCurve.get(i);
        frcnum[i] = qNorm * r.getNumerator() / r.getNumberOfSamples();
    }
    // Compute the spatial frequency and the region for curve fitting
    final double[] q = Frc.computeQ(frcCurve, false);
    int low = 0;
    int high = q.length;
    while (high > 0 && q[high - 1] > settings.maxQ) {
        high--;
    }
    while (low < q.length && q[low] < settings.minQ) {
        low++;
    }
    // Require we fit at least 10% of the curve
    if (high - low < q.length * 0.1) {
        IJ.error(pluginTitle, "Not enough points for Q estimation");
        return;
    }
    // Obtain initial estimate of Q plateau height and decay.
    // This can be done by fitting the precision histogram and then fixing the mean and sigma.
    // Or it can be done by allowing the precision to be sampled and the mean and sigma
    // become parameters for fitting.
    // Check if we can sample precision values
    final boolean sampleDecay = precision != null && settings.sampleDecay;
    double[] expDecay;
    if (sampleDecay) {
        // Random sample of precision values from the distribution is used to
        // construct the decay curve
        final int[] sample = RandomUtils.sample(10000, precision.getN(), UniformRandomProviders.create());
        final double four_pi2 = 4 * Math.PI * Math.PI;
        final double[] pre = new double[q.length];
        for (int i = 1; i < q.length; i++) {
            pre[i] = -four_pi2 * q[i] * q[i];
        }
        // Sample
        final int n = sample.length;
        final double[] hq = new double[n];
        for (int j = 0; j < n; j++) {
            // Scale to SR pixels
            double s2 = precision.getValue(sample[j]) / images.nmPerPixel;
            s2 *= s2;
            for (int i = 1; i < q.length; i++) {
                hq[i] += StdMath.exp(pre[i] * s2);
            }
        }
        for (int i = 1; i < q.length; i++) {
            hq[i] /= n;
        }
        expDecay = new double[q.length];
        expDecay[0] = 1;
        for (int i = 1; i < q.length; i++) {
            final double sinc_q = sinc(Math.PI * q[i]);
            expDecay[i] = sinc_q * sinc_q * hq[i];
        }
    } else {
        // Note: The sigma mean and std should be in the units of super-resolution
        // pixels so scale to SR pixels
        expDecay = computeExpDecay(histogram.mean / images.nmPerPixel, histogram.sigma / images.nmPerPixel, q);
    }
    // Smoothing
    double[] smooth;
    if (settings.loessSmoothing) {
        // Note: This computes the log then smooths it
        final double bandwidth = 0.1;
        final int robustness = 0;
        final double[] l = new double[expDecay.length];
        for (int i = 0; i < l.length; i++) {
            // Original Matlab code computes the log for each array.
            // This is equivalent to a single log on the fraction of the two.
            // Perhaps the two log method is more numerically stable.
            // l[i] = Math.log(Math.abs(frcnum[i])) - Math.log(exp_decay[i]);
            l[i] = Math.log(Math.abs(frcnum[i] / expDecay[i]));
        }
        try {
            final LoessInterpolator loess = new LoessInterpolator(bandwidth, robustness);
            smooth = loess.smooth(q, l);
        } catch (final Exception ex) {
            IJ.error(pluginTitle, "LOESS smoothing failed");
            return;
        }
    } else {
        // Note: This smooths the curve before computing the log
        final double[] norm = new double[expDecay.length];
        for (int i = 0; i < norm.length; i++) {
            norm[i] = frcnum[i] / expDecay[i];
        }
        // Median window of 5 == radius of 2
        final DoubleMedianWindow mw = DoubleMedianWindow.wrap(norm, 2);
        smooth = new double[expDecay.length];
        for (int i = 0; i < norm.length; i++) {
            smooth[i] = Math.log(Math.abs(mw.getMedian()));
            mw.increment();
        }
    }
    // Fit with quadratic to find the initial guess.
    // Note: example Matlab code frc_Qcorrection7.m identifies regions of the
    // smoothed log curve with low derivative and only fits those. The fit is
    // used for the final estimate. Fitting a subset with low derivative is not
    // implemented here since the initial estimate is subsequently optimised
    // to maximise a cost function.
    final Quadratic curve = new Quadratic();
    final SimpleCurveFitter fit = SimpleCurveFitter.create(curve, new double[2]);
    final WeightedObservedPoints points = new WeightedObservedPoints();
    for (int i = low; i < high; i++) {
        points.add(q[i], smooth[i]);
    }
    final double[] estimate = fit.fit(points.toList());
    double qvalue = StdMath.exp(estimate[0]);
    // This could be made an option. Just use for debugging
    final boolean debug = false;
    if (debug) {
        // Plot the initial fit and the fit curve
        final double[] qScaled = Frc.computeQ(frcCurve, true);
        final double[] line = new double[q.length];
        for (int i = 0; i < q.length; i++) {
            line[i] = curve.value(q[i], estimate);
        }
        final String title = pluginTitle + " Initial fit";
        final Plot plot = new Plot(title, "Spatial Frequency (nm^-1)", "FRC Numerator");
        final String label = String.format("Q = %.3f", qvalue);
        plot.addPoints(qScaled, smooth, Plot.LINE);
        plot.setColor(Color.red);
        plot.addPoints(qScaled, line, Plot.LINE);
        plot.setColor(Color.black);
        plot.addLabel(0, 0, label);
        ImageJUtils.display(title, plot, ImageJUtils.NO_TO_FRONT);
    }
    if (settings.fitPrecision) {
        // Q - Should this be optional?
        if (sampleDecay) {
            // If a sample of the precision was used to construct the data for the initial fit
            // then update the estimate using the fit result since it will be a better start point.
            histogram.sigma = precision.getStandardDeviation();
            // Normalise sum-of-squares to the SR pixel size
            final double meanSumOfSquares = (precision.getSumOfSquares() / (images.nmPerPixel * images.nmPerPixel)) / precision.getN();
            histogram.mean = images.nmPerPixel * Math.sqrt(meanSumOfSquares - estimate[1] / (4 * Math.PI * Math.PI));
        }
        // Do a multivariate fit ...
        final SimplexOptimizer opt = new SimplexOptimizer(1e-6, 1e-10);
        PointValuePair pair = null;
        final MultiPlateauness f = new MultiPlateauness(frcnum, q, low, high);
        final double[] initial = new double[] { histogram.mean / images.nmPerPixel, histogram.sigma / images.nmPerPixel, qvalue };
        pair = findMin(pair, opt, f, scale(initial, 0.1));
        pair = findMin(pair, opt, f, scale(initial, 0.5));
        pair = findMin(pair, opt, f, initial);
        pair = findMin(pair, opt, f, scale(initial, 2));
        pair = findMin(pair, opt, f, scale(initial, 10));
        if (pair != null) {
            final double[] point = pair.getPointRef();
            histogram.mean = point[0] * images.nmPerPixel;
            histogram.sigma = point[1] * images.nmPerPixel;
            qvalue = point[2];
        }
    } else {
        // If so then this should be optional.
        if (sampleDecay) {
            if (precisionMethod != PrecisionMethod.FIXED) {
                histogram.sigma = precision.getStandardDeviation();
                // Normalise sum-of-squares to the SR pixel size
                final double meanSumOfSquares = (precision.getSumOfSquares() / (images.nmPerPixel * images.nmPerPixel)) / precision.getN();
                histogram.mean = images.nmPerPixel * Math.sqrt(meanSumOfSquares - estimate[1] / (4 * Math.PI * Math.PI));
            }
            expDecay = computeExpDecay(histogram.mean / images.nmPerPixel, histogram.sigma / images.nmPerPixel, q);
        }
        // Estimate spurious component by promoting plateauness.
        // The Matlab code used random initial points for a Simplex optimiser.
        // A Brent line search should be pretty deterministic so do simple repeats.
        // However it will proceed downhill so if the initial point is wrong then
        // it will find a sub-optimal result.
        final UnivariateOptimizer o = new BrentOptimizer(1e-3, 1e-6);
        final Plateauness f = new Plateauness(frcnum, expDecay, low, high);
        UnivariatePointValuePair result = null;
        result = findMin(result, o, f, qvalue, 0.1);
        result = findMin(result, o, f, qvalue, 0.2);
        result = findMin(result, o, f, qvalue, 0.333);
        result = findMin(result, o, f, qvalue, 0.5);
        // Do some Simplex repeats as well
        final SimplexOptimizer opt = new SimplexOptimizer(1e-6, 1e-10);
        result = findMin(result, opt, f, qvalue * 0.1);
        result = findMin(result, opt, f, qvalue * 0.5);
        result = findMin(result, opt, f, qvalue);
        result = findMin(result, opt, f, qvalue * 2);
        result = findMin(result, opt, f, qvalue * 10);
        if (result != null) {
            qvalue = result.getPoint();
        }
    }
    final QPlot qplot = new QPlot(frcCurve, qvalue, low, high);
    // Interactive dialog to estimate Q (blinking events per flourophore) using
    // sliders for the mean and standard deviation of the localisation precision.
    showQEstimationDialog(histogram, qplot, images.nmPerPixel);
    IJ.showStatus(pluginTitle + " complete");
}
Also used : DoubleMedianWindow(uk.ac.sussex.gdsc.core.utils.DoubleMedianWindow) BrentOptimizer(org.apache.commons.math3.optim.univariate.BrentOptimizer) PointValuePair(org.apache.commons.math3.optim.PointValuePair) UnivariatePointValuePair(org.apache.commons.math3.optim.univariate.UnivariatePointValuePair) LoessInterpolator(org.apache.commons.math3.analysis.interpolation.LoessInterpolator) WeightedObservedPoints(org.apache.commons.math3.fitting.WeightedObservedPoints) FrcCurve(uk.ac.sussex.gdsc.smlm.ij.frc.Frc.FrcCurve) SimplexOptimizer(org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) FrcCurveResult(uk.ac.sussex.gdsc.smlm.ij.frc.Frc.FrcCurveResult) SimpleCurveFitter(org.apache.commons.math3.fitting.SimpleCurveFitter) Plot(ij.gui.Plot) HistogramPlot(uk.ac.sussex.gdsc.core.ij.HistogramPlot) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) UnivariatePointValuePair(org.apache.commons.math3.optim.univariate.UnivariatePointValuePair) WeightedObservedPoint(org.apache.commons.math3.fitting.WeightedObservedPoint) DataException(uk.ac.sussex.gdsc.core.data.DataException) ConversionException(uk.ac.sussex.gdsc.core.data.utils.ConversionException) Frc(uk.ac.sussex.gdsc.smlm.ij.frc.Frc) UnivariateOptimizer(org.apache.commons.math3.optim.univariate.UnivariateOptimizer)

Example 38 with Line

use of org.apache.commons.math3.geometry.euclidean.twod.Line in project GDSC-SMLM by aherbert.

the class PsfDrift method showHwhm.

private void showHwhm() {
    // Build a list of suitable images
    final List<String> titles = createImageList(false);
    if (titles.isEmpty()) {
        IJ.error(TITLE, "No suitable PSF images");
        return;
    }
    final GenericDialog gd = new GenericDialog(TITLE);
    gd.addMessage("Approximate the volume of the PSF as a Gaussian and\n" + "compute the equivalent Gaussian width.");
    settings = Settings.load();
    gd.addChoice("PSF", titles.toArray(new String[0]), settings.title);
    gd.addCheckbox("Use_offset", settings.useOffset);
    gd.addSlider("Smoothing", 0, 0.5, settings.smoothing);
    gd.addHelp(HelpUrls.getUrl("psf-hwhm"));
    gd.showDialog();
    if (gd.wasCanceled()) {
        return;
    }
    settings.title = gd.getNextChoice();
    settings.useOffset = gd.getNextBoolean();
    settings.smoothing = gd.getNextNumber();
    settings.save();
    imp = WindowManager.getImage(settings.title);
    if (imp == null) {
        IJ.error(TITLE, "No PSF image for image: " + settings.title);
        return;
    }
    psfSettings = getPsfSettings(imp);
    if (psfSettings == null) {
        IJ.error(TITLE, "No PSF settings for image: " + settings.title);
        return;
    }
    final int size = imp.getStackSize();
    final ImagePsfModel psf = createImagePsf(1, size, 1);
    final double[] w0 = psf.getAllHwhm0();
    final double[] w1 = psf.getAllHwhm1();
    // Get current centre
    final int centre = psfSettings.getCentreImage();
    // Extract valid values (some can be NaN)
    double[] sw0 = new double[w0.length];
    double[] sw1 = new double[w1.length];
    final TDoubleArrayList s0 = new TDoubleArrayList(w0.length);
    final TDoubleArrayList s1 = new TDoubleArrayList(w0.length);
    int c0 = 0;
    int c1 = 0;
    for (int i = 0; i < w0.length; i++) {
        if (Double.isFinite(w0[i])) {
            s0.add(i + 1);
            sw0[c0++] = w0[i];
        }
        if (Double.isFinite(w1[i])) {
            s1.add(i + 1);
            sw1[c1++] = w1[i];
        }
    }
    if (c0 == 0 && c1 == 0) {
        IJ.error(TITLE, "No computed HWHM for image: " + settings.title);
        return;
    }
    double[] slice0 = s0.toArray();
    sw0 = Arrays.copyOf(sw0, c0);
    double[] slice1 = s1.toArray();
    sw1 = Arrays.copyOf(sw1, c1);
    // Smooth
    if (settings.smoothing > 0) {
        final LoessInterpolator loess = new LoessInterpolator(settings.smoothing, 1);
        sw0 = loess.smooth(slice0, sw0);
        sw1 = loess.smooth(slice1, sw1);
    }
    final TDoubleArrayList minWx = new TDoubleArrayList();
    final TDoubleArrayList minWy = new TDoubleArrayList();
    for (int i = 0; i < w0.length; i++) {
        double weight = 0;
        if (Double.isFinite(w0[i])) {
            if (Double.isFinite(w1[i])) {
                weight = w0[i] * w1[i];
            } else {
                weight = w0[i] * w0[i];
            }
        } else if (Double.isFinite(w1[i])) {
            weight = w1[i] * w1[i];
        }
        if (weight != 0) {
            minWx.add(i + 1);
            minWy.add(Math.sqrt(weight));
        }
    }
    // Smooth the combined line
    final double[] cx = minWx.toArray();
    double[] cy = minWy.toArray();
    if (settings.smoothing > 0) {
        final LoessInterpolator loess = new LoessInterpolator(settings.smoothing, 1);
        cy = loess.smooth(cx, cy);
    }
    final int newCentre = SimpleArrayUtils.findMinIndex(cy);
    // Convert to FWHM
    final double fwhm = psfSettings.getFwhm();
    // Widths are in pixels
    final String title = TITLE + " HWHM";
    final Plot plot = new Plot(title, "Slice", "HWHM (px)");
    double[] limits = MathUtils.limits(sw0);
    limits = MathUtils.limits(limits, sw1);
    final double maxY = limits[1] * 1.05;
    plot.setLimits(1, size, 0, maxY);
    plot.setColor(Color.red);
    plot.addPoints(slice0, sw0, Plot.LINE);
    plot.setColor(Color.blue);
    plot.addPoints(slice1, sw1, Plot.LINE);
    plot.setColor(Color.magenta);
    plot.addPoints(cx, cy, Plot.LINE);
    plot.setColor(Color.black);
    plot.addLabel(0, 0, "X=red; Y=blue, Combined=Magenta");
    final PlotWindow pw = ImageJUtils.display(title, plot);
    // Show a non-blocking dialog to allow the centre to be updated ...
    // Add a label and dynamically update when the centre is moved.
    final NonBlockingExtendedGenericDialog gd2 = new NonBlockingExtendedGenericDialog(TITLE);
    final double scale = psfSettings.getPixelSize();
    // @formatter:off
    ImageJUtils.addMessage(gd2, "Update the PSF information?\n \n" + "Current z-centre = %d, FHWM = %s px (%s nm)\n", centre, MathUtils.rounded(fwhm), MathUtils.rounded(fwhm * scale));
    // @formatter:on
    gd2.addSlider("z-centre", cx[0], cx[cx.length - 1], newCentre);
    final TextField tf = gd2.getLastTextField();
    gd2.addMessage("");
    gd2.addAndGetButton("Reset", event -> tf.setText(Integer.toString(newCentre)));
    final Label label = gd2.getLastLabel();
    gd2.addCheckbox("Update_centre", settings.updateCentre);
    gd2.addCheckbox("Update_HWHM", settings.updateHwhm);
    gd2.enableYesNoCancel();
    gd2.hideCancelButton();
    final UpdateDialogListener dl = new UpdateDialogListener(cx, cy, maxY, newCentre, scale, pw, label);
    gd2.addDialogListener(dl);
    gd.addHelp(HelpUrls.getUrl("psf-hwhm"));
    gd2.showDialog();
    if (gd2.wasOKed() && (settings.updateCentre || settings.updateHwhm)) {
        final ImagePSF.Builder b = psfSettings.toBuilder();
        if (settings.updateCentre) {
            b.setCentreImage(dl.centre);
        }
        if (settings.updateHwhm) {
            b.setFwhm(dl.getFwhm());
        }
        imp.setProperty("Info", ImagePsfHelper.toString(b));
    }
}
Also used : Plot(ij.gui.Plot) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) Label(java.awt.Label) PlotWindow(ij.gui.PlotWindow) LoessInterpolator(org.apache.commons.math3.analysis.interpolation.LoessInterpolator) TDoubleArrayList(gnu.trove.list.array.TDoubleArrayList) ImagePSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) GenericDialog(ij.gui.GenericDialog) TextField(java.awt.TextField) ImagePsfModel(uk.ac.sussex.gdsc.smlm.model.ImagePsfModel)

Example 39 with Line

use of org.apache.commons.math3.geometry.euclidean.twod.Line in project recordinality by cscotta.

the class RecordinalityTest method buildRun.

private Callable<Result> buildRun(final int kSize, final int numRuns, final List<String> lines) {
    return new Callable<Result>() {

        public Result call() throws Exception {
            long start = System.currentTimeMillis();
            final double[] results = new double[numRuns];
            for (int i = 0; i < numRuns; i++) {
                Recordinality rec = new Recordinality(kSize);
                for (String line : lines) rec.observe(line);
                results[i] = rec.estimateCardinality();
            }
            double mean = new Mean().evaluate(results);
            double stdDev = new StandardDeviation().evaluate(results);
            double stdError = stdDev / 3193;
            long runTime = System.currentTimeMillis() - start;
            return new Result(kSize, mean, stdError, runTime);
        }
    };
}
Also used : Mean(org.apache.commons.math3.stat.descriptive.moment.Mean) StandardDeviation(org.apache.commons.math3.stat.descriptive.moment.StandardDeviation)

Aggregations

ArrayList (java.util.ArrayList)10 List (java.util.List)8 PointValuePair (org.apache.commons.math3.optim.PointValuePair)8 Line (org.twak.utils.Line)8 Plot2 (ij.gui.Plot2)7 HashSet (java.util.HashSet)7 Map (java.util.Map)7 Set (java.util.Set)7 Collectors (java.util.stream.Collectors)7 Point2d (javax.vecmath.Point2d)7 Collections (java.util.Collections)6 Pair (org.twak.utils.Pair)6 Iterator (java.util.Iterator)5 Point3d (javax.vecmath.Point3d)5 Vector2d (javax.vecmath.Vector2d)5 LoessInterpolator (org.apache.commons.math3.analysis.interpolation.LoessInterpolator)4 ConvergenceException (org.apache.commons.math3.exception.ConvergenceException)4 TooManyIterationsException (org.apache.commons.math3.exception.TooManyIterationsException)4 SimpleValueChecker (org.apache.commons.math3.optim.SimpleValueChecker)4 Mathz (org.twak.utils.Mathz)4