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);
}
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);
}
}
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());
}
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));
}
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);
}
}
}
Aggregations