Search in sources :

Example 6 with FitEngineConfiguration

use of gdsc.smlm.engine.FitEngineConfiguration in project GDSC-SMLM by aherbert.

the class PSFEstimator method setup.

/*
	 * (non-Javadoc)
	 * 
	 * @see ij.plugin.filter.PlugInFilter#setup(java.lang.String, ij.ImagePlus)
	 */
public int setup(String arg, ImagePlus imp) {
    SMLMUsageTracker.recordPlugin(this.getClass(), arg);
    extraOptions = Utils.isExtraOptions();
    if (imp == null) {
        IJ.noImage();
        return DONE;
    }
    globalSettings = SettingsManager.loadSettings();
    settings = globalSettings.getPsfEstimatorSettings();
    // Reset
    if (IJ.controlKeyDown()) {
        config = new FitEngineConfiguration(new FitConfiguration());
        globalSettings.setFitEngineConfiguration(config);
    } else {
        config = globalSettings.getFitEngineConfiguration();
    }
    Roi roi = imp.getRoi();
    if (roi != null && roi.getType() != Roi.RECTANGLE) {
        IJ.error("Rectangular ROI required");
        return DONE;
    }
    return showDialog(imp);
}
Also used : FitEngineConfiguration(gdsc.smlm.engine.FitEngineConfiguration) FitConfiguration(gdsc.smlm.fitting.FitConfiguration) Roi(ij.gui.Roi)

Example 7 with FitEngineConfiguration

use of gdsc.smlm.engine.FitEngineConfiguration in project GDSC-SMLM by aherbert.

the class BenchmarkFilterAnalysis method createResults.

/**
	 * Create peak results.
	 *
	 * @param filterResults
	 *            The results from running the filter (or null)
	 * @param filter
	 *            the filter
	 */
private MemoryPeakResults createResults(PreprocessedPeakResult[] filterResults, DirectFilter filter, boolean withBorder) {
    if (filterResults == null) {
        final MultiPathFilter multiPathFilter = createMPF(filter, minimalFilter);
        //multiPathFilter.setDebugFile("/tmp/filter.txt");
        filterResults = filterResults(multiPathFilter);
    }
    MemoryPeakResults results = new MemoryPeakResults();
    results.copySettings(this.results);
    results.setName(TITLE);
    if (withBorder) {
        // To produce the same results as the PeakFit plugin we must implement the border
        // functionality used in the FitWorker. This respects the border of the spot filter.
        FitEngineConfiguration config = new FitEngineConfiguration(new FitConfiguration());
        updateAllConfiguration(config);
        MaximaSpotFilter spotFilter = config.createSpotFilter(true);
        final int border = spotFilter.getBorder();
        int[] bounds = getBounds();
        final int borderLimitX = bounds[0] - border;
        final int borderLimitY = bounds[1] - border;
        for (PreprocessedPeakResult spot : filterResults) {
            if (spot.getX() > border && spot.getX() < borderLimitX && spot.getY() > border && spot.getY() < borderLimitY) {
                double[] p = spot.toGaussian2DParameters();
                float[] params = new float[p.length];
                for (int j = 0; j < p.length; j++) params[j] = (float) p[j];
                int frame = spot.getFrame();
                int origX = (int) p[Gaussian2DFunction.X_POSITION];
                int origY = (int) p[Gaussian2DFunction.Y_POSITION];
                results.addf(frame, origX, origY, 0, 0, spot.getNoise(), params, null);
            }
        }
    } else {
        for (PreprocessedPeakResult spot : filterResults) {
            double[] p = spot.toGaussian2DParameters();
            float[] params = new float[p.length];
            for (int j = 0; j < p.length; j++) params[j] = (float) p[j];
            int frame = spot.getFrame();
            int origX = (int) p[Gaussian2DFunction.X_POSITION];
            int origY = (int) p[Gaussian2DFunction.Y_POSITION];
            results.addf(frame, origX, origY, 0, 0, spot.getNoise(), params, null);
        }
    }
    return results;
}
Also used : FitEngineConfiguration(gdsc.smlm.engine.FitEngineConfiguration) FitConfiguration(gdsc.smlm.fitting.FitConfiguration) MaximaSpotFilter(gdsc.smlm.filters.MaximaSpotFilter) MultiPathFilter(gdsc.smlm.results.filter.MultiPathFilter) BasePreprocessedPeakResult(gdsc.smlm.results.filter.BasePreprocessedPeakResult) PreprocessedPeakResult(gdsc.smlm.results.filter.PreprocessedPeakResult) MemoryPeakResults(gdsc.smlm.results.MemoryPeakResults)

Example 8 with FitEngineConfiguration

use of gdsc.smlm.engine.FitEngineConfiguration in project GDSC-SMLM by aherbert.

the class BenchmarkSpotFit method showDialog.

@SuppressWarnings("unchecked")
private boolean showDialog() {
    GenericDialog gd = new GenericDialog(TITLE);
    gd.addHelp(About.HELP_URL);
    gd.addMessage(String.format("Fit candidate spots in the benchmark image created by " + CreateData.TITLE + " plugin\nand identified by the " + BenchmarkSpotFilter.TITLE + " plugin.\nPSF width = %s nm (Square pixel adjustment = %s nm)\n \nConfigure the fitting:", Utils.rounded(simulationParameters.s), Utils.rounded(getSa())));
    gd.addSlider("Fraction_positives", 50, 100, fractionPositives);
    gd.addSlider("Fraction_negatives_after_positives", 0, 100, fractionNegativesAfterAllPositives);
    gd.addSlider("Min_negatives_after_positives", 0, 10, negativesAfterAllPositives);
    gd.addSlider("Match_distance", 0.5, 3.5, distance);
    gd.addSlider("Lower_distance", 0, 3.5, lowerDistance);
    gd.addSlider("Match_signal", 0, 3.5, signalFactor);
    gd.addSlider("Lower_signal", 0, 3.5, lowerSignalFactor);
    // Collect options for fitting
    final double sa = getSa();
    gd.addNumericField("Initial_StdDev", Maths.round(sa / simulationParameters.a), 3);
    gd.addSlider("Fitting_width", 2, 4.5, config.getFitting());
    String[] solverNames = SettingsManager.getNames((Object[]) FitSolver.values());
    gd.addChoice("Fit_solver", solverNames, solverNames[fitConfig.getFitSolver().ordinal()]);
    String[] functionNames = SettingsManager.getNames((Object[]) FitFunction.values());
    gd.addChoice("Fit_function", functionNames, functionNames[fitConfig.getFitFunction().ordinal()]);
    gd.addMessage("Multi-path filter (used to pick optimum results during fitting)");
    // Allow loading the best filter fot these results
    boolean benchmarkSettingsCheckbox = fitResultsId == BenchmarkFilterAnalysis.lastId;
    // This should always be an opt-in decision. Otherwise the user cannot use the previous settings
    useBenchmarkSettings = false;
    if (benchmarkSettingsCheckbox)
        gd.addCheckbox("Benchmark_settings", useBenchmarkSettings);
    gd.addTextAreas(XmlUtils.convertQuotes(multiFilter.toXML()), null, 6, 60);
    gd.addNumericField("Fail_limit", config.getFailuresLimit(), 0);
    gd.addCheckbox("Include_neighbours", config.isIncludeNeighbours());
    gd.addSlider("Neighbour_height", 0.01, 1, config.getNeighbourHeightThreshold());
    //gd.addSlider("Residuals_threshold", 0.01, 1, config.getResidualsThreshold());
    gd.addCheckbox("Compute_doublets", computeDoublets);
    gd.addNumericField("Duplicate_distance", fitConfig.getDuplicateDistance(), 2);
    gd.addCheckbox("Show_score_histograms", showFilterScoreHistograms);
    gd.addCheckbox("Show_correlation", showCorrelation);
    gd.addCheckbox("Plot_rank_by_intensity", rankByIntensity);
    gd.addCheckbox("Save_filter_range", saveFilterRange);
    if (extraOptions) {
    }
    // Add a mouse listener to the config file field
    if (benchmarkSettingsCheckbox && Utils.isShowGenericDialog()) {
        Vector<TextField> numerics = (Vector<TextField>) gd.getNumericFields();
        Vector<Checkbox> checkboxes = (Vector<Checkbox>) gd.getCheckboxes();
        taFilterXml = gd.getTextArea1();
        Checkbox b = checkboxes.get(0);
        b.addItemListener(this);
        textFailLimit = numerics.get(9);
        cbIncludeNeighbours = checkboxes.get(1);
        textNeighbourHeight = numerics.get(10);
        cbComputeDoublets = checkboxes.get(2);
        if (useBenchmarkSettings) {
            FitConfiguration tmpFitConfig = new FitConfiguration();
            FitEngineConfiguration tmp = new FitEngineConfiguration(tmpFitConfig);
            // Collect the residuals threshold
            tmpFitConfig.setComputeResiduals(true);
            if (BenchmarkFilterAnalysis.updateConfiguration(tmp, false)) {
                textFailLimit.setText("" + tmp.getFailuresLimit());
                cbIncludeNeighbours.setState(tmp.isIncludeNeighbours());
                textNeighbourHeight.setText(Utils.rounded(tmp.getNeighbourHeightThreshold()));
                cbComputeDoublets.setState(tmp.getResidualsThreshold() < 1);
                final DirectFilter primaryFilter = tmpFitConfig.getSmartFilter();
                final double residualsThreshold = tmp.getResidualsThreshold();
                taFilterXml.setText(new MultiPathFilter(primaryFilter, minimalFilter, residualsThreshold).toXML());
            }
        }
    }
    gd.showDialog();
    if (gd.wasCanceled())
        return false;
    fractionPositives = Math.abs(gd.getNextNumber());
    fractionNegativesAfterAllPositives = Math.abs(gd.getNextNumber());
    negativesAfterAllPositives = (int) Math.abs(gd.getNextNumber());
    distance = Math.abs(gd.getNextNumber());
    lowerDistance = Math.abs(gd.getNextNumber());
    signalFactor = Math.abs(gd.getNextNumber());
    lowerSignalFactor = Math.abs(gd.getNextNumber());
    fitConfig.setInitialPeakStdDev(gd.getNextNumber());
    config.setFitting(gd.getNextNumber());
    fitConfig.setFitSolver(gd.getNextChoiceIndex());
    fitConfig.setFitFunction(gd.getNextChoiceIndex());
    boolean myUseBenchmarkSettings = false;
    if (benchmarkSettingsCheckbox)
        //useBenchmarkSettings = 
        myUseBenchmarkSettings = gd.getNextBoolean();
    // Read dialog settings
    String xml = gd.getNextText();
    int failLimit = (int) gd.getNextNumber();
    boolean includeNeighbours = gd.getNextBoolean();
    double neighbourHeightThreshold = gd.getNextNumber();
    boolean myComputeDoublets = gd.getNextBoolean();
    double myDuplicateDistance = gd.getNextNumber();
    MultiPathFilter myMultiFilter = null;
    if (myUseBenchmarkSettings && !Utils.isShowGenericDialog()) {
        // Only copy the benchmark settings if not interactive
        FitConfiguration tmpFitConfig = new FitConfiguration();
        FitEngineConfiguration tmp = new FitEngineConfiguration(tmpFitConfig);
        // Collect the residuals threshold
        tmpFitConfig.setComputeResiduals(true);
        if (BenchmarkFilterAnalysis.updateConfiguration(tmp, false)) {
            config.setFailuresLimit(tmp.getFailuresLimit());
            config.setIncludeNeighbours(tmp.isIncludeNeighbours());
            config.setNeighbourHeightThreshold(tmp.getNeighbourHeightThreshold());
            computeDoublets = (tmp.getResidualsThreshold() < 1);
            fitConfig.setDuplicateDistance(tmpFitConfig.getDuplicateDistance());
            final DirectFilter primaryFilter = tmpFitConfig.getSmartFilter();
            final double residualsThreshold = tmp.getResidualsThreshold();
            myMultiFilter = new MultiPathFilter(primaryFilter, minimalFilter, residualsThreshold);
        }
    } else {
        myMultiFilter = MultiPathFilter.fromXML(xml);
        config.setFailuresLimit(failLimit);
        config.setIncludeNeighbours(includeNeighbours);
        config.setNeighbourHeightThreshold(neighbourHeightThreshold);
        computeDoublets = myComputeDoublets;
        fitConfig.setDuplicateDistance(myDuplicateDistance);
    }
    if (myMultiFilter == null) {
        gd = new GenericDialog(TITLE);
        gd.addMessage("The multi-path filter was invalid.\n \nContinue with a default filter?");
        gd.enableYesNoCancel();
        gd.hideCancelButton();
        gd.showDialog();
        if (!gd.wasOKed())
            return false;
    } else {
        multiFilter = myMultiFilter;
    }
    if (computeDoublets) {
        //config.setComputeResiduals(true);
        config.setResidualsThreshold(0);
        fitConfig.setComputeResiduals(true);
    } else {
        config.setResidualsThreshold(1);
        fitConfig.setComputeResiduals(false);
    }
    showFilterScoreHistograms = gd.getNextBoolean();
    showCorrelation = gd.getNextBoolean();
    rankByIntensity = gd.getNextBoolean();
    saveFilterRange = gd.getNextBoolean();
    // Avoid stupidness, i.e. things that move outside the fit window and are bad widths
    // TODO - Fix this for simple or smart filter...
    fitConfig.setDisableSimpleFilter(false);
    // Realistically we cannot fit lower than this
    fitConfig.setMinPhotons(15);
    // Disable shift as candidates may be re-mapped to alternative candidates so the initial position is wrong.
    fitConfig.setCoordinateShiftFactor(0);
    fitConfig.setMinWidthFactor(1.0 / 5);
    fitConfig.setWidthFactor(5);
    // Disable the direct filter
    fitConfig.setDirectFilter(null);
    if (extraOptions) {
    }
    if (gd.invalidNumber())
        return false;
    if (lowerDistance > distance)
        lowerDistance = distance;
    if (lowerSignalFactor > signalFactor)
        lowerSignalFactor = signalFactor;
    // Distances relative to sa (not s) as this is the same as the BenchmarkSpotFilter plugin 
    distanceInPixels = distance * sa / simulationParameters.a;
    lowerDistanceInPixels = lowerDistance * sa / simulationParameters.a;
    GlobalSettings settings = new GlobalSettings();
    settings.setFitEngineConfiguration(config);
    settings.setCalibration(cal);
    // Copy simulation defaults if a new simulation
    if (lastId != simulationParameters.id) {
        cal.setNmPerPixel(simulationParameters.a);
        cal.setGain(simulationParameters.gain);
        cal.setAmplification(simulationParameters.amplification);
        cal.setExposureTime(100);
        cal.setReadNoise(simulationParameters.readNoise);
        cal.setBias(simulationParameters.bias);
        cal.setEmCCD(simulationParameters.emCCD);
        // This is needed to configure the fit solver
        fitConfig.setNmPerPixel(Maths.round(cal.getNmPerPixel()));
        fitConfig.setGain(Maths.round(cal.getGain()));
        fitConfig.setBias(Maths.round(cal.getBias()));
        fitConfig.setReadNoise(Maths.round(cal.getReadNoise()));
        fitConfig.setAmplification(Maths.round(cal.getAmplification()));
        fitConfig.setEmCCD(cal.isEmCCD());
    }
    if (!PeakFit.configureFitSolver(settings, null, extraOptions))
        return false;
    return true;
}
Also used : FitEngineConfiguration(gdsc.smlm.engine.FitEngineConfiguration) DirectFilter(gdsc.smlm.results.filter.DirectFilter) GlobalSettings(gdsc.smlm.ij.settings.GlobalSettings) PeakResultPoint(gdsc.smlm.ij.plugins.ResultsMatchCalculator.PeakResultPoint) BasePoint(gdsc.core.match.BasePoint) Checkbox(java.awt.Checkbox) FitConfiguration(gdsc.smlm.fitting.FitConfiguration) GenericDialog(ij.gui.GenericDialog) MultiPathFilter(gdsc.smlm.results.filter.MultiPathFilter) TextField(java.awt.TextField) Vector(java.util.Vector)

Example 9 with FitEngineConfiguration

use of gdsc.smlm.engine.FitEngineConfiguration in project GDSC-SMLM by aherbert.

the class BenchmarkSpotFit method itemStateChanged.

public void itemStateChanged(ItemEvent e) {
    if (e.getSource() instanceof Checkbox) {
        Checkbox checkbox = (Checkbox) e.getSource();
        int failLimit;
        boolean includeNeighbours;
        double neighbourHeightThrehsold;
        boolean computeDoublets;
        MultiPathFilter myMultiFilter;
        if (checkbox.getState()) {
            FitConfiguration tmpFitConfig = new FitConfiguration();
            FitEngineConfiguration tmp = new FitEngineConfiguration(tmpFitConfig);
            // Collect residuals threshold
            tmpFitConfig.setComputeResiduals(true);
            if (BenchmarkFilterAnalysis.updateConfiguration(tmp, false)) {
                failLimit = tmp.getFailuresLimit();
                includeNeighbours = tmp.isIncludeNeighbours();
                neighbourHeightThrehsold = tmp.getNeighbourHeightThreshold();
                computeDoublets = tmp.getResidualsThreshold() < 1;
                final DirectFilter primaryFilter = tmpFitConfig.getSmartFilter();
                final double residualsThreshold = tmp.getResidualsThreshold();
                myMultiFilter = new MultiPathFilter(primaryFilter, minimalFilter, residualsThreshold);
            } else {
                IJ.log("Failed to update settings using the filter analysis");
                checkbox.setState(false);
                return;
            }
        } else {
            failLimit = config.getFailuresLimit();
            includeNeighbours = config.isIncludeNeighbours();
            neighbourHeightThrehsold = config.getNeighbourHeightThreshold();
            computeDoublets = BenchmarkSpotFit.computeDoublets;
            myMultiFilter = multiFilter;
        }
        // Update the dialog
        taFilterXml.setText(myMultiFilter.toXML());
        textFailLimit.setText("" + failLimit);
        cbIncludeNeighbours.setState(includeNeighbours);
        textNeighbourHeight.setText(Utils.rounded(neighbourHeightThrehsold));
        cbComputeDoublets.setState(computeDoublets);
    }
}
Also used : Checkbox(java.awt.Checkbox) FitConfiguration(gdsc.smlm.fitting.FitConfiguration) FitEngineConfiguration(gdsc.smlm.engine.FitEngineConfiguration) DirectFilter(gdsc.smlm.results.filter.DirectFilter) MultiPathFilter(gdsc.smlm.results.filter.MultiPathFilter) PeakResultPoint(gdsc.smlm.ij.plugins.ResultsMatchCalculator.PeakResultPoint) BasePoint(gdsc.core.match.BasePoint)

Example 10 with FitEngineConfiguration

use of gdsc.smlm.engine.FitEngineConfiguration in project GDSC-SMLM by aherbert.

the class TraceMolecules method fitTraces.

private void fitTraces(MemoryPeakResults results, Trace[] traces) {
    // Check if the original image is open and the fit configuration can be extracted
    ImageSource source = results.getSource();
    if (source == null)
        return;
    if (!source.open())
        return;
    FitEngineConfiguration config = (FitEngineConfiguration) XmlUtils.fromXML(results.getConfiguration());
    if (config == null)
        return;
    // Show a dialog asking if the traces should be refit
    ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
    gd.addMessage("Do you want to fit the traces as a single peak using a combined image?");
    gd.addCheckbox("Fit_closest_to_centroid", !fitOnlyCentroid);
    gd.addSlider("Distance_threshold", 0.01, 3, distanceThreshold);
    gd.addSlider("Expansion_factor", 1, 4.5, expansionFactor);
    // Allow fitting settings to be adjusted
    FitConfiguration fitConfig = config.getFitConfiguration();
    gd.addMessage("--- Gaussian fitting ---");
    String[] filterTypes = SettingsManager.getNames((Object[]) DataFilterType.values());
    gd.addChoice("Spot_filter_type", filterTypes, filterTypes[config.getDataFilterType().ordinal()]);
    String[] filterNames = SettingsManager.getNames((Object[]) DataFilter.values());
    gd.addChoice("Spot_filter", filterNames, filterNames[config.getDataFilter(0).ordinal()]);
    gd.addSlider("Smoothing", 0, 2.5, config.getSmooth(0));
    gd.addSlider("Search_width", 0.5, 2.5, config.getSearch());
    gd.addSlider("Border", 0.5, 2.5, config.getBorder());
    gd.addSlider("Fitting_width", 2, 4.5, config.getFitting());
    String[] solverNames = SettingsManager.getNames((Object[]) FitSolver.values());
    gd.addChoice("Fit_solver", solverNames, solverNames[fitConfig.getFitSolver().ordinal()]);
    String[] functionNames = SettingsManager.getNames((Object[]) FitFunction.values());
    gd.addChoice("Fit_function", functionNames, functionNames[fitConfig.getFitFunction().ordinal()]);
    String[] criteriaNames = SettingsManager.getNames((Object[]) FitCriteria.values());
    gd.addChoice("Fit_criteria", criteriaNames, criteriaNames[fitConfig.getFitCriteria().ordinal()]);
    gd.addNumericField("Significant_digits", fitConfig.getSignificantDigits(), 0);
    gd.addNumericField("Coord_delta", fitConfig.getDelta(), 4);
    gd.addNumericField("Lambda", fitConfig.getLambda(), 4);
    gd.addNumericField("Max_iterations", fitConfig.getMaxIterations(), 0);
    gd.addNumericField("Fail_limit", config.getFailuresLimit(), 0);
    gd.addCheckbox("Include_neighbours", config.isIncludeNeighbours());
    gd.addSlider("Neighbour_height", 0.01, 1, config.getNeighbourHeightThreshold());
    gd.addSlider("Residuals_threshold", 0.01, 1, config.getResidualsThreshold());
    //gd.addSlider("Duplicate_distance", 0, 1.5, fitConfig.getDuplicateDistance());
    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.01, 2, fitConfig.getCoordinateShiftFactor());
    gd.addNumericField("Signal_strength", fitConfig.getSignalStrength(), 2);
    gd.addNumericField("Min_photons", fitConfig.getMinPhotons(), 0);
    gd.addSlider("Min_width_factor", 0, 0.99, fitConfig.getMinWidthFactor());
    gd.addSlider("Width_factor", 1.01, 5, fitConfig.getWidthFactor());
    gd.addNumericField("Precision", fitConfig.getPrecisionThreshold(), 2);
    gd.addCheckbox("Debug_failures", debugFailures);
    gd.showDialog();
    if (!gd.wasOKed()) {
        source.close();
        return;
    }
    // Get parameters for the fit
    fitOnlyCentroid = !gd.getNextBoolean();
    distanceThreshold = (float) gd.getNextNumber();
    expansionFactor = (float) gd.getNextNumber();
    config.setDataFilterType(gd.getNextChoiceIndex());
    config.setDataFilter(gd.getNextChoiceIndex(), Math.abs(gd.getNextNumber()), 0);
    config.setSearch(gd.getNextNumber());
    config.setBorder(gd.getNextNumber());
    config.setFitting(gd.getNextNumber());
    fitConfig.setFitSolver(gd.getNextChoiceIndex());
    fitConfig.setFitFunction(gd.getNextChoiceIndex());
    fitConfig.setFitCriteria(gd.getNextChoiceIndex());
    fitConfig.setSignificantDigits((int) gd.getNextNumber());
    fitConfig.setDelta(gd.getNextNumber());
    fitConfig.setLambda(gd.getNextNumber());
    fitConfig.setMaxIterations((int) gd.getNextNumber());
    config.setFailuresLimit((int) gd.getNextNumber());
    config.setIncludeNeighbours(gd.getNextBoolean());
    config.setNeighbourHeightThreshold(gd.getNextNumber());
    config.setResidualsThreshold(gd.getNextNumber());
    fitConfig.setSmartFilter(gd.getNextBoolean());
    fitConfig.setDisableSimpleFilter(gd.getNextBoolean());
    fitConfig.setCoordinateShiftFactor(gd.getNextNumber());
    fitConfig.setSignalStrength(gd.getNextNumber());
    fitConfig.setMinPhotons(gd.getNextNumber());
    fitConfig.setMinWidthFactor(gd.getNextNumber());
    fitConfig.setWidthFactor(gd.getNextNumber());
    fitConfig.setPrecisionThreshold(gd.getNextNumber());
    // Check arguments
    try {
        Parameters.isAboveZero("Distance threshold", distanceThreshold);
        Parameters.isAbove("Expansion factor", expansionFactor, 1);
        Parameters.isAboveZero("Search_width", config.getSearch());
        Parameters.isAboveZero("Fitting_width", config.getFitting());
        Parameters.isAboveZero("Significant digits", fitConfig.getSignificantDigits());
        Parameters.isAboveZero("Delta", fitConfig.getDelta());
        Parameters.isAboveZero("Lambda", fitConfig.getLambda());
        Parameters.isAboveZero("Max iterations", fitConfig.getMaxIterations());
        Parameters.isPositive("Failures limit", config.getFailuresLimit());
        Parameters.isPositive("Neighbour height threshold", config.getNeighbourHeightThreshold());
        Parameters.isPositive("Residuals threshold", config.getResidualsThreshold());
        Parameters.isPositive("Coordinate Shift factor", fitConfig.getCoordinateShiftFactor());
        Parameters.isPositive("Signal strength", fitConfig.getSignalStrength());
        Parameters.isPositive("Min photons", fitConfig.getMinPhotons());
        Parameters.isPositive("Min width factor", fitConfig.getMinWidthFactor());
        Parameters.isPositive("Width factor", fitConfig.getWidthFactor());
        Parameters.isPositive("Precision threshold", fitConfig.getPrecisionThreshold());
    } catch (IllegalArgumentException e) {
        IJ.error(TITLE, e.getMessage());
        source.close();
        return;
    }
    debugFailures = gd.getNextBoolean();
    if (!PeakFit.configureSmartFilter(globalSettings, filename))
        return;
    if (!PeakFit.configureDataFilter(globalSettings, filename, false))
        return;
    if (!PeakFit.configureFitSolver(globalSettings, filename, false))
        return;
    // Adjust settings for a single maxima
    config.setIncludeNeighbours(false);
    fitConfig.setDuplicateDistance(0);
    // Create a fit engine
    MemoryPeakResults refitResults = new MemoryPeakResults();
    refitResults.copySettings(results);
    refitResults.setName(results.getName() + " Trace Fit");
    refitResults.setSortAfterEnd(true);
    refitResults.begin();
    // No border since we know where the peaks are and we must not miss them due to truncated searching 
    FitEngine engine = new FitEngine(config, refitResults, Prefs.getThreads(), FitQueue.BLOCKING);
    // Either : Only fit the centroid
    // or     : Extract a bigger region, allowing all fits to run as normal and then 
    //          find the correct spot using Euclidian distance.
    // Set up the limits
    final double stdDev = FastMath.max(fitConfig.getInitialPeakStdDev0(), fitConfig.getInitialPeakStdDev1());
    float fitWidth = (float) (stdDev * config.getFitting() * ((fitOnlyCentroid) ? 1 : expansionFactor));
    IJ.showStatus("Refitting traces ...");
    List<JobItem> jobItems = new ArrayList<JobItem>(traces.length);
    int singles = 0;
    int fitted = 0;
    for (int n = 0; n < traces.length; n++) {
        Trace trace = traces[n];
        if (n % 32 == 0)
            IJ.showProgress(n, traces.length);
        // Skip traces with one peak
        if (trace.size() == 1) {
            singles++;
            // Use the synchronized method to avoid thread clashes with the FitEngine
            refitResults.addSync(trace.getHead());
            continue;
        }
        Rectangle bounds = new Rectangle();
        double[] combinedNoise = new double[1];
        float[] data = buildCombinedImage(source, trace, fitWidth, bounds, combinedNoise, false);
        if (data == null)
            continue;
        // Fit the combined image
        FitParameters params = new FitParameters();
        params.noise = (float) combinedNoise[0];
        float[] centre = trace.getCentroid();
        if (fitOnlyCentroid) {
            int newX = (int) Math.round(centre[0]) - bounds.x;
            int newY = (int) Math.round(centre[1]) - bounds.y;
            params.maxIndices = new int[] { newY * bounds.width + newX };
        } else {
            params.filter = new ArrayList<float[]>();
            params.filter.add(new float[] { centre[0] - bounds.x, centre[1] - bounds.y });
            params.distanceThreshold = distanceThreshold;
        }
        // This is not needed since the bounds are passed using the FitJob
        //params.setOffset(new float[] { bounds.x, bounds.y });
        int startT = trace.getHead().getFrame();
        params.endT = trace.getTail().getFrame();
        ParameterisedFitJob job = new ParameterisedFitJob(n, params, startT, data, bounds);
        jobItems.add(new JobItem(job, trace, centre));
        engine.run(job);
        fitted++;
    }
    engine.end(false);
    IJ.showStatus("");
    IJ.showProgress(1);
    // Check the success ...
    FitStatus[] values = FitStatus.values();
    int[] statusCount = new int[values.length + 1];
    ArrayList<String> names = new ArrayList<String>(Arrays.asList(SettingsManager.getNames((Object[]) values)));
    names.add(String.format("No maxima within %.2f of centroid", distanceThreshold));
    int separated = 0;
    int success = 0;
    final int debugLimit = 3;
    for (JobItem jobItem : jobItems) {
        int id = jobItem.getId();
        ParameterisedFitJob job = jobItem.job;
        Trace trace = jobItem.trace;
        int[] indices = job.getIndices();
        FitResult fitResult = null;
        int status;
        if (indices.length < 1) {
            status = values.length;
        } else if (indices.length > 1) {
            // Choose the first OK result. This is all that matters for the success reporting
            for (int n = 0; n < indices.length; n++) {
                if (job.getFitResult(n).getStatus() == FitStatus.OK) {
                    fitResult = job.getFitResult(n);
                    break;
                }
            }
            // Otherwise use the closest failure. 
            if (fitResult == null) {
                final float[] centre = traces[id].getCentroid();
                double minD = Double.POSITIVE_INFINITY;
                for (int n = 0; n < indices.length; n++) {
                    // Since the fit has failed we use the initial parameters
                    final double[] params = job.getFitResult(n).getInitialParameters();
                    final double dx = params[Gaussian2DFunction.X_POSITION] - centre[0];
                    final double dy = params[Gaussian2DFunction.Y_POSITION] - centre[1];
                    final double d = dx * dx + dy * dy;
                    if (minD > d) {
                        minD = d;
                        fitResult = job.getFitResult(n);
                    }
                }
            }
            status = fitResult.getStatus().ordinal();
        } else {
            fitResult = job.getFitResult(0);
            status = fitResult.getStatus().ordinal();
        }
        // All jobs have only one peak
        statusCount[status]++;
        // Debug why any fits failed
        if (fitResult == null || fitResult.getStatus() != FitStatus.OK) {
            refitResults.addAll(trace.getPoints());
            separated += trace.size();
            if (debugFailures) {
                FitStatus s = (fitResult == null) ? FitStatus.UNKNOWN : fitResult.getStatus();
                // Only display the first n per category to limit the number of images
                double[] noise = new double[1];
                if (statusCount[status] <= debugLimit) {
                    Rectangle bounds = new Rectangle();
                    buildCombinedImage(source, trace, fitWidth, bounds, noise, true);
                    float[] centre = trace.getCentroid();
                    Utils.display(String.format("Trace %d (n=%d) : x=%f,y=%f", id, trace.size(), centre[0], centre[1]), slices);
                    switch(s) {
                        case INSUFFICIENT_PRECISION:
                            float precision = (Float) fitResult.getStatusData();
                            IJ.log(String.format("Trace %d (n=%d) : %s = %f", id, trace.size(), names.get(status), precision));
                            break;
                        case INSUFFICIENT_SIGNAL:
                            if (noise[0] == 0)
                                noise[0] = getCombinedNoise(trace);
                            float snr = (Float) fitResult.getStatusData();
                            IJ.log(String.format("Trace %d (n=%d) : %s = %f (noise=%.2f)", id, trace.size(), names.get(status), snr, noise[0]));
                            break;
                        case COORDINATES_MOVED:
                        case OUTSIDE_FIT_REGION:
                        case WIDTH_DIVERGED:
                            float[] shift = (float[]) fitResult.getStatusData();
                            IJ.log(String.format("Trace %d (n=%d) : %s = %.3f,%.3f", id, trace.size(), names.get(status), shift[0], shift[1]));
                            break;
                        default:
                            IJ.log(String.format("Trace %d (n=%d) : %s", id, trace.size(), names.get(status)));
                            break;
                    }
                }
            }
        } else {
            success++;
            if (debugFailures) {
                // Only display the first n per category to limit the number of images
                double[] noise = new double[1];
                if (statusCount[status] <= debugLimit) {
                    Rectangle bounds = new Rectangle();
                    buildCombinedImage(source, trace, fitWidth, bounds, noise, true);
                    float[] centre = trace.getCentroid();
                    Utils.display(String.format("Trace %d (n=%d) : x=%f,y=%f", id, trace.size(), centre[0], centre[1]), slices);
                }
            }
        }
    }
    IJ.log(String.format("Trace fitting : %d singles : %d / %d fitted : %d separated", singles, success, fitted, separated));
    if (separated > 0) {
        IJ.log("Reasons for fit failure :");
        // Start at i=1 to skip FitStatus.OK
        for (int i = 1; i < statusCount.length; i++) {
            if (statusCount[i] != 0)
                IJ.log("  " + names.get(i) + " = " + statusCount[i]);
        }
    }
    refitResults.end();
    MemoryPeakResults.addResults(refitResults);
    source.close();
}
Also used : FitParameters(gdsc.smlm.engine.FitParameters) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) FitStatus(gdsc.smlm.fitting.FitStatus) MemoryPeakResults(gdsc.smlm.results.MemoryPeakResults) ParameterisedFitJob(gdsc.smlm.engine.ParameterisedFitJob) FitEngineConfiguration(gdsc.smlm.engine.FitEngineConfiguration) ExtendedGenericDialog(ij.gui.ExtendedGenericDialog) ClusterPoint(gdsc.core.clustering.ClusterPoint) Trace(gdsc.smlm.results.Trace) FitEngine(gdsc.smlm.engine.FitEngine) FitConfiguration(gdsc.smlm.fitting.FitConfiguration) FitResult(gdsc.smlm.fitting.FitResult) ImageSource(gdsc.smlm.results.ImageSource)

Aggregations

FitEngineConfiguration (gdsc.smlm.engine.FitEngineConfiguration)22 FitConfiguration (gdsc.smlm.fitting.FitConfiguration)16 GlobalSettings (gdsc.smlm.ij.settings.GlobalSettings)9 ExtendedGenericDialog (ij.gui.ExtendedGenericDialog)6 Calibration (gdsc.smlm.results.Calibration)5 GenericDialog (ij.gui.GenericDialog)4 Checkbox (java.awt.Checkbox)4 XStreamException (com.thoughtworks.xstream.XStreamException)3 BasePoint (gdsc.core.match.BasePoint)3 PeakResultPoint (gdsc.smlm.ij.plugins.ResultsMatchCalculator.PeakResultPoint)3 ResultsSettings (gdsc.smlm.ij.settings.ResultsSettings)3 DirectFilter (gdsc.smlm.results.filter.DirectFilter)3 MultiPathFilter (gdsc.smlm.results.filter.MultiPathFilter)3 MemoryPeakResults (gdsc.smlm.results.MemoryPeakResults)2 Choice (java.awt.Choice)2 TextField (java.awt.TextField)2 File (java.io.File)2 FileNotFoundException (java.io.FileNotFoundException)2 IOException (java.io.IOException)2 Vector (java.util.Vector)2