Search in sources :

Example 1 with BlockMeanFilter

use of uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter in project GDSC-SMLM by aherbert.

the class GaussianFit method runFinal.

/**
 * Perform fitting using the chosen maxima. Update the overlay if successful.
 *
 * @param ip The input image
 */
private void runFinal(ImageProcessor ip) {
    ip.reset();
    final Rectangle bounds = ip.getRoi();
    // Crop to the ROI
    final float[] data = ImageJImageConverter.getData(ip);
    final int width = bounds.width;
    final int height = bounds.height;
    // Sort the maxima
    float[] smoothData = data;
    if (getSmooth() > 0) {
        // Smoothing destructively modifies the data so create a copy
        smoothData = Arrays.copyOf(data, width * height);
        final BlockMeanFilter filter = new BlockMeanFilter();
        if (settings.smooth <= settings.border) {
            filter.stripedBlockFilterInternal(smoothData, width, height, (float) settings.smooth);
        } else {
            filter.stripedBlockFilter(smoothData, width, height, (float) settings.smooth);
        }
    }
    SortUtils.sortIndices(maxIndices, smoothData, true);
    // Show the candidate peaks
    if (maxIndices.length > 0) {
        final String message = String.format("Identified %d peaks", maxIndices.length);
        if (isLogProgress()) {
            IJ.log(message);
            for (final int index : maxIndices) {
                IJ.log(String.format("  %.2f @ [%d,%d]", data[index], bounds.x + index % width, bounds.y + index / width));
            }
        }
        // Check whether to run if the number of peaks is large
        if (maxIndices.length > 10) {
            final GenericDialog gd = new GenericDialog("Warning");
            gd.addMessage(message + "\nDo you want to fit?");
            gd.showDialog();
            if (gd.wasCanceled()) {
                return;
            }
        }
    } else {
        IJ.log("No maxima identified");
        return;
    }
    results = new ImageJTablePeakResults(settings.showDeviations, imp.getTitle() + " [" + imp.getCurrentSlice() + "]");
    final CalibrationWriter cw = new CalibrationWriter();
    cw.setIntensityUnit(IntensityUnit.COUNT);
    cw.setDistanceUnit(DistanceUnit.PIXEL);
    cw.setAngleUnit(AngleUnit.RADIAN);
    results.setCalibration(cw.getCalibration());
    results.setPsf(PsfProtosHelper.getDefaultPsf(getPsfType()));
    results.setShowFittingData(true);
    results.setAngleUnit(AngleUnit.DEGREE);
    results.begin();
    // Perform the Gaussian fit
    long ellapsed = 0;
    final FloatProcessor renderedImage = settings.showFit ? new FloatProcessor(ip.getWidth(), ip.getHeight()) : null;
    if (!settings.singleFit) {
        if (isLogProgress()) {
            IJ.log("Combined fit");
        }
        // Estimate height from smoothed data
        final double[] estimatedHeights = new double[maxIndices.length];
        for (int i = 0; i < estimatedHeights.length; i++) {
            estimatedHeights[i] = smoothData[maxIndices[i]];
        }
        final FitConfiguration config = new FitConfiguration();
        setupPeakFiltering(config);
        final long time = System.nanoTime();
        final double[] params = fitMultiple(data, width, height, maxIndices, estimatedHeights);
        ellapsed = System.nanoTime() - time;
        if (params != null) {
            // Copy all the valid parameters into a new array
            final double[] validParams = new double[params.length];
            int count = 0;
            int validPeaks = 0;
            validParams[count++] = params[0];
            final double[] initialParams = convertParameters(fitResult.getInitialParameters());
            final double[] paramsDev = convertParameters(fitResult.getParameterDeviations());
            final Rectangle regionBounds = new Rectangle();
            final float[] xpoints = new float[maxIndices.length];
            final float[] ypoints = new float[maxIndices.length];
            int npoints = 0;
            for (int i = 1, n = 0; i < params.length; i += Gaussian2DFunction.PARAMETERS_PER_PEAK, n++) {
                final int y = maxIndices[n] / width;
                final int x = maxIndices[n] % width;
                // Check the peak is a good fit
                if (settings.filterResults && config.validatePeak(n, initialParams, params, paramsDev) != FitStatus.OK) {
                    continue;
                }
                if (settings.showFit) {
                    // Copy the valid parameters before there are adjusted to global bounds
                    validPeaks++;
                    for (int ii = i, j = 0; j < Gaussian2DFunction.PARAMETERS_PER_PEAK; ii++, j++) {
                        validParams[count++] = params[ii];
                    }
                }
                final double[] peakParams = extractParams(params, i);
                final double[] peakParamsDev = extractParams(paramsDev, i);
                addResult(bounds, regionBounds, peakParams, peakParamsDev, npoints, x, y, data[maxIndices[n]]);
                // Add fit result to the overlay - Coords are updated with the region offsets in addResult
                final double xf = peakParams[Gaussian2DFunction.X_POSITION];
                final double yf = peakParams[Gaussian2DFunction.Y_POSITION];
                xpoints[npoints] = (float) xf;
                ypoints[npoints] = (float) yf;
                npoints++;
            }
            setOverlay(npoints, xpoints, ypoints);
            // Draw the fit
            if (validPeaks != 0) {
                addToImage(bounds.x, bounds.y, renderedImage, validParams, validPeaks, width, height);
            }
        } else {
            if (isLogProgress()) {
                IJ.log("Failed to fit " + TextUtils.pleural(maxIndices.length, "peak") + ": " + getReason(fitResult));
            }
            imp.setOverlay(null);
        }
    } else {
        if (isLogProgress()) {
            IJ.log("Individual fit");
        }
        int npoints = 0;
        final float[] xpoints = new float[maxIndices.length];
        final float[] ypoints = new float[maxIndices.length];
        // Extract each peak and fit individually
        final ImageExtractor ie = ImageExtractor.wrap(data, width, height);
        float[] region = null;
        final Gaussian2DFitter gf = createGaussianFitter(settings.filterResults);
        double[] validParams = null;
        final ShortProcessor renderedImageCount = settings.showFit ? new ShortProcessor(ip.getWidth(), ip.getHeight()) : null;
        for (int n = 0; n < maxIndices.length; n++) {
            final int y = maxIndices[n] / width;
            final int x = maxIndices[n] % width;
            final long time = System.nanoTime();
            final Rectangle regionBounds = ie.getBoxRegionBounds(x, y, settings.singleRegionSize);
            region = ie.crop(regionBounds, region);
            final int newIndex = (y - regionBounds.y) * regionBounds.width + x - regionBounds.x;
            if (isLogProgress()) {
                IJ.log("Fitting peak " + (n + 1));
            }
            final double[] peakParams = fitSingle(gf, region, regionBounds.width, regionBounds.height, newIndex, smoothData[maxIndices[n]]);
            ellapsed += System.nanoTime() - time;
            // Output fit result
            if (peakParams != null) {
                if (settings.showFit) {
                    // Copy the valid parameters before there are adjusted to global bounds
                    validParams = peakParams.clone();
                }
                double[] peakParamsDev = null;
                if (settings.showDeviations) {
                    peakParamsDev = convertParameters(fitResult.getParameterDeviations());
                }
                addResult(bounds, regionBounds, peakParams, peakParamsDev, n, x, y, data[maxIndices[n]]);
                // Add fit result to the overlay - Coords are updated with the region offsets in addResult
                final double xf = peakParams[Gaussian2DFunction.X_POSITION];
                final double yf = peakParams[Gaussian2DFunction.Y_POSITION];
                xpoints[npoints] = (float) xf;
                ypoints[npoints] = (float) yf;
                npoints++;
                // Draw the fit
                if (settings.showDeviations) {
                    final int ox = bounds.x + regionBounds.x;
                    final int oy = bounds.y + regionBounds.y;
                    addToImage(ox, oy, renderedImage, validParams, 1, regionBounds.width, regionBounds.height);
                    addCount(ox, oy, renderedImageCount, regionBounds.width, regionBounds.height);
                }
            } else if (isLogProgress()) {
                IJ.log("Failed to fit peak " + (n + 1) + ": " + getReason(fitResult));
            }
        }
        // Update the overlay
        if (npoints > 0) {
            setOverlay(npoints, xpoints, ypoints);
        } else {
            imp.setOverlay(null);
        }
        // Create the mean
        if (settings.showFit) {
            for (int i = renderedImageCount.getPixelCount(); i-- > 0; ) {
                final int count = renderedImageCount.get(i);
                if (count > 1) {
                    renderedImage.setf(i, renderedImage.getf(i) / count);
                }
            }
        }
    }
    results.end();
    if (renderedImage != null) {
        ImageJUtils.display(TITLE, renderedImage);
    }
    if (isLogProgress()) {
        IJ.log("Time = " + (ellapsed / 1000000.0) + "ms");
    }
}
Also used : FloatProcessor(ij.process.FloatProcessor) Gaussian2DFitter(uk.ac.sussex.gdsc.smlm.fitting.Gaussian2DFitter) Rectangle(java.awt.Rectangle) ImageJTablePeakResults(uk.ac.sussex.gdsc.smlm.ij.results.ImageJTablePeakResults) ShortProcessor(ij.process.ShortProcessor) BlockMeanFilter(uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) GenericDialog(ij.gui.GenericDialog) CalibrationWriter(uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter) ImageExtractor(uk.ac.sussex.gdsc.core.utils.ImageExtractor)

Example 2 with BlockMeanFilter

use of uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter in project GDSC-SMLM by aherbert.

the class GaussianFit method run.

@Override
public void run(ImageProcessor ip) {
    final Rectangle bounds = ip.getRoi();
    // Crop to the ROI
    final float[] data = ImageJImageConverter.getData(ip);
    final int width = bounds.width;
    final int height = bounds.height;
    if (getSmooth() > 0) {
        // No need for a copy since we are using a snapshot buffer
        final BlockMeanFilter filter = new BlockMeanFilter();
        filter.stripedBlockFilter(data, width, height, (float) getSmooth());
    }
    maxIndices = getMaxima(data, width, height);
    if (settings.topN > 0 && maxIndices.length > settings.topN) {
        SortUtils.sortIndices(maxIndices, data, true);
        maxIndices = Arrays.copyOf(maxIndices, settings.topN);
    }
    // Show an overlay of the indices
    if (maxIndices.length > 0) {
        final int nMaxima = maxIndices.length;
        final float[] xpoints = new float[nMaxima];
        final float[] ypoints = new float[nMaxima];
        int count = 0;
        for (final int index : maxIndices) {
            final int x = index % width;
            final int y = index / width;
            xpoints[count] = 0.5f + bounds.x + x;
            ypoints[count] = 0.5f + bounds.y + y;
            count++;
        }
        setOverlay(nMaxima, xpoints, ypoints);
    } else {
        imp.setOverlay(null);
    }
    for (int index = data.length; index-- > 0; ) {
        ip.setf(bounds.x + index % width, bounds.y + index / width, data[index]);
    }
}
Also used : BlockMeanFilter(uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter) Rectangle(java.awt.Rectangle)

Example 3 with BlockMeanFilter

use of uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter in project GDSC-SMLM by aherbert.

the class PsfCreator method getLimitsPerSlice.

/**
 * Gets the min and max limits per slice.
 *
 * <p>Smooths the PSF block region data before analysis.
 *
 * @param psf the psf
 * @param maxx the maxx
 * @param maxy the maxy
 * @param n the block size of the region
 * @return the limits per slice
 */
private static float[][] getLimitsPerSlice(float[][] psf, int maxx, int maxy, int n) {
    final BlockMeanFilter filter = new BlockMeanFilter();
    final float[][] limits = new float[2][psf.length];
    for (int zz = 0; zz < psf.length; zz++) {
        float[] data = psf[zz];
        if (n > 0) {
            data = data.clone();
            filter.rollingBlockFilterInternal(data, maxx, maxy, n);
        }
        final float[] l = findLimits(data, maxx, maxy, n);
        limits[0][zz] = l[0];
        limits[1][zz] = l[1];
    // float[] l2 = Maths.limits(data);
    // System.out.printf("%f - %f vs %f - %f\n", l[0], l[1], l2[0], l2[1]);
    }
    return limits;
}
Also used : BlockMeanFilter(uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter) Point(java.awt.Point) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint)

Aggregations

BlockMeanFilter (uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter)3 Rectangle (java.awt.Rectangle)2 GenericDialog (ij.gui.GenericDialog)1 FloatProcessor (ij.process.FloatProcessor)1 ShortProcessor (ij.process.ShortProcessor)1 Point (java.awt.Point)1 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)1 BasePoint (uk.ac.sussex.gdsc.core.match.BasePoint)1 ImageExtractor (uk.ac.sussex.gdsc.core.utils.ImageExtractor)1 CalibrationWriter (uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter)1 FitConfiguration (uk.ac.sussex.gdsc.smlm.engine.FitConfiguration)1 Gaussian2DFitter (uk.ac.sussex.gdsc.smlm.fitting.Gaussian2DFitter)1 ImageJTablePeakResults (uk.ac.sussex.gdsc.smlm.ij.results.ImageJTablePeakResults)1