Search in sources :

Example 1 with InterlacedImageSource

use of uk.ac.sussex.gdsc.smlm.results.InterlacedImageSource in project GDSC-SMLM by aherbert.

the class PsfEstimator method calculateStatistics.

private boolean calculateStatistics(PeakFit fitter, double[] params, double[] paramsDev) {
    debug("  Fitting PSF");
    swapStatistics();
    // Create the fit engine using the PeakFit plugin
    final FitConfiguration fitConfig = config.getFitConfiguration();
    fitConfig.setInitialPeakStdDev0((float) params[1]);
    try {
        fitConfig.setInitialPeakStdDev1((float) params[2]);
        fitConfig.setInitialAngle((float) Math.toRadians(params[0]));
    } catch (IllegalStateException ex) {
    // Ignore this as the current PSF is not a 2 axis and theta Gaussian PSF
    }
    final ImageStack stack = imp.getImageStack();
    final Rectangle roi = stack.getProcessor(1).getRoi();
    ImageSource source = new IJImageSource(imp);
    // Allow interlaced data by wrapping the image source
    if (interlacedData) {
        source = new InterlacedImageSource(source, dataStart, dataBlock, dataSkip);
    }
    // Allow frame aggregation by wrapping the image source
    if (integrateFrames > 1) {
        source = new AggregatedImageSource(source, integrateFrames);
    }
    fitter.initialiseImage(source, roi, true);
    fitter.addPeakResults(this);
    fitter.initialiseFitting();
    final FitEngine engine = fitter.createFitEngine();
    // Use random slices
    final int[] slices = new int[stack.getSize()];
    for (int i = 0; i < slices.length; i++) {
        slices[i] = i + 1;
    }
    RandomUtils.shuffle(slices, UniformRandomProviders.create());
    IJ.showStatus("Fitting ...");
    // Use multi-threaded code for speed
    int sliceIndex;
    for (sliceIndex = 0; sliceIndex < slices.length; sliceIndex++) {
        final int slice = slices[sliceIndex];
        IJ.showProgress(size(), settings.getNumberOfPeaks());
        final ImageProcessor ip = stack.getProcessor(slice);
        // stack processor does not set the bounds required by ImageConverter
        ip.setRoi(roi);
        final FitJob job = new FitJob(slice, ImageJImageConverter.getData(ip), roi);
        engine.run(job);
        if (sampleSizeReached() || ImageJUtils.isInterrupted()) {
            break;
        }
    }
    if (ImageJUtils.isInterrupted()) {
        IJ.showProgress(1);
        engine.end(true);
        return false;
    }
    // Wait until we have enough results
    while (!sampleSizeReached() && !engine.isQueueEmpty()) {
        IJ.showProgress(size(), settings.getNumberOfPeaks());
        try {
            Thread.sleep(50);
        } catch (final InterruptedException ex) {
            Thread.currentThread().interrupt();
            throw new ConcurrentRuntimeException("Unexpected interruption", ex);
        }
    }
    // End now if we have enough samples
    engine.end(sampleSizeReached());
    ImageJUtils.finished();
    // This count will be an over-estimate given that the provider is ahead of the consumer
    // in this multi-threaded system
    debug("  Processed %d/%d slices (%d peaks)", sliceIndex, slices.length, size());
    setParams(ANGLE, params, paramsDev, sampleNew[ANGLE]);
    setParams(X, params, paramsDev, sampleNew[X]);
    setParams(Y, params, paramsDev, sampleNew[Y]);
    if (settings.getShowHistograms()) {
        final HistogramPlotBuilder builder = new HistogramPlotBuilder(TITLE).setNumberOfBins(settings.getHistogramBins());
        final WindowOrganiser wo = new WindowOrganiser();
        for (int ii = 0; ii < 3; ii++) {
            if (sampleNew[ii].getN() == 0) {
                continue;
            }
            final StoredDataStatistics stats = StoredDataStatistics.create(sampleNew[ii].getValues());
            builder.setData(stats).setName(NAMES[ii]).setPlotLabel("Mean = " + MathUtils.rounded(stats.getMean()) + ". Median = " + MathUtils.rounded(sampleNew[ii].getPercentile(50))).show(wo);
        }
        wo.tile();
    }
    if (size() < 2) {
        log("ERROR: Insufficient number of fitted peaks, terminating ...");
        return false;
    }
    return true;
}
Also used : InterlacedImageSource(uk.ac.sussex.gdsc.smlm.results.InterlacedImageSource) AggregatedImageSource(uk.ac.sussex.gdsc.smlm.results.AggregatedImageSource) ImageStack(ij.ImageStack) Rectangle(java.awt.Rectangle) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) HistogramPlotBuilder(uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) IJImageSource(uk.ac.sussex.gdsc.smlm.ij.IJImageSource) ImageProcessor(ij.process.ImageProcessor) FitEngine(uk.ac.sussex.gdsc.smlm.engine.FitEngine) ConcurrentRuntimeException(org.apache.commons.lang3.concurrent.ConcurrentRuntimeException) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration) ImageSource(uk.ac.sussex.gdsc.smlm.results.ImageSource) IJImageSource(uk.ac.sussex.gdsc.smlm.ij.IJImageSource) InterlacedImageSource(uk.ac.sussex.gdsc.smlm.results.InterlacedImageSource) AggregatedImageSource(uk.ac.sussex.gdsc.smlm.results.AggregatedImageSource) FitJob(uk.ac.sussex.gdsc.smlm.engine.FitJob)

Example 2 with InterlacedImageSource

use of uk.ac.sussex.gdsc.smlm.results.InterlacedImageSource in project GDSC-SMLM by aherbert.

the class PeakFit method showDialog.

private int showDialog(ImagePlus imp) {
    // Executing as an ImageJ plugin.
    // Load the settings
    resultsSettings = SettingsManager.readResultsSettings(0).toBuilder();
    // Settings are within the FitEngineSettings
    config = SettingsManager.readFitEngineConfiguration(0);
    fitConfig = config.getFitConfiguration();
    settings = Settings.load();
    if (simpleFit) {
        return showSimpleDialog();
    }
    // Note: The bounds are not set when running in the fit maxima option (since all candidates
    // have been identified already the crop is not required).
    final boolean isCrop = (bounds != null && imp != null && (bounds.width < imp.getWidth() || bounds.height < imp.getHeight()));
    // Some options are not always needed
    if (extraOptions || isCrop) {
        extraSettings = ExtraSettings.load();
        ignoreBoundsForNoise = extraSettings.optionIgnoreBoundsForNoise;
    }
    if (!extraOptions) {
        resultsSettings.getResultsImageSettingsBuilder().setRollingWindowSize(0);
        fitConfig.setBackgroundFitting(true);
        fitConfig.setNoise(0);
        config.setNoiseMethod(NoiseEstimatorMethod.QUICK_RESIDUALS_LEAST_MEAN_OF_SQUARES);
    }
    final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
    String helpKey;
    if (maximaIdentification) {
        helpKey = "spot-finder";
        gd.addMessage("Identify candidate maxima");
    } else {
        helpKey = "peak-fit";
        gd.addMessage("Fit 2D Gaussian to identified maxima");
    }
    // Note: Currently is is not useful to append "-series" when running for a series image
    // source since the params in this dialog do not concern the image input.
    gd.addHelp(HelpUrls.getUrl(helpKey));
    final String[] templates = ConfigurationTemplate.getTemplateNames(true);
    gd.addChoice("Template", templates, templates[0]);
    final CalibrationReader calibration = fitConfig.getCalibrationReader();
    addCameraOptions(gd, 0, fitConfig);
    gd.addNumericField("Calibration", calibration.getNmPerPixel(), 2, 6, "nm/px");
    gd.addNumericField("Exposure_time", calibration.getExposureTime(), 2, 6, "ms");
    if (isCrop) {
        gd.addCheckbox("Ignore_bounds_for_noise", ignoreBoundsForNoise);
    }
    final FitConfigurationProvider fitConfigurationProvider = () -> fitConfig;
    final FitEngineConfigurationProvider fitEngineConfigurationProvider = () -> config;
    addPsfOptions(gd, fitConfigurationProvider);
    addDataFilterOptions(gd, fitEngineConfigurationProvider);
    addSearchOptions(gd, fitEngineConfigurationProvider);
    addBorderOptions(gd, fitEngineConfigurationProvider);
    addFittingOptions(gd, fitEngineConfigurationProvider);
    if (extraOptions && !fitMaxima) {
        gd.addCheckbox("Interlaced_data", extraSettings.interlacedData);
        gd.addSlider("Integrate_frames", 1, 5, extraSettings.integrateFrames);
    }
    // Special case top get the slider since the GenericDialog does not provide access to this.
    Scrollbar sliderCoordinateShiftFactor = null;
    final boolean isShowGenericDialog = ImageJUtils.isShowGenericDialog();
    if (!maximaIdentification) {
        gd.addMessage("--- Gaussian fitting ---");
        gd.addChoice("Fit_solver", SettingsManager.getFitSolverNames(), FitProtosHelper.getName(fitConfig.getFitSolver()));
        if (extraOptions) {
            gd.addCheckbox("Fit_background", fitConfig.isBackgroundFitting());
        }
        // Parameters specific to each Fit solver are collected in a second dialog
        gd.addNumericField("Fail_limit", config.getFailuresLimit(), 0);
        gd.addNumericField("Pass_rate", config.getPassRate(), 2);
        gd.addCheckbox("Include_neighbours", config.isIncludeNeighbours());
        gd.addSlider("Neighbour_height", 0.01, 1, config.getNeighbourHeightThreshold());
        gd.addSlider("Residuals_threshold", 0.01, 1, config.getResidualsThreshold());
        addDuplicateDistanceOptions(gd, fitEngineConfigurationProvider);
        gd.addMessage("--- Peak filtering ---\nDiscard fits that shift; are too low; or expand/contract");
        gd.addCheckbox("Smart_filter", fitConfig.isSmartFilter());
        gd.addCheckbox("Disable_simple_filter", fitConfig.isDisableSimpleFilter());
        gd.addSlider("Shift_factor", 0.0, 2.5, fitConfig.getCoordinateShiftFactor());
        if (isShowGenericDialog) {
            sliderCoordinateShiftFactor = gd.getLastScrollbar();
        }
        gd.addNumericField("Signal_strength", fitConfig.getSignalStrength(), 2);
        gd.addNumericField("Min_photons", fitConfig.getMinPhotons(), 0);
        if (extraOptions) {
            gd.addNumericField("Noise", fitConfig.getNoise(), 2);
            gd.addChoice("Noise_method", SettingsManager.getNoiseEstimatorMethodNames(), config.getNoiseMethod().ordinal());
        }
        gd.addSlider("Min_width_factor", 0, 0.99, fitConfig.getMinWidthFactor());
        gd.addSlider("Width_factor", 1, 4.5, fitConfig.getMaxWidthFactor());
        addPrecisionOptions(gd, fitConfigurationProvider);
    // Q. Add dynamically displayed options for z-filtering here?
    }
    gd.addMessage("--- Results ---");
    gd.addCheckbox("Log_progress", resultsSettings.getLogProgress());
    if (!maximaIdentification) {
        gd.addCheckbox("Show_deviations", resultsSettings.getShowDeviations());
    }
    ResultsManager.addTableResultsOptions(gd, resultsSettings);
    ResultsManager.addImageResultsOptions(gd, resultsSettings, (extraOptions) ? ResultsManager.FLAG_EXTRA_OPTIONS : 0);
    if (extraOptions) {
        gd.addCheckbox("Show_processed_frames", extraSettings.showProcessedFrames);
    }
    ResultsManager.addFileResultsOptions(gd, resultsSettings, ResultsManager.FLAG_RESULTS_DIRECTORY);
    ResultsManager.addInMemoryResultsOptions(gd, resultsSettings);
    if (extraOptions) {
        gd.addMessage("--- Misc ---");
        gd.addSlider("Fraction_of_threads", 0.1, 1, settings.fractionOfThreads);
    }
    // Add a mouse listener to the config file field
    if (isShowGenericDialog) {
        new ItemDialogListener(sliderCoordinateShiftFactor).attach(gd, isCrop);
    }
    gd.showDialog();
    if (gd.wasCanceled() || !readDialog(gd, isCrop)) {
        return DONE;
    }
    if (imp != null) {
        // Store whether the user selected to process all the images.
        final int flags = IJ.setupDialog(imp, pluginFlags);
        // Check if cancelled
        if ((flags & DONE) != 0) {
            return DONE;
        }
        if ((flags & DOES_STACKS) == 0) {
            // Save the slice number for the overlay
            singleFrame = imp.getCurrentSlice();
            // Account for interlaced data
            if (extraSettings.interlacedData) {
                int start = singleFrame;
                // Calculate the first frame that is not skipped
                while (ignoreFrame(start) && start > extraSettings.dataStart) {
                    start--;
                }
                if (start < extraSettings.dataStart) {
                    log("The current frame (%d) is before the start of the interlaced data", singleFrame);
                    return DONE;
                }
                if (start != singleFrame) {
                    log("Updated the current frame (%d) to a valid interlaced data frame (%d)", singleFrame, start);
                }
                singleFrame = start;
            }
            // Account for integrated frames
            int endFrame = singleFrame;
            if (extraSettings.integrateFrames > 1) {
                int totalFrames = 1;
                while (totalFrames < extraSettings.integrateFrames) {
                    endFrame++;
                    if (!ignoreFrame(endFrame)) {
                        totalFrames++;
                    }
                }
                log("Updated the image end frame (%d) to %d allow %d integrated frames", singleFrame, endFrame, extraSettings.integrateFrames);
            }
            // Create a new image source with the correct frames
            setSource(new IJImageSource(imp, singleFrame, endFrame - singleFrame));
            // Store the image so the results can be added as an overlay
            this.imp = imp;
            this.imp.setOverlay(null);
        }
    }
    // Allow interlaced data by wrapping the image source
    if (extraSettings.interlacedData) {
        setSource(new InterlacedImageSource(this.source, extraSettings.dataStart, extraSettings.dataBlock, extraSettings.dataSkip));
    }
    // Allow frame aggregation by wrapping the image source
    if (extraSettings.integrateFrames > 1) {
        setSource(new AggregatedImageSource(this.source, extraSettings.integrateFrames));
    }
    // Ask if the user wants to log progress on multiple frame images
    if (resultsSettings.getLogProgress() && source.getFrames() > 1) {
        final ExtendedGenericDialog egd = new ExtendedGenericDialog(TITLE);
        egd.addMessage("Warning: Log progress on multiple-frame image will be slow");
        egd.addCheckbox("Log_progress", true);
        egd.showDialog();
        if (egd.wasCanceled()) {
            return DONE;
        }
        if (!egd.getNextBoolean()) {
            resultsSettings.setLogProgress(false);
            SettingsManager.writeSettings(resultsSettings.build());
        }
    }
    // single call to be made.
    return pluginFlags;
}
Also used : InterlacedImageSource(uk.ac.sussex.gdsc.smlm.results.InterlacedImageSource) AggregatedImageSource(uk.ac.sussex.gdsc.smlm.results.AggregatedImageSource) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) CalibrationReader(uk.ac.sussex.gdsc.smlm.data.config.CalibrationReader) IJImageSource(uk.ac.sussex.gdsc.smlm.ij.IJImageSource) Scrollbar(java.awt.Scrollbar)

Aggregations

IJImageSource (uk.ac.sussex.gdsc.smlm.ij.IJImageSource)2 AggregatedImageSource (uk.ac.sussex.gdsc.smlm.results.AggregatedImageSource)2 InterlacedImageSource (uk.ac.sussex.gdsc.smlm.results.InterlacedImageSource)2 ImageStack (ij.ImageStack)1 ImageProcessor (ij.process.ImageProcessor)1 Rectangle (java.awt.Rectangle)1 Scrollbar (java.awt.Scrollbar)1 ConcurrentRuntimeException (org.apache.commons.lang3.concurrent.ConcurrentRuntimeException)1 HistogramPlotBuilder (uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder)1 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)1 WindowOrganiser (uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser)1 StoredDataStatistics (uk.ac.sussex.gdsc.core.utils.StoredDataStatistics)1 CalibrationReader (uk.ac.sussex.gdsc.smlm.data.config.CalibrationReader)1 FitConfiguration (uk.ac.sussex.gdsc.smlm.engine.FitConfiguration)1 FitEngine (uk.ac.sussex.gdsc.smlm.engine.FitEngine)1 FitJob (uk.ac.sussex.gdsc.smlm.engine.FitJob)1 ImageSource (uk.ac.sussex.gdsc.smlm.results.ImageSource)1