Search in sources :

Example 31 with FitEngineConfiguration

use of uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration in project gdsc-smlm by aherbert.

the class SpotFinderPreview method showDialog.

@Override
public int showDialog(ImagePlus imp, String command, PlugInFilterRunner pfr) {
    settings = Settings.load();
    this.overlay = imp.getOverlay();
    this.imp = imp;
    // Saved by reference so do it once now
    settings.save();
    // The image is locked by the PlugInFilterRunner so unlock it to allow scroll.
    // This should be OK as the image data is not modified and only the overlay is
    // adjusted. If another plugin changes the image then the preview should update
    // the overlay and it will be obvious to the user to turn this plugin off.
    imp.unlock();
    config = SettingsManager.readFitEngineConfiguration(0);
    fitConfig = config.getFitConfiguration();
    gd = new NonBlockingExtendedGenericDialog(TITLE);
    gd.addHelp(HelpUrls.getUrl("spot-finder-preview"));
    gd.addMessage("Preview candidate maxima");
    final String[] templates = ConfigurationTemplate.getTemplateNames(true);
    gd.addChoice("Template", templates, templates[0]);
    final String[] models = CameraModelManager.listCameraModels(true);
    gd.addChoice("Camera_model_name", models, fitConfig.getCameraModelName());
    PeakFit.addPsfOptions(gd, (FitConfigurationProvider) () -> fitConfig);
    final PeakFit.SimpleFitEngineConfigurationProvider provider = new PeakFit.SimpleFitEngineConfigurationProvider(config);
    PeakFit.addDataFilterOptions(gd, provider);
    gd.addChoice("Spot_filter_2", SettingsManager.getDataFilterMethodNames(), config.getDataFilterMethod(1, settings.defaultDataFilterMethod).ordinal());
    PeakFit.addRelativeParameterOptions(gd, new RelativeParameterProvider(2.5, 4.5, "Smoothing_2", provider) {

        @Override
        void setAbsolute(boolean absolute) {
            final FitEngineConfiguration c = fitEngineConfigurationProvider.getFitEngineConfiguration();
            final DataFilterMethod m = c.getDataFilterMethod(1, settings.defaultDataFilterMethod);
            final double smooth = c.getDataFilterParameterValue(1, settings.defaultSmooth);
            c.setDataFilter(m, smooth, absolute, 1);
        }

        @Override
        boolean isAbsolute() {
            return fitEngineConfigurationProvider.getFitEngineConfiguration().getDataFilterParameterAbsolute(1, false);
        }

        @Override
        double getValue() {
            return fitEngineConfigurationProvider.getFitEngineConfiguration().getDataFilterParameterValue(1, settings.defaultSmooth);
        }
    });
    PeakFit.addSearchOptions(gd, provider);
    PeakFit.addBorderOptions(gd, provider);
    // Find if this image was created with ground truth data
    if (imp.getID() == CreateData.getImageId()) {
        final MemoryPeakResults results = CreateData.getResults();
        if (results != null) {
            gd.addSlider("Match_distance", 0, 2.5, settings.distance);
            gd.addSlider("Lower_match_distance (%)", 0, 100, settings.lowerDistance);
            gd.addCheckbox("Multiple_matches", settings.multipleMatches);
            gd.addCheckbox("Show_TP", settings.showTP);
            gd.addCheckbox("Show_FP", settings.showFP);
            gd.addMessage("");
            label = (Label) gd.getMessage();
            final boolean integerCoords = false;
            actualCoordinates = ResultsMatchCalculator.getCoordinates(results, integerCoords);
        }
    }
    if (label == null) {
        // If no ground truth data add options to show the spots by their rank
        // and number of neighbours
        gd.addSlider("Top_N", 0, 100, settings.topN);
        topNScrollBar = gd.getLastScrollbar();
        gd.addSlider("Select", 0, 100, settings.select);
        selectScrollBar = gd.getLastScrollbar();
        gd.addSlider("Neigbour_radius", 0, 10, settings.neighbourRadius);
    }
    ImageListener imageListener = null;
    if (ImageJUtils.isShowGenericDialog()) {
        // Listen for changes in the dialog options
        gd.addOptionCollectedListener(event -> {
            // Just run on the current processor
            if (preview) {
                run(imp.getProcessor());
            }
        });
        // Listen for changes to an image
        imageListener = new ImageAdapter() {

            @Override
            public void imageUpdated(ImagePlus imp) {
                if (SpotFinderPreview.this.imp.getID() == imp.getID() && preview && imp.getCurrentSlice() != currentSlice && filter != null) {
                    run(imp.getProcessor(), filter);
                }
            }
        };
        ImagePlus.addImageListener(imageListener);
        // Support template settings
        final Vector<TextField> numerics = gd.getNumericFields();
        final Vector<Choice> choices = gd.getChoices();
        final Iterator<TextField> nu = numerics.iterator();
        final Iterator<Choice> ch = choices.iterator();
        final Choice textTemplate = ch.next();
        textTemplate.removeItemListener(gd);
        textTemplate.removeKeyListener(gd);
        textTemplate.addItemListener(this::itemStateChanged);
        textCameraModelName = ch.next();
        textPsf = ch.next();
        textDataFilterType = ch.next();
        textDataFilterMethod = ch.next();
        textSmooth = nu.next();
        textDataFilterMethod2 = ch.next();
        textSmooth2 = nu.next();
        textSearch = nu.next();
        textBorder = nu.next();
    }
    gd.addPreviewCheckbox(pfr);
    gd.addDialogListener(this::dialogItemChanged);
    gd.setOKLabel("Save");
    gd.setCancelLabel("Close");
    gd.showDialog();
    if (imageListener != null) {
        ImagePlus.removeImageListener(imageListener);
    }
    if (!gd.wasCanceled() && !SettingsManager.writeSettings(config, SettingsManager.FLAG_SILENT)) {
        IJ.error(TITLE, "Failed to save settings");
    }
    // Reset
    imp.setOverlay(overlay);
    return DONE;
}
Also used : Choice(java.awt.Choice) ImageListener(ij.ImageListener) FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) ImagePlus(ij.ImagePlus) DataFilterMethod(uk.ac.sussex.gdsc.smlm.data.config.FitProtos.DataFilterMethod) RelativeParameterProvider(uk.ac.sussex.gdsc.smlm.ij.plugins.PeakFit.RelativeParameterProvider) ImageAdapter(uk.ac.sussex.gdsc.core.ij.ImageAdapter) TextField(java.awt.TextField) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)

Example 32 with FitEngineConfiguration

use of uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration in project gdsc-smlm by aherbert.

the class BenchmarkFilterAnalysis method showDialog.

private boolean showDialog(int optimiseParameters) {
    final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
    final boolean showOptimiseFilter = (optimiseParameters & FLAG_OPTIMISE_FILTER) != 0;
    final boolean showOptimiseParams = (optimiseParameters & FLAG_OPTIMISE_PARAMS) != 0;
    final String helpKey = showOptimiseParams ? "benchmark-filter-parameters" : "benchmark-filter-analysis";
    addSimulationData(gd);
    // TODO - Make minimal filter configurable?
    gd.addSlider("Fail_count", 0, 20, settings.failCount);
    if (showOptimiseParams) {
        gd.addNumericField("Min_fail_count", settings.minFailCount, 0);
        gd.addNumericField("Max_fail_count", settings.maxFailCount, 0);
    }
    if (computeDoublets) {
        gd.addSlider("Residuals_threshold", 0.01, 1, settings.residualsThreshold);
        if (showOptimiseParams) {
            gd.addNumericField("Min_residuals_threshold", settings.minResidualsThreshold, 2);
            gd.addNumericField("Max_residuals_threshold", settings.maxResidualsThreshold, 2);
        }
    }
    final FitEngineConfiguration tmp = FitEngineConfiguration.create();
    tmp.setDuplicateDistance(settings.duplicateDistance);
    tmp.setDuplicateDistanceAbsolute(settings.duplicateDistanceAbsolute);
    PeakFit.addDuplicateDistanceOptions(gd, new PeakFit.SimpleFitEngineConfigurationProvider(tmp));
    if (showOptimiseParams) {
        gd.addNumericField("Min_duplicate_distance", settings.minDuplicateDistance, 2);
        gd.addNumericField("Max_duplicate_distance", settings.maxDuplicateDistance, 2);
    }
    gd.addCheckbox("Reset", settings.reset);
    gd.addCheckbox("Show_table", settings.showResultsTable);
    gd.addCheckbox("Show_summary", settings.showSummaryTable);
    gd.addCheckbox("Clear_tables", settings.clearTables);
    gd.addSlider("Summary_top_n", 0, 20, settings.summaryTopN);
    gd.addNumericField("Summary_depth (nm)", settings.summaryDepth, 0);
    gd.addSlider("Plot_top_n", 0, 20, settings.plotTopN);
    gd.addCheckbox("Save_best_filter", settings.saveBestFilter);
    gd.addCheckbox("Save_template", settings.saveTemplate);
    gd.addCheckbox("Calculate_sensitivity", settings.calculateSensitivity);
    gd.addSlider("Delta", 0.01, 1, settings.delta);
    gd.addMessage("Match scoring");
    gd.addChoice("Criteria", Settings.COLUMNS, settings.criteriaIndex);
    gd.addNumericField("Criteria_limit", settings.criteriaLimit, 4);
    gd.addChoice("Score", Settings.COLUMNS, settings.scoreIndex);
    ImageJUtils.addMessage(gd, "Fitting match distance = %s nm; signal factor = %s", MathUtils.rounded(spotFitResults.distanceInPixels * simulationParameters.pixelPitch), MathUtils.rounded(fitSignalFactor));
    gd.addSlider("Upper_match_distance (%)", 0, 100, settings.upperMatchDistance);
    gd.addSlider("Partial_match_distance (%)", 0, 100, settings.partialMatchDistance);
    gd.addSlider("Upper_signal_factor (%)", 0, 100, settings.upperSignalFactor);
    gd.addSlider("Partial_signal_factor (%)", 0, 100, settings.partialSignalFactor);
    if (!simulationParameters.fixedDepth) {
        gd.addCheckbox("Depth_recall_analysis", settings.depthRecallAnalysis);
    }
    gd.addCheckbox("Score_analysis", settings.scoreAnalysis);
    gd.addChoice("Component_analysis", Settings.COMPONENT_ANALYSIS_OPTIONS, settings.componentAnalysis);
    if (showOptimiseFilter) {
        gd.addChoice("Evolve", Settings.EVOLVE_OPTIONS, settings.evolve);
        gd.addCheckbox("Repeat_evolve", settings.repeatEvolve);
    }
    if (showOptimiseParams) {
        gd.addChoice("Search", Settings.SEARCH_OPTIONS, settings.searchParam);
        gd.addCheckbox("Repeat_search", settings.repeatSearch);
    }
    gd.addStringField("Title", settings.resultsTitle, 20);
    final String[] labels = { "Show_TP", "Show_FP", "Show_FN" };
    gd.addCheckboxGroup(1, 3, labels, new boolean[] { settings.showTP, settings.showFP, settings.showFN });
    gd.addHelp(HelpUrls.getUrl(helpKey));
    gd.showDialog();
    if (gd.wasCanceled() || !readDialog(gd, optimiseParameters, tmp) || !selectTableColumns()) {
        return false;
    }
    // We may have to read the results again if the ranking option has changed.
    // Also we must read the results with the maximum duplicate distance we may encounter.
    final double dd = settings.duplicateDistance;
    if (showOptimiseParams) {
        settings.duplicateDistance = settings.maxDuplicateDistance;
    }
    readResults();
    settings.duplicateDistance = dd;
    return true;
}
Also used : FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) PeakFit(uk.ac.sussex.gdsc.smlm.ij.plugins.PeakFit) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)

Example 33 with FitEngineConfiguration

use of uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration in project gdsc-smlm by aherbert.

the class BenchmarkFilterAnalysis method readResults.

private MultiPathFitResults[] readResults() {
    // Extract all the results in memory into a list per frame. This can be cached
    boolean update = false;
    Pair<Integer, CustomInt2ObjectOpenHashMap<UniqueIdPeakResult[]>> coords = COORDINATE_CACHE.get();
    if (coords.getKey() != simulationParameters.id) {
        coords = Pair.of(simulationParameters.id, getCoordinates(results));
        COORDINATE_CACHE.set(coords);
        update = true;
    }
    actualCoordinates = coords.getValue();
    spotFitResults = BenchmarkSpotFit.getBenchmarkSpotFitResults();
    FitResultData localFitResultData = FIT_RESULTS_DATA_CACHE.get();
    final SettingsList scoreSettings = new SettingsList(settings.partialMatchDistance, settings.upperMatchDistance, settings.partialSignalFactor, settings.upperSignalFactor);
    final boolean equalScoreSettings = scoreSettings.equals(localFitResultData.scoreSettings);
    if (update || localFitResultData.fittingId != spotFitResults.id || !equalScoreSettings || localFitResultData.differentSettings(settings)) {
        IJ.showStatus("Reading results ...");
        if (localFitResultData.fittingId < 0) {
            // Copy the settings from the fitter if this is the first run.
            // This just starts the plugin with sensible settings.
            // Q. Should this be per new simulation or fitting result instead?
            final FitEngineConfiguration config = BenchmarkSpotFit.getFitEngineConfiguration();
            settings.failCount = config.getFailuresLimit();
            settings.duplicateDistance = config.getDuplicateDistance();
            settings.duplicateDistanceAbsolute = config.getDuplicateDistanceAbsolute();
            settings.residualsThreshold = (BenchmarkSpotFit.getComputeDoublets()) ? BenchmarkSpotFit.getMultiFilter().residualsThreshold : 1;
        }
        // This functionality is for choosing the optimum filter for the given scoring metric.
        if (!equalScoreSettings) {
            filterAnalysisResult.scores.clear();
        }
        localFitResultData = new FitResultData(spotFitResults.id, scoreSettings, settings);
        // @formatter:off
        // -=-=-=-
        // The scoring is designed to find the best fitter+filter combination for the given spot
        // candidates. The ideal combination would correctly fit+pick all the candidate positions
        // that are close to a localisation.
        // 
        // Use the following scoring scheme for all candidates:
        // 
        // Candidates
        // +----------------------------------------+
        // |   Actual matches                       |
        // |  +-----------+                TN       |
        // |  |  FN       |                         |
        // |  |      +----------                    |
        // |  |      | TP |    | Fitted             |
        // |  +-----------+    | spots              |
        // |         |     FP  |                    |
        // |         +---------+                    |
        // +----------------------------------------+
        // 
        // Candidates     = All the spot candidates
        // Actual matches = Any spot candidate or fitted spot candidate that matches a localisation
        // Fitted spots   = Any spot candidate that was successfully fitted
        // 
        // TP = A spot candidate that was fitted and matches a localisation and is accepted
        // FP = A spot candidate that was fitted but does not match a localisation and is accepted
        // FN = A spot candidate that failed to be fitted but matches a localisation
        // = A spot candidate that was fitted and matches a localisation and is rejected
        // TN = A spot candidate that failed to be fitted and does not match a localisation
        // = A spot candidate that was fitted and does not match a localisation and is rejected
        // 
        // When fitting only produces one result it is possible to compute the TN score.
        // Since unfitted candidates can only be TN or FN we could accumulate these scores and cache
        // them. This was the old method of benchmarking single spot fitting and allowed more scores
        // to be computed.
        // 
        // When fitting produces multiple results then we have to score each fit result against all
        // possible actual results and keep a record of the scores. These can then be assessed when
        // the specific results have been chosen by result filtering.
        // 
        // Using a distance ramped scoring function the degree of match can be varied from 0 to 1.
        // Using a signal-factor ramped scoring function the degree of fitted can be varied from 0
        // to 1. When using ramped scoring functions the fractional allocation of scores using the
        // above scheme is performed, i.e. candidates are treated as if they both match and unmatch.
        // This results in an equivalent to multiple analysis using different thresholds and averaging
        // of the scores.
        // 
        // The totals TP+FP+TN+FN must equal the number of spot candidates. This allows different
        // fitting methods to be compared since the total number of candidates is the same.
        // 
        // Precision = TP / (TP+FP)    : This is always valid as a minimum criteria score
        // Recall    = TP / (TP+FN)    : This is valid between different fitting methods since a
        // method that fits more spots will have a potentially lower FN
        // Jaccard   = TP / (TP+FN+FP) : This is valid between fitting methods
        // 
        // -=-=-=-
        // As an alternative scoring system, different fitting methods can be compared using the same
        // TP value but calculating FN = localisations - TP and FP as Positives - TP. This creates a
        // score against the original number of simulated molecules using everything that was passed
        // through the filter (Positives). This score is comparable when a different spot candidate
        // filter has been used and the total number of candidates is different, e.g. Mean filtering
        // vs. Gaussian filtering
        // -=-=-=-
        // @formatter:on
        final RampedScore distanceScore = RampedScore.of(spotFitResults.distanceInPixels * settings.upperMatchDistance / 100.0, spotFitResults.distanceInPixels * settings.partialMatchDistance / 100.0, false);
        localFitResultData.lowerDistanceInPixels = distanceScore.edge1;
        localFitResultData.distanceInPixels = distanceScore.edge0;
        final double matchDistance = MathUtils.pow2(localFitResultData.distanceInPixels);
        localFitResultData.resultsPrefix3 = "\t" + MathUtils.rounded(distanceScore.edge1 * simulationParameters.pixelPitch) + "\t" + MathUtils.rounded(distanceScore.edge0 * simulationParameters.pixelPitch);
        localFitResultData.limitRange = ", d=" + MathUtils.rounded(distanceScore.edge1 * simulationParameters.pixelPitch) + "-" + MathUtils.rounded(distanceScore.edge0 * simulationParameters.pixelPitch);
        // Signal factor must be greater than 1
        final RampedScore signalScore;
        final double spotSignalFactor = BenchmarkSpotFit.getSignalFactor();
        if (spotSignalFactor > 0 && settings.upperSignalFactor > 0) {
            signalScore = RampedScore.of(spotSignalFactor * settings.upperSignalFactor / 100.0, spotSignalFactor * settings.partialSignalFactor / 100.0, false);
            localFitResultData.lowerSignalFactor = signalScore.edge1;
            localFitResultData.signalFactor = signalScore.edge0;
            localFitResultData.resultsPrefix3 += "\t" + MathUtils.rounded(signalScore.edge1) + "\t" + MathUtils.rounded(signalScore.edge0);
            localFitResultData.limitRange += ", s=" + MathUtils.rounded(signalScore.edge1) + "-" + MathUtils.rounded(signalScore.edge0);
        } else {
            signalScore = null;
            localFitResultData.resultsPrefix3 += "\t0\t0";
            localFitResultData.lowerSignalFactor = localFitResultData.signalFactor = 0;
        }
        // Store all the results
        final ArrayList<MultiPathFitResults> multiPathFitResults = new ArrayList<>(spotFitResults.fitResults.size());
        final List<MultiPathFitResults> syncResults = Collections.synchronizedList(multiPathFitResults);
        // This could be multi-threaded ...
        final int nThreads = getThreads(spotFitResults.fitResults.size());
        final BlockingQueue<Job> jobs = new ArrayBlockingQueue<>(nThreads * 2);
        final List<FitResultsWorker> workers = new LinkedList<>();
        final List<Thread> threads = new LinkedList<>();
        final AtomicInteger uniqueId = new AtomicInteger();
        final CoordinateStore localCoordinateStore = createCoordinateStore();
        final Ticker ticker = ImageJUtils.createTicker(spotFitResults.fitResults.size(), nThreads, null);
        for (int i = 0; i < nThreads; i++) {
            final FitResultsWorker worker = new FitResultsWorker(jobs, syncResults, matchDistance, distanceScore, signalScore, uniqueId, localCoordinateStore.newInstance(), ticker, actualCoordinates);
            final Thread t = new Thread(worker);
            workers.add(worker);
            threads.add(t);
            t.start();
        }
        spotFitResults.fitResults.int2ObjectEntrySet().forEach(e -> put(jobs, new Job(e.getIntKey(), e.getValue())));
        // Finish all the worker threads by passing in a null job
        for (int i = threads.size(); i-- != 0; ) {
            put(jobs, new Job(0, null));
        }
        // Wait for all to finish
        for (int i = 0; i < threads.size(); i++) {
            try {
                threads.get(i).join();
                final FitResultsWorker worker = workers.get(i);
                localFitResultData.matches += worker.matches;
                localFitResultData.fittedResults += worker.included;
                localFitResultData.totalResults += worker.total;
                localFitResultData.notDuplicateCount += worker.notDuplicateCount;
                localFitResultData.newResultCount += worker.newResultCount;
                localFitResultData.countActual += worker.includedActual;
                if (i == 0) {
                    localFitResultData.depthStats = worker.depthStats;
                    localFitResultData.depthFitStats = worker.depthFitStats;
                    localFitResultData.signalFactorStats = worker.signalFactorStats;
                    localFitResultData.distanceStats = worker.distanceStats;
                } else {
                    localFitResultData.depthStats.add(worker.depthStats);
                    localFitResultData.depthFitStats.add(worker.depthFitStats);
                    localFitResultData.signalFactorStats.add(worker.signalFactorStats);
                    localFitResultData.distanceStats.add(worker.distanceStats);
                }
            } catch (final InterruptedException ex) {
                Thread.currentThread().interrupt();
                throw new ConcurrentRuntimeException("Unexpected interrupt", ex);
            }
        }
        threads.clear();
        ImageJUtils.finished();
        localFitResultData.maxUniqueId = uniqueId.get();
        localFitResultData.resultsList = multiPathFitResults.toArray(new MultiPathFitResults[0]);
        Arrays.sort(localFitResultData.resultsList, (o1, o2) -> Integer.compare(o1.getFrame(), o2.getFrame()));
        MultiPathFilter.resetValidationFlag(localFitResultData.resultsList);
        FIT_RESULTS_DATA_CACHE.set(localFitResultData);
    }
    fitResultData = localFitResultData;
    return localFitResultData.resultsList;
}
Also used : ArrayList(java.util.ArrayList) GridCoordinateStore(uk.ac.sussex.gdsc.smlm.results.filter.GridCoordinateStore) CoordinateStore(uk.ac.sussex.gdsc.smlm.results.filter.CoordinateStore) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) CustomInt2ObjectOpenHashMap(uk.ac.sussex.gdsc.core.utils.OpenHashMaps.CustomInt2ObjectOpenHashMap) SettingsList(uk.ac.sussex.gdsc.core.utils.SettingsList) FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) Ticker(uk.ac.sussex.gdsc.core.logging.Ticker) LinkedList(java.util.LinkedList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ConcurrentRuntimeException(org.apache.commons.lang3.concurrent.ConcurrentRuntimeException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RampedScore(uk.ac.sussex.gdsc.core.utils.RampedScore) MultiPathFitResults(uk.ac.sussex.gdsc.smlm.results.filter.MultiPathFitResults)

Example 34 with FitEngineConfiguration

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

the class BenchmarkFit method showDialog.

private boolean showDialog() {
    final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
    settings = Settings.load();
    // Save back by reference
    settings.save();
    final double sa = getSa();
    ImageJUtils.addMessage(gd, "Fits the benchmark image created by CreateData plugin.\nPSF width = %s, adjusted = %s", MathUtils.rounded(benchmarkParameters.sd / benchmarkParameters.pixelPitch), MathUtils.rounded(sa));
    final FitEngineConfiguration config = SettingsManager.readFitEngineConfiguration(0);
    fitConfig = config.getFitConfiguration();
    fitConfig.setNmPerPixel(benchmarkParameters.pixelPitch);
    // For each new benchmark width, reset the PSF width to the square pixel adjustment
    if (settings.lastId != benchmarkParameters.id) {
        settings.lastId = benchmarkParameters.id;
        fitConfig.setInitialPeakStdDev(benchmarkParameters.sd / benchmarkParameters.pixelPitch);
        // The adjusted width is only relevant when using a single point approximation
        // for a Gaussian over the pixel. Using the ERF function computes the actual
        // integral over the pixel.
        // fitConfig.setInitialPeakStdDev(sa);
        // Set the PSF. This requires the CreateData plugin to store the most appropriate
        // PSF used for the simulation.
        fitConfig.setPsf(benchmarkParameters.psf);
    }
    gd.addSlider("Region_size", 2, 20, settings.regionSize);
    PeakFit.addPsfOptions(gd, fitConfig);
    gd.addChoice("Fit_solver", SettingsManager.getFitSolverNames(), FitProtosHelper.getName(fitConfig.getFitSolver()));
    gd.addChoice("Origin_XY", Settings.ORIGIN_XY, settings.originXY, new OptionListener<Integer>() {

        @Override
        public boolean collectOptions(Integer value) {
            settings.originXY = value;
            return collectOptions(false);
        }

        @Override
        public boolean collectOptions() {
            return collectOptions(true);
        }

        private boolean collectOptions(boolean silent) {
            if (settings.originXY != 2) {
                return false;
            }
            final ExtendedGenericDialog egd = new ExtendedGenericDialog("Origin XY");
            egd.addNumericField("Offset_X", settings.offsetX, 2, 6, "nm");
            egd.addNumericField("Offset_Y", settings.offsetY, 2, 6, "nm");
            egd.setSilent(silent);
            egd.showDialog(true, gd);
            if (egd.wasCanceled()) {
                return false;
            }
            settings.offsetX = gd.getNextNumber();
            settings.offsetY = gd.getNextNumber();
            return true;
        }
    });
    gd.addChoice("Origin_Z", Settings.ORIGIN_Z, settings.originZ, new OptionListener<Integer>() {

        @Override
        public boolean collectOptions(Integer value) {
            settings.originZ = value;
            return collectOptions(false);
        }

        @Override
        public boolean collectOptions() {
            return collectOptions(true);
        }

        private boolean collectOptions(boolean silent) {
            if (settings.originZ != 2) {
                return false;
            }
            final ExtendedGenericDialog egd = new ExtendedGenericDialog("Origin Z");
            egd.addNumericField("Offset_Z", settings.offsetZ, 2, 6, "nm");
            egd.setSilent(silent);
            egd.showDialog(true, gd);
            if (egd.wasCanceled()) {
                return false;
            }
            settings.offsetZ = gd.getNextNumber();
            return true;
        }
    });
    gd.addCheckbox("Zero_offset", settings.zeroOffset);
    gd.addNumericField("Offset_points", settings.offsetPoints, 0, new OptionListener<Double>() {

        @Override
        public boolean collectOptions(Double value) {
            settings.offsetPoints = Math.max(0, value);
            return collectOptions(false);
        }

        @Override
        public boolean collectOptions() {
            return collectOptions(true);
        }

        private boolean collectOptions(boolean silent) {
            if (settings.offsetPoints == 0) {
                return false;
            }
            final ExtendedGenericDialog egd = new ExtendedGenericDialog("Offset range");
            egd.addSlider("Offset_range_x", 0, 2.5, settings.offsetRangeX);
            egd.addSlider("Offset_range_y", 0, 2.5, settings.offsetRangeY);
            egd.addSlider("Offset_range_z", 0, 2.5, settings.offsetRangeZ);
            egd.setSilent(silent);
            egd.showDialog(true, gd);
            if (egd.wasCanceled()) {
                return false;
            }
            settings.offsetRangeX = Math.max(0, egd.getNextNumber());
            settings.offsetRangeY = Math.max(0, egd.getNextNumber());
            settings.offsetRangeZ = Math.max(0, egd.getNextNumber());
            return true;
        }
    });
    gd.addCheckbox("Background_fitting", settings.backgroundFitting, new OptionListener<Boolean>() {

        @Override
        public boolean collectOptions(Boolean value) {
            settings.backgroundFitting = value;
            return collectOptions(false);
        }

        @Override
        public boolean collectOptions() {
            return collectOptions(true);
        }

        private boolean collectOptions(boolean silent) {
            if (!settings.backgroundFitting) {
                return false;
            }
            final ExtendedGenericDialog egd = new ExtendedGenericDialog("Background fitting");
            egd.addCheckbox("Estimate_background", settings.estimateBackground);
            egd.setSilent(silent);
            egd.showDialog(true, gd);
            if (egd.wasCanceled()) {
                return false;
            }
            settings.estimateBackground = egd.getNextBoolean();
            return true;
        }
    });
    gd.addMessage("Signal fitting can be disabled for " + PsfProtosHelper.getName(PSFType.ONE_AXIS_GAUSSIAN_2D) + " function");
    gd.addCheckbox("Signal_fitting", settings.signalFitting, new OptionListener<Boolean>() {

        @Override
        public boolean collectOptions(Boolean value) {
            settings.signalFitting = value;
            return collectOptions(false);
        }

        @Override
        public boolean collectOptions() {
            return collectOptions(true);
        }

        private boolean collectOptions(boolean silent) {
            if (!settings.signalFitting) {
                return false;
            }
            final ExtendedGenericDialog egd = new ExtendedGenericDialog("Signal fitting");
            egd.addCheckbox("Estimate_signal", settings.estimateSignal);
            egd.setSilent(silent);
            egd.showDialog(true, gd);
            if (egd.wasCanceled()) {
                return false;
            }
            settings.estimateSignal = egd.getNextBoolean();
            return true;
        }
    });
    gd.addCheckbox("Show_histograms", settings.showHistograms);
    gd.addCheckbox("Save_raw_data", settings.saveRawData);
    gd.addHelp(HelpUrls.getUrl("fit-benchmark-data"));
    gd.showDialog();
    if (gd.wasCanceled()) {
        return false;
    }
    settings.regionSize = (int) Math.abs(gd.getNextNumber());
    fitConfig.setPsfType(PeakFit.getPsfTypeValues()[gd.getNextChoiceIndex()]);
    // Some enum values are not supported
    fitConfig.setFitSolver(SettingsManager.getFitSolverValues()[gd.getNextChoiceIndex()]);
    settings.originXY = gd.getNextChoiceIndex();
    settings.originZ = gd.getNextChoiceIndex();
    settings.zeroOffset = gd.getNextBoolean();
    settings.offsetPoints = Math.max(0, gd.getNextNumber());
    settings.backgroundFitting = gd.getNextBoolean();
    settings.signalFitting = gd.getNextBoolean();
    settings.showHistograms = gd.getNextBoolean();
    settings.saveRawData = gd.getNextBoolean();
    gd.collectOptions();
    // Do this before the call to is3D()
    if (!PeakFit.configurePsfModel(config)) {
        return false;
    }
    getStartPoints(fitConfig.is3D());
    if (startPoints.length == 0) {
        IJ.error(TITLE, "No initial fitting positions");
        return false;
    }
    if (settings.regionSize < 1) {
        settings.regionSize = 1;
    }
    if (gd.invalidNumber()) {
        return false;
    }
    // Initialise the correct calibration
    final CalibrationWriter calibration = new CalibrationWriter(fitConfig.getCalibration());
    calibration.setNmPerPixel(benchmarkParameters.pixelPitch);
    calibration.setCountPerPhoton(benchmarkParameters.gain);
    calibration.setQuantumEfficiency(benchmarkParameters.qe);
    calibration.setBias(benchmarkParameters.bias);
    calibration.setCameraType(benchmarkParameters.cameraType);
    calibration.setReadNoise(benchmarkParameters.readNoise);
    calibration.setExposureTime(1000);
    fitConfig.setCalibration(calibration.getCalibration());
    fitConfig.setCameraModelName(benchmarkParameters.cameraModelName);
    if (!PeakFit.configureFitSolver(config, IJImageSource.getBounds(imp), null, 0)) {
        return false;
    }
    if (settings.showHistograms) {
        final ExtendedGenericDialog gd2 = new ExtendedGenericDialog(TITLE);
        gd2.addMessage("Select the histograms to display");
        gd2.addNumericField("Histogram_bins", settings.histogramBins, 0);
        final double[] convert = getConversionFactors();
        for (int i = 0; i < DISPLAY_HISTOGRAMS.length; i++) {
            if (convert[i] != 0) {
                gd2.addCheckbox(NAMES[i].replace(' ', '_'), DISPLAY_HISTOGRAMS[i]);
            }
        }
        gd2.showDialog();
        if (gd2.wasCanceled()) {
            return false;
        }
        settings.histogramBins = (int) Math.abs(gd2.getNextNumber());
        for (int i = 0; i < DISPLAY_HISTOGRAMS.length; i++) {
            if (convert[i] != 0) {
                DISPLAY_HISTOGRAMS[i] = gd2.getNextBoolean();
            }
        }
    }
    return true;
}
Also used : FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CalibrationWriter(uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter)

Example 35 with FitEngineConfiguration

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

the class BenchmarkSpotFilter method updateConfiguration.

/**
 * Updates the given configuration using the latest settings used in benchmarking.
 *
 * @param config the configuration
 * @return true, if successful
 */
public static boolean updateConfiguration(FitEngineConfiguration config) {
    final BenchmarkSpotFilterResult result = FILTER_RESULT.get();
    if (result == null) {
        return false;
    }
    final FitEngineConfiguration latestConfig = result.config;
    config.setDataFilterType(latestConfig.getDataFilterType());
    final int nFilters = latestConfig.getNumberOfFilters();
    for (int n = 0; n < nFilters; n++) {
        final RelativeParameter p = latestConfig.getDataFilterParameter(n);
        config.setDataFilter(latestConfig.getDataFilterMethod(n), p.getValue(), p.getAbsolute(), n);
    }
    config.setSearch(latestConfig.getSearch(), latestConfig.getSearchAbsolute());
    config.setBorder(latestConfig.getBorder(), latestConfig.getBorderAbsolute());
    return true;
}
Also used : FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) RelativeParameter(uk.ac.sussex.gdsc.smlm.data.config.FitProtos.RelativeParameter) PeakResultPoint(uk.ac.sussex.gdsc.smlm.results.PeakResultPoint) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint)

Aggregations

FitEngineConfiguration (uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration)43 FitConfiguration (uk.ac.sussex.gdsc.smlm.engine.FitConfiguration)16 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)10 TemplateSettings (uk.ac.sussex.gdsc.smlm.data.config.TemplateProtos.TemplateSettings)8 ImagePlus (ij.ImagePlus)6 Checkbox (java.awt.Checkbox)6 BasePoint (uk.ac.sussex.gdsc.core.match.BasePoint)6 DataFilterMethod (uk.ac.sussex.gdsc.smlm.data.config.FitProtos.DataFilterMethod)6 PeakResultPoint (uk.ac.sussex.gdsc.smlm.results.PeakResultPoint)6 MultiPathFilter (uk.ac.sussex.gdsc.smlm.results.filter.MultiPathFilter)6 ImageListener (ij.ImageListener)4 Choice (java.awt.Choice)4 Rectangle (java.awt.Rectangle)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 NonBlockingExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog)4 MemoryPeakResults (uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)4 DirectFilter (uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter)4 ImageWindow (ij.gui.ImageWindow)2 NonBlockingGenericDialog (ij.gui.NonBlockingGenericDialog)2 TextField (java.awt.TextField)2