Search in sources :

Example 1 with FitConfiguration

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

the class BenchmarkSpotFit method showDialog.

private boolean showDialog() {
    ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
    gd.addHelp(HelpUrls.getUrl("fit-spot-data"));
    ImageJUtils.addMessage(gd, "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 \n" + "Configure the fitting:", MathUtils.rounded(simulationParameters.sd), MathUtils.rounded(getSa()));
    gd.addSlider("Fraction_positives", 50, 100, settings.fractionPositives);
    gd.addSlider("Fraction_negatives_after_positives", 0, 100, settings.fractionNegativesAfterAllPositives);
    gd.addSlider("Min_negatives_after_positives", 0, 30, settings.negativesAfterAllPositives);
    gd.addSlider("Match_distance", 0.5, 3.5, settings.distance);
    gd.addSlider("Lower_distance", 0, 3.5, settings.lowerDistance);
    gd.addSlider("Match_signal", 0, 3.5, settings.signalFactor);
    gd.addSlider("Lower_signal", 0, 3.5, settings.lowerSignalFactor);
    final FitEngineConfigurationProvider fitEngineConfigurationProvider = new PeakFit.SimpleFitEngineConfigurationProvider(config);
    // Collect options for fitting
    final double sa = getSa();
    final FitConfiguration fitConfig = config.getFitConfiguration();
    fitConfig.setInitialPeakStdDev(MathUtils.round(sa / simulationParameters.pixelPitch));
    PeakFit.addPsfOptions(gd, fitConfig);
    PeakFit.addFittingOptions(gd, fitEngineConfigurationProvider);
    gd.addChoice("Fit_solver", SettingsManager.getFitSolverNames(), FitProtosHelper.getName(fitConfig.getFitSolver()));
    gd.addMessage("Multi-path filter (used to pick optimum results during fitting)");
    // Allow loading the best filter for these results
    final boolean benchmarkSettingsCheckbox = BenchmarkSpotFitResult.fitResultsId.get() == BenchmarkFilterAnalysis.getLastFittingId();
    Checkbox cbBenchmark = null;
    if (benchmarkSettingsCheckbox) {
        // This should always be an opt-in decision. Otherwise the user cannot use the previous
        // settings.
        cbBenchmark = gd.addAndGetCheckbox("Benchmark_settings", false);
    }
    gd.addTextAreas(XmlUtils.convertQuotes(multiFilter.toXml()), null, 6, 60);
    textFailLimit = gd.addAndGetNumericField("Fail_limit", config.getFailuresLimit(), 0);
    cbIncludeNeighbours = gd.addAndGetCheckbox("Include_neighbours", config.isIncludeNeighbours());
    gd.addAndGetSlider("Neighbour_height", 0.01, 1, config.getNeighbourHeightThreshold());
    textNeighbourHeight = gd.getLastTextField();
    cbComputeDoublets = gd.addAndGetCheckbox("Compute_doublets", settings.computeDoublets);
    PeakFit.addDuplicateDistanceOptions(gd, fitEngineConfigurationProvider);
    gd.addCheckbox("Show_score_histograms", settings.showFilterScoreHistograms);
    gd.addCheckbox("Show_correlation", settings.showCorrelation);
    gd.addCheckbox("Plot_rank_by_intensity", settings.rankByIntensity);
    gd.addCheckbox("Save_filter_range", settings.saveFilterRange);
    if (extraOptions) {
    // No extra options
    }
    // Add a mouse listener to the config file field
    if (cbBenchmark != null && ImageJUtils.isShowGenericDialog()) {
        taFilterXml = gd.getTextArea1();
        cbBenchmark.addItemListener(this);
    }
    gd.showDialog();
    if (gd.wasCanceled()) {
        return false;
    }
    settings.fractionPositives = Math.abs(gd.getNextNumber());
    settings.fractionNegativesAfterAllPositives = Math.abs(gd.getNextNumber());
    settings.negativesAfterAllPositives = (int) Math.abs(gd.getNextNumber());
    settings.distance = Math.abs(gd.getNextNumber());
    settings.lowerDistance = Math.abs(gd.getNextNumber());
    settings.signalFactor = Math.abs(gd.getNextNumber());
    settings.lowerSignalFactor = Math.abs(gd.getNextNumber());
    fitConfig.setPsfType(PeakFit.getPsfTypeValues()[gd.getNextChoiceIndex()]);
    config.setFitting(gd.getNextNumber());
    // Some enum values are not supported
    fitConfig.setFitSolver(SettingsManager.getFitSolverValues()[gd.getNextChoiceIndex()]);
    boolean myUseBenchmarkSettings = false;
    if (benchmarkSettingsCheckbox) {
        // useBenchmarkSettings =
        myUseBenchmarkSettings = gd.getNextBoolean();
    }
    // Read dialog settings
    final String xml = gd.getNextText();
    final int failLimit = (int) gd.getNextNumber();
    final boolean includeNeighbours = gd.getNextBoolean();
    final double neighbourHeightThreshold = gd.getNextNumber();
    final boolean myComputeDoublets = gd.getNextBoolean();
    final double myDuplicateDistance = gd.getNextNumber();
    gd.collectOptions();
    MultiPathFilter myMultiFilter = null;
    if (myUseBenchmarkSettings && !ImageJUtils.isShowGenericDialog()) {
        // Only copy the benchmark settings if not interactive
        final FitEngineConfiguration tmp = new FitEngineConfiguration();
        final FitConfiguration tmpFitConfig = tmp.getFitConfiguration();
        // Collect the residuals threshold
        tmpFitConfig.setComputeResiduals(true);
        if (BenchmarkFilterAnalysis.updateConfiguration(tmp, false)) {
            config.setFailuresLimit(tmp.getFailuresLimit());
            config.setIncludeNeighbours(tmp.isIncludeNeighbours());
            config.setNeighbourHeightThreshold(tmp.getNeighbourHeightThreshold());
            settings.computeDoublets = (tmp.getResidualsThreshold() < 1);
            config.setDuplicateDistance(tmp.getDuplicateDistance());
            config.setDuplicateDistanceAbsolute(tmp.getDuplicateDistanceAbsolute());
            final DirectFilter primaryFilter = tmpFitConfig.getSmartFilter();
            final double residualsThreshold = tmp.getResidualsThreshold();
            myMultiFilter = new MultiPathFilter(primaryFilter, FitWorker.createMinimalFilter(tmpFitConfig.getFilterPrecisionMethod()), residualsThreshold);
        }
    } else {
        myMultiFilter = MultiPathFilter.fromXml(xml);
        config.setFailuresLimit(failLimit);
        config.setIncludeNeighbours(includeNeighbours);
        config.setNeighbourHeightThreshold(neighbourHeightThreshold);
        settings.computeDoublets = myComputeDoublets;
        config.setDuplicateDistance(myDuplicateDistance);
    }
    if (myMultiFilter == null) {
        gd = new ExtendedGenericDialog(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 (settings.computeDoublets) {
        config.setResidualsThreshold(0);
        fitConfig.setComputeResiduals(true);
    } else {
        config.setResidualsThreshold(1);
        fitConfig.setComputeResiduals(false);
    }
    settings.showFilterScoreHistograms = gd.getNextBoolean();
    settings.showCorrelation = gd.getNextBoolean();
    settings.rankByIntensity = gd.getNextBoolean();
    settings.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.setMaxWidthFactor(5);
    // Disable the direct filter
    fitConfig.setDirectFilter(null);
    if (extraOptions) {
    // No extra options
    }
    if (gd.invalidNumber()) {
        return false;
    }
    if (settings.lowerDistance > settings.distance) {
        settings.lowerDistance = settings.distance;
    }
    if (settings.lowerSignalFactor > settings.signalFactor) {
        settings.lowerSignalFactor = settings.signalFactor;
    }
    // Distances relative to sa (not s) as this is the same as the BenchmarkSpotFilter plugin
    distanceInPixels = settings.distance * sa / simulationParameters.pixelPitch;
    lowerDistanceInPixels = settings.lowerDistance * sa / simulationParameters.pixelPitch;
    // Copy simulation defaults if a new simulation.
    // if (lastSimulationId.get() != simulationParameters.id) {
    // This is needed to configure the fit solver.
    fitConfig.setNmPerPixel(simulationParameters.pixelPitch);
    fitConfig.setGain(simulationParameters.gain);
    fitConfig.setQuantumEfficiency(simulationParameters.qe);
    fitConfig.setReadNoise(simulationParameters.readNoise);
    fitConfig.setBias(simulationParameters.bias);
    fitConfig.setCameraType(simulationParameters.cameraType);
    fitConfig.setCameraModel(CreateData.getCameraModel(simulationParameters));
    // }
    if (!PeakFit.configurePsfModel(config)) {
        return false;
    }
    return PeakFit.configureFitSolver(config, IJImageSource.getBounds(imp), null, (extraOptions) ? PeakFit.FLAG_EXTRA_OPTIONS : 0);
}
Also used : FitEngineConfigurationProvider(uk.ac.sussex.gdsc.smlm.ij.plugins.PeakFit.FitEngineConfigurationProvider) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration) Checkbox(java.awt.Checkbox) FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) DirectFilter(uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter) MultiPathFilter(uk.ac.sussex.gdsc.smlm.results.filter.MultiPathFilter) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) PeakResultPoint(uk.ac.sussex.gdsc.smlm.results.PeakResultPoint) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint)

Example 2 with FitConfiguration

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

the class BenchmarkSpotFit method itemStateChanged.

@Override
public void itemStateChanged(ItemEvent event) {
    if (event.getSource() instanceof Checkbox) {
        final Checkbox checkbox = (Checkbox) event.getSource();
        int failLimit;
        boolean includeNeighbours;
        double neighbourHeightThrehsold;
        boolean computeDoublets;
        MultiPathFilter myMultiFilter;
        if (checkbox.getState()) {
            final FitEngineConfiguration tmp = new FitEngineConfiguration();
            final FitConfiguration tmpFitConfig = tmp.getFitConfiguration();
            // 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, FitWorker.createMinimalFilter(tmpFitConfig.getFilterPrecisionMethod()), 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.this.settings.computeDoublets;
            myMultiFilter = multiFilter;
        }
        // Update the dialog
        taFilterXml.setText(myMultiFilter.toXml());
        textFailLimit.setText("" + failLimit);
        cbIncludeNeighbours.setState(includeNeighbours);
        textNeighbourHeight.setText(MathUtils.rounded(neighbourHeightThrehsold));
        cbComputeDoublets.setState(computeDoublets);
    }
}
Also used : Checkbox(java.awt.Checkbox) FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration) DirectFilter(uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter) MultiPathFilter(uk.ac.sussex.gdsc.smlm.results.filter.MultiPathFilter) PeakResultPoint(uk.ac.sussex.gdsc.smlm.results.PeakResultPoint) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint)

Example 3 with FitConfiguration

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

the class DoubletAnalysis method runAnalysis.

/**
 * Run analysis.
 */
private void runAnalysis() {
    final ReferenceResults results = referenceResults.get();
    if (results == null) {
        IJ.error(TITLE, "No doublet results in memory");
        return;
    }
    // Ask the user to set filters
    if (!showAnalysisDialog()) {
        return;
    }
    showResults(results.doubletResults, settings.analysisShowResults);
    // Store the effect of fitting as a doublet
    final ArrayList<DoubletBonus> data = new ArrayList<>(results.doubletResults.size());
    // True positive and False positives at residuals = 0
    double tp = 0;
    double fp = 0;
    final Logger logger = (settings.analysisLogging) ? ImageJPluginLoggerHelper.getLogger(getClass()) : null;
    // Get filters for the single and double fits
    // No coordinate shift for the doublet. We have already done simple checking of the
    // coordinates to get the good=2 flag
    final FitConfiguration filterFitConfig2 = filterFitConfig.createCopy();
    filterFitConfig2.setCoordinateShift(Integer.MAX_VALUE);
    final int size = 2 * config.getFittingWidth() + 1;
    final Rectangle regionBounds = new Rectangle(0, 0, size, size);
    final double otherDriftAngle = 180 - settings.analysisDriftAngle;
    final FitConfiguration fitConfig = config.getFitConfiguration();
    filterFitConfig.setup();
    // Process all the results
    for (final DoubletResult result : results.doubletResults) {
        // Filter the singles that would be accepted
        if (result.good1) {
            filterFitConfig.setNoise(result.noise);
            final FitStatus fitStatus0 = filterFitConfig.validatePeak(0, result.fitResult1.getInitialParameters(), result.fitResult1.getParameters(), result.fitResult1.getParameterDeviations());
            double tp1 = 0;
            double fp1 = 0;
            if (fitStatus0 == FitStatus.OK) {
                tp1 = result.tp1;
                fp1 = result.fp1;
            } else if (settings.analysisLogging) {
                logFailure(logger, 0, result, fitStatus0);
            }
            // width diverged spots as OK for a doublet fit
            if ((fitStatus0 == FitStatus.OK || fitStatus0 == FitStatus.WIDTH_DIVERGED) && selectFit(result) && result.good2) {
                double tp2 = 0;
                double fp2 = 0;
                // Basic spot criteria (SNR, Photons, width)
                filterFitConfig2.setNoise(result.noise);
                final FitStatus fitStatus1 = filterFitConfig2.validatePeak(0, result.fitResult2.getInitialParameters(), result.fitResult2.getParameters(), result.fitResult2.getParameterDeviations());
                final FitStatus fitStatus2 = filterFitConfig2.validatePeak(1, result.fitResult2.getInitialParameters(), result.fitResult2.getParameters(), result.fitResult2.getParameterDeviations());
                // Log basic failures
                final boolean[] accept = new boolean[2];
                if (fitStatus1 == FitStatus.OK) {
                    accept[0] = true;
                } else if (settings.analysisLogging) {
                    logFailure(logger, 1, result, fitStatus1);
                }
                if (fitStatus2 == FitStatus.OK) {
                    accept[1] = true;
                } else if (settings.analysisLogging) {
                    logFailure(logger, 2, result, fitStatus2);
                }
                // We can filter each spot with criteria such as shift and the angle to the quadrant.
                if ((accept[0] || accept[1]) && (result.gap < settings.minGap)) {
                    accept[0] = accept[1] = false;
                    if (logger != null) {
                        LoggerUtils.log(logger, Level.INFO, "Reject Doublet (%.2f): Fitted coordinates below min gap (%g<%g)", result.getMaxScore(), result.gap, settings.minGap);
                    }
                }
                if (accept[0] || accept[1]) {
                    // The logic in here will be copied to the FitWorker.quadrantAnalysis routine.
                    final double[] params = result.fitResult1.getParameters();
                    final double[] newParams = result.fitResult2.getParameters();
                    // Set up for shift filtering
                    double shift = filterFitConfig.getCoordinateShift();
                    if (shift == 0 || shift == Double.POSITIVE_INFINITY) {
                        // Allow the shift to span half of the fitted window.
                        shift = 0.5 * Math.min(regionBounds.width, regionBounds.height);
                    }
                    // Set an upper limit on the shift that is not too far outside the fit window
                    final double maxShiftX;
                    final double maxShiftY;
                    final double factor = Gaussian2DFunction.SD_TO_HWHM_FACTOR;
                    if (fitConfig.isXSdFitting()) {
                        // Add the fitted standard deviation to the allowed shift
                        maxShiftX = regionBounds.width * 0.5 + factor * params[Gaussian2DFunction.X_SD];
                        maxShiftY = regionBounds.height * 0.5 + factor * params[Gaussian2DFunction.Y_SD];
                    } else {
                        // Add the configured standard deviation to the allowed shift
                        maxShiftX = regionBounds.width * 0.5 + factor * fitConfig.getInitialXSd();
                        maxShiftY = regionBounds.height * 0.5 + factor * fitConfig.getInitialYSd();
                    }
                    for (int n = 0; n < 2; n++) {
                        if (!accept[n]) {
                            continue;
                        }
                        // Reset
                        accept[n] = false;
                        final double xShift = newParams[Gaussian2DFunction.X_POSITION + n * Gaussian2DFunction.PARAMETERS_PER_PEAK] - params[Gaussian2DFunction.X_POSITION];
                        final double yShift = newParams[Gaussian2DFunction.Y_POSITION + n * Gaussian2DFunction.PARAMETERS_PER_PEAK] - params[Gaussian2DFunction.Y_POSITION];
                        if (Math.abs(xShift) > maxShiftX || Math.abs(yShift) > maxShiftY) {
                            if (logger != null) {
                                LoggerUtils.log(logger, Level.INFO, "Reject P%d (%.2f): Fitted coordinates moved outside fit region (x=%g,y=%g)", n + 1, result.getMaxScore(), xShift, yShift);
                            }
                            continue;
                        }
                        if ((Math.abs(xShift) > shift || Math.abs(yShift) > shift) && // Allow up to a 45 degree difference to show the shift is along the vector
                        (result.angle[n] > settings.analysisDriftAngle && result.angle[n] < otherDriftAngle)) {
                            if (logger != null) {
                                LoggerUtils.log(logger, Level.INFO, "Reject P%d (%.2f): Fitted coordinates moved into wrong quadrant" + " (x=%g,y=%g,a=%f)", n + 1, result.getMaxScore(), xShift, yShift, result.angle[n]);
                            }
                            continue;
                        }
                        // This is OK
                        accept[n] = true;
                    }
                }
                if (accept[0]) {
                    tp2 += result.tp2a;
                    fp2 += result.fp2a;
                }
                if (accept[1]) {
                    tp2 += result.tp2b;
                    fp2 += result.fp2b;
                }
                if (accept[0] || accept[1]) {
                    tp += tp2;
                    fp += fp2;
                    // Store this as a doublet bonus
                    data.add(new DoubletBonus(result.getMaxScore(), result.getAvScore(), tp2 - tp1, fp2 - fp1));
                } else {
                    // No doublet fit so this will always be the single fit result
                    tp += tp1;
                    fp += fp1;
                }
            } else {
                // No doublet fit so this will always be the single fit result
                tp += tp1;
                fp += fp1;
            }
        }
    }
    // Compute the max Jaccard
    computeScores(data, tp, fp, results.numberOfMolecules, settings.useMaxResiduals);
    if (settings.showJaccardPlot) {
        plotJaccard(residualsScore, (settings.useMaxResiduals) ? results.residualsScoreMax : results.residualsScoreAv);
    }
    final StringBuilder sb = new StringBuilder(results.analysisPrefix);
    sb.append(settings.analysisTitle).append('\t');
    sb.append((settings.useMaxResiduals) ? "Max" : "Average").append('\t');
    sb.append(Settings.SELECTION_CRITERIAS[settings.selectionCriteria]).append('\t');
    if (filterFitConfig.isSmartFilter()) {
        sb.append(filterFitConfig.getSmartFilterName()).append("\t\t\t\t\t\t\t\t");
    } else {
        sb.append('\t');
        sb.append(filterFitConfig.getCoordinateShiftFactor()).append('\t');
        sb.append(filterFitConfig.getSignalStrength()).append('\t');
        sb.append(filterFitConfig.getMinPhotons()).append('\t');
        sb.append(filterFitConfig.getMinWidthFactor()).append('\t');
        sb.append(filterFitConfig.getMaxWidthFactor()).append('\t');
        sb.append(filterFitConfig.getPrecisionThreshold()).append('\t');
        sb.append(filterFitConfig.getPrecisionMethod()).append('\t');
    }
    sb.append(settings.analysisDriftAngle).append('\t');
    sb.append(settings.minGap).append('\t');
    addJaccardScores(sb);
    createAnalysisTable().append(sb.toString());
    saveTemplate(sb.toString());
}
Also used : ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) Logger(java.util.logging.Logger) PeakResultPoint(uk.ac.sussex.gdsc.smlm.results.PeakResultPoint) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) FitStatus(uk.ac.sussex.gdsc.smlm.fitting.FitStatus) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration)

Example 4 with FitConfiguration

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

the class DoubletAnalysis method summariseResults.

/**
 * Summarise results.
 *
 * @param results the results
 * @param density the density
 * @param runTime the run time
 */
private void summariseResults(ArrayList<DoubletResult> results, double density, long runTime) {
    // If we are only assessing results with no neighbour candidates
    // TODO - Count the number of actual results that have no neighbours
    final int numberOfMolecules = this.results.size() - ignored.get();
    final FitConfiguration fitConfig = config.getFitConfiguration();
    // Store details we want in the analysis table
    final StringBuilder sb = new StringBuilder();
    sb.append(MathUtils.rounded(density)).append('\t');
    sb.append(MathUtils.rounded(getSa())).append('\t');
    sb.append(config.getFittingWidth()).append('\t');
    sb.append(PsfProtosHelper.getName(fitConfig.getPsfType()));
    sb.append(":").append(PeakFit.getSolverName(fitConfig));
    if (fitConfig.isModelCameraMle()) {
        sb.append(":Camera\t");
        // Add details of the noise model for the MLE
        final CalibrationReader r = new CalibrationReader(fitConfig.getCalibration());
        sb.append("EM=").append(r.isEmCcd());
        sb.append(":A=").append(MathUtils.rounded(r.getCountPerElectron()));
        sb.append(":N=").append(MathUtils.rounded(r.getReadNoise()));
        sb.append('\t');
    } else {
        sb.append("\t\t");
    }
    final String analysisPrefix = sb.toString();
    // -=-=-=-=-
    showResults(results, settings.showResults);
    sb.setLength(0);
    final int n = countN(results);
    // Create the benchmark settings and the fitting settings
    sb.append(numberOfMolecules).append('\t');
    sb.append(n).append('\t');
    sb.append(MathUtils.rounded(density)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.minSignal)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.maxSignal)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.averageSignal)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.sd)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.pixelPitch)).append('\t');
    sb.append(MathUtils.rounded(getSa() * simulationParameters.pixelPitch)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.gain)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.readNoise)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.background)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.noise)).append('\t');
    sb.append(MathUtils.rounded(simulationParameters.averageSignal / simulationParameters.noise)).append('\t');
    sb.append(config.getFittingWidth()).append('\t');
    sb.append(PsfProtosHelper.getName(fitConfig.getPsfType()));
    sb.append(":").append(PeakFit.getSolverName(fitConfig));
    if (fitConfig.isModelCameraMle()) {
        sb.append(":Camera\t");
        // Add details of the noise model for the MLE
        final CalibrationReader r = new CalibrationReader(fitConfig.getCalibration());
        sb.append("EM=").append(r.isEmCcd());
        sb.append(":A=").append(MathUtils.rounded(r.getCountPerElectron()));
        sb.append(":N=").append(MathUtils.rounded(r.getReadNoise()));
        sb.append('\t');
    } else {
        sb.append("\t\t");
    }
    // Now output the actual results ...
    // Show histograms as cumulative to avoid problems with bin width
    // Residuals scores
    // Iterations and evaluations where fit was OK
    final StoredDataStatistics[] stats = new StoredDataStatistics[Settings.NAMES2.length];
    for (int i = 0; i < stats.length; i++) {
        stats[i] = new StoredDataStatistics();
    }
    // For Jaccard scoring we need to count the score with no residuals threshold,
    // i.e. Accumulate the score accepting all doublets that were fit
    double tp = 0;
    double fp = 0;
    double bestTp = 0;
    double bestFp = 0;
    final ArrayList<DoubletBonus> data = new ArrayList<>(results.size());
    for (final DoubletResult result : results) {
        final double score = result.getMaxScore();
        // Filter the singles that would be accepted
        if (result.good1) {
            // Filter the doublets that would be accepted
            if (result.good2) {
                final double tp2 = result.tp2a + result.tp2b;
                final double fp2 = result.fp2a + result.fp2b;
                tp += tp2;
                fp += fp2;
                if (result.tp2a > 0.5) {
                    bestTp += result.tp2a;
                    bestFp += result.fp2a;
                }
                if (result.tp2b > 0.5) {
                    bestTp += result.tp2b;
                    bestFp += result.fp2b;
                }
                // Store this as a doublet bonus
                data.add(new DoubletBonus(score, result.getAvScore(), tp2 - result.tp1, fp2 - result.fp1));
            } else {
                // No doublet fit so this will always be the single fit result
                tp += result.tp1;
                fp += result.fp1;
                if (result.tp1 > 0.5) {
                    bestTp += result.tp1;
                    bestFp += result.fp1;
                }
            }
        }
        // Build statistics
        final int c = result.matchClass;
        // True results, i.e. where there was a choice between single or doublet
        if (result.valid) {
            stats[c].add(score);
        }
        // Of those where the fit was good, summarise the iterations and evaluations
        if (result.good1) {
            stats[3].add(result.iter1);
            stats[4].add(result.eval1);
            // about the iteration increase for singles that are not doublets.
            if (c != 0 && result.good2) {
                stats[5].add(result.iter2);
                stats[6].add(result.eval2);
            }
        }
    }
    // Debug the counts
    // double tpSingle = 0;
    // double fpSingle = 0;
    // double tpDoublet = 0;
    // double fpDoublet = 0;
    // int nSingle = 0, nDoublet = 0;
    // for (DoubletResult result : results) {
    // if (result.good1) {
    // if (result.good2) {
    // tpDoublet += result.tp2a + result.tp2b;
    // fpDoublet += result.fp2a + result.fp2b;
    // nDoublet++;
    // }
    // tpSingle += result.tp1;
    // fpSingle += result.fp1;
    // nSingle++;
    // }
    // }
    // System.out.printf("Single %.1f,%.1f (%d) : Doublet %.1f,%.1f (%d)\n", tpSingle, fpSingle,
    // nSingle, tpDoublet, fpDoublet, nDoublet * 2);
    // Summarise score for true results
    final Percentile p = new Percentile(99);
    for (int c = 0; c < stats.length; c++) {
        final double[] values = stats[c].getValues();
        // Sorting is need for the percentile and the cumulative histogram so do it once
        Arrays.sort(values);
        sb.append(MathUtils.rounded(stats[c].getMean())).append("+/-").append(MathUtils.rounded(stats[c].getStandardDeviation())).append(" (").append(stats[c].getN()).append(") ").append(MathUtils.rounded(p.evaluate(values))).append('\t');
        if (settings.showHistograms && settings.displayHistograms[c + Settings.NAMES.length]) {
            showCumulativeHistogram(values, Settings.NAMES2[c]);
        }
    }
    sb.append(Settings.MATCHING_METHODS[settings.matchingMethod]).append('\t');
    // Plot a graph of the additional results we would fit at all score thresholds.
    // This assumes we just pick the the doublet if we fit it (NO FILTERING at all!)
    // Initialise the score for residuals 0
    // Store this as it serves as a baseline for the filtering analysis
    final ResidualsScore residualsScoreMax = computeScores(data, tp, fp, numberOfMolecules, true);
    final ResidualsScore residualsScoreAv = computeScores(data, tp, fp, numberOfMolecules, false);
    residualsScore = (settings.useMaxResiduals) ? residualsScoreMax : residualsScoreAv;
    if (settings.showJaccardPlot) {
        plotJaccard(residualsScore, null);
    }
    final String bestJaccard = MathUtils.rounded(bestTp / (bestFp + numberOfMolecules)) + '\t';
    final String analysisPrefix2 = analysisPrefix + bestJaccard;
    sb.append(bestJaccard);
    addJaccardScores(sb);
    sb.append('\t').append(TextUtils.nanosToString(runTime));
    createSummaryTable().append(sb.toString());
    // Store results in memory for later analysis
    referenceResults.set(new ReferenceResults(results, residualsScoreMax, residualsScoreAv, numberOfMolecules, analysisPrefix2));
}
Also used : Percentile(org.apache.commons.math3.stat.descriptive.rank.Percentile) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) ArrayList(java.util.ArrayList) CalibrationReader(uk.ac.sussex.gdsc.smlm.data.config.CalibrationReader) PeakResultPoint(uk.ac.sussex.gdsc.smlm.results.PeakResultPoint) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration)

Example 5 with FitConfiguration

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

the class DoubletAnalysis method itemStateChanged.

@Override
public void itemStateChanged(ItemEvent event) {
    if (event.getSource() instanceof Choice) {
        // Update the settings from the template
        final Choice choice = (Choice) event.getSource();
        final String templateName = choice.getSelectedItem();
        // Get the configuration template
        final TemplateSettings template = ConfigurationTemplate.getTemplate(templateName);
        if (textCoordinateShiftFactor != null) {
            // Start with a default. This will cause a reset.
            final FitConfiguration fitConfig = new FitConfiguration();
            if (template != null) {
                fitConfig.setFitSettings(template.getFitEngineSettings().getFitSettings());
            }
            cbSmartFilter.setState(fitConfig.isSmartFilter());
            textCoordinateShiftFactor.setText("" + fitConfig.getCoordinateShiftFactor());
            textSignalStrength.setText("" + fitConfig.getSignalStrength());
            textMinPhotons.setText("" + fitConfig.getMinPhotons());
            textMinWidthFactor.setText("" + fitConfig.getMinWidthFactor());
            textWidthFactor.setText("" + fitConfig.getMaxWidthFactor());
            textPrecisionThreshold.setText("" + fitConfig.getPrecisionThreshold());
            textPrecisionMethod.select(fitConfig.getPrecisionMethod().ordinal());
        } else if (template != null) {
            if (template.hasFitEngineSettings()) {
                final boolean custom = ConfigurationTemplate.isCustomTemplate(templateName);
                final FitEngineConfiguration config2 = new FitEngineConfiguration(template.getFitEngineSettings(), template.getCalibration(), template.getPsf());
                final FitConfiguration fitConfig2 = config2.getFitConfiguration();
                if (custom && template.hasPsf()) {
                    textPsf.select(PeakFit.getPsfTypeNames()[fitConfig2.getPsfType().ordinal()]);
                }
                textDataFilterType.select(config2.getDataFilterType().ordinal());
                textDataFilter.select(config2.getDataFilterMethod(0).ordinal());
                textSmooth.setText("" + config2.getDataFilterParameterValue(0));
                textSearch.setText("" + config2.getSearch());
                textBorder.setText("" + config2.getBorder());
                textFitting.setText("" + config2.getFitting());
                textFitSolver.select(FitProtosHelper.getName(fitConfig2.getFitSolver()));
                // Copy settings not in the dialog for the fit solver
                final FitConfiguration fitConfig = config.getFitConfiguration();
                if (custom) {
                    fitConfig.setPsf(fitConfig2.getPsf());
                }
                fitConfig.setFitSolverSettings(fitConfig2.getFitSolverSettings());
            }
        } else {
        // Ignore
        }
    } else if (event.getSource() instanceof Checkbox) {
        final Checkbox checkbox = (Checkbox) event.getSource();
        if (!checkbox.getState()) {
            return;
        }
        if (textCoordinateShiftFactor != null) {
            if (!updateFilterConfiguration(filterFitConfig)) {
                return;
            }
            cbSmartFilter.setState(filterFitConfig.isSmartFilter());
            textCoordinateShiftFactor.setText("" + filterFitConfig.getCoordinateShiftFactor());
            textSignalStrength.setText("" + filterFitConfig.getSignalStrength());
            textMinPhotons.setText("" + filterFitConfig.getMinPhotons());
            textMinWidthFactor.setText("" + filterFitConfig.getMinWidthFactor());
            textWidthFactor.setText("" + filterFitConfig.getMaxWidthFactor());
            textPrecisionThreshold.setText("" + filterFitConfig.getPrecisionThreshold());
            textPrecisionMethod.select(filterFitConfig.getPrecisionMethod().ordinal());
        } else {
            if (!updateFitConfiguration(config)) {
                return;
            }
            final FitConfiguration fitConfig = config.getFitConfiguration();
            textPsf.select(PeakFit.getPsfTypeNames()[fitConfig.getPsfType().ordinal()]);
            textDataFilterType.select(config.getDataFilterType().ordinal());
            textDataFilter.select(config.getDataFilterMethod(0).ordinal());
            textSmooth.setText("" + config.getDataFilterParameterValue(0));
            textSearch.setText("" + config.getSearch());
            textBorder.setText("" + config.getBorder());
            textFitting.setText("" + config.getFitting());
            textFitSolver.select(FitProtosHelper.getName(fitConfig.getFitSolver()));
            textMatchDistance.setText("" + settings.matchDistance);
            textLowerDistance.setText("" + settings.lowerDistance);
            textSignalFactor.setText("" + settings.signalFactor);
            textLowerFactor.setText("" + settings.lowerSignalFactor);
        }
    }
}
Also used : TemplateSettings(uk.ac.sussex.gdsc.smlm.data.config.TemplateProtos.TemplateSettings) Choice(java.awt.Choice) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration) FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) Checkbox(java.awt.Checkbox)

Aggregations

FitConfiguration (uk.ac.sussex.gdsc.smlm.engine.FitConfiguration)32 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)11 FitEngineConfiguration (uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration)9 BasePoint (uk.ac.sussex.gdsc.core.match.BasePoint)8 PeakResultPoint (uk.ac.sussex.gdsc.smlm.results.PeakResultPoint)7 Checkbox (java.awt.Checkbox)6 Rectangle (java.awt.Rectangle)5 CalibrationWriter (uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter)5 ArrayList (java.util.ArrayList)4 ImageStack (ij.ImageStack)3 TextField (java.awt.TextField)3 ConcurrentRuntimeException (org.apache.commons.lang3.concurrent.ConcurrentRuntimeException)3 StoredDataStatistics (uk.ac.sussex.gdsc.core.utils.StoredDataStatistics)3 PSF (uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF)3 BenchmarkSpotFilterResult (uk.ac.sussex.gdsc.smlm.ij.plugins.benchmark.BenchmarkSpotFilter.BenchmarkSpotFilterResult)3 MemoryPeakResults (uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)3 TIntObjectHashMap (gnu.trove.map.hash.TIntObjectHashMap)2 Choice (java.awt.Choice)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2