use of gdsc.smlm.fitting.FitConfiguration in project GDSC-SMLM by aherbert.
the class PSFEstimator method calculateStatistics.
private boolean calculateStatistics(PeakFit fitter, double[] params, double[] params_dev) {
debug(" Fitting PSF");
swapStatistics();
// Create the fit engine using the PeakFit plugin
FitConfiguration fitConfig = config.getFitConfiguration();
fitConfig.setInitialAngle((float) params[0]);
fitConfig.setInitialPeakStdDev0((float) params[1]);
fitConfig.setInitialPeakStdDev1((float) params[2]);
ImageStack stack = imp.getImageStack();
Rectangle roi = stack.getProcessor(1).getRoi();
ImageSource source = new IJImageSource(imp);
// Allow interlaced data by wrapping the image source
if (interlacedData) {
source = new InterlacedImageSource(source, dataStart, dataBlock, dataSkip);
}
// Allow frame aggregation by wrapping the image source
if (integrateFrames > 1) {
source = new AggregatedImageSource(source, integrateFrames);
}
fitter.initialiseImage(source, roi, true);
fitter.addPeakResults(this);
fitter.initialiseFitting();
FitEngine engine = fitter.createFitEngine();
// Use random slices
int[] slices = new int[stack.getSize()];
for (int i = 0; i < slices.length; i++) slices[i] = i + 1;
Random rand = new Random();
rand.shuffle(slices);
IJ.showStatus("Fitting ...");
// Use multi-threaded code for speed
int i;
for (i = 0; i < slices.length; i++) {
int slice = slices[i];
//debug(" Processing slice = %d\n", slice);
IJ.showProgress(size(), settings.numberOfPeaks);
ImageProcessor ip = stack.getProcessor(slice);
// stack processor does not set the bounds required by ImageConverter
ip.setRoi(roi);
FitJob job = new FitJob(slice, ImageConverter.getData(ip), roi);
engine.run(job);
if (sampleSizeReached() || Utils.isInterrupted()) {
break;
}
}
if (Utils.isInterrupted()) {
IJ.showProgress(1);
engine.end(true);
return false;
}
// Wait until we have enough results
while (!sampleSizeReached() && !engine.isQueueEmpty()) {
IJ.showProgress(size(), settings.numberOfPeaks);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
break;
}
}
// End now if we have enough samples
engine.end(sampleSizeReached());
IJ.showStatus("");
IJ.showProgress(1);
// This count will be an over-estimate given that the provider is ahead of the consumer
// in this multi-threaded system
debug(" Processed %d/%d slices (%d peaks)", i, slices.length, size());
setParams(ANGLE, params, params_dev, sampleNew[ANGLE]);
setParams(X, params, params_dev, sampleNew[X]);
setParams(Y, params, params_dev, sampleNew[Y]);
if (settings.showHistograms) {
int[] idList = new int[NAMES.length];
int count = 0;
boolean requireRetile = false;
for (int ii = 0; ii < 3; ii++) {
if (sampleNew[ii].getN() == 0)
continue;
StoredDataStatistics stats = new StoredDataStatistics(sampleNew[ii].getValues());
idList[count++] = Utils.showHistogram(TITLE, stats, NAMES[ii], 0, 0, settings.histogramBins, "Mean = " + Utils.rounded(stats.getMean()) + ". Median = " + Utils.rounded(sampleNew[ii].getPercentile(50)));
requireRetile = requireRetile || Utils.isNewWindow();
}
if (requireRetile && count > 0) {
new WindowOrganiser().tileWindows(Arrays.copyOf(idList, count));
}
}
if (size() < 2) {
log("ERROR: Insufficient number of fitted peaks, terminating ...");
return false;
}
return true;
}
use of gdsc.smlm.fitting.FitConfiguration in project GDSC-SMLM by aherbert.
the class PSFEstimator method setup.
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#setup(java.lang.String, ij.ImagePlus)
*/
public int setup(String arg, ImagePlus imp) {
SMLMUsageTracker.recordPlugin(this.getClass(), arg);
extraOptions = Utils.isExtraOptions();
if (imp == null) {
IJ.noImage();
return DONE;
}
globalSettings = SettingsManager.loadSettings();
settings = globalSettings.getPsfEstimatorSettings();
// Reset
if (IJ.controlKeyDown()) {
config = new FitEngineConfiguration(new FitConfiguration());
globalSettings.setFitEngineConfiguration(config);
} else {
config = globalSettings.getFitEngineConfiguration();
}
Roi roi = imp.getRoi();
if (roi != null && roi.getType() != Roi.RECTANGLE) {
IJ.error("Rectangular ROI required");
return DONE;
}
return showDialog(imp);
}
use of gdsc.smlm.fitting.FitConfiguration in project GDSC-SMLM by aherbert.
the class DoubletAnalysis method updateConfiguration.
/**
* Updates the given configuration using the latest fitting settings used in benchmarking.
*
* @param pConfig
* the configuration
* @return true, if successful
*/
public static boolean updateConfiguration(FitEngineConfiguration pConfig) {
final FitConfiguration pFitConfig = pConfig.getFitConfiguration();
pFitConfig.setInitialPeakStdDev(fitConfig.getInitialPeakStdDev0());
pConfig.copyDataFilter(config);
pConfig.setSearch(config.getSearch());
pConfig.setBorder(config.getBorder());
pConfig.setFitting(config.getFitting());
pFitConfig.setFitSolver(fitConfig.getFitSolver());
pFitConfig.setFitFunction(fitConfig.getFitFunction());
pConfig.setIncludeNeighbours(config.isIncludeNeighbours());
pConfig.setNeighbourHeightThreshold(config.getNeighbourHeightThreshold());
pFitConfig.setDuplicateDistance(fitConfig.getDuplicateDistance());
pFitConfig.setMaxIterations(fitConfig.getMaxIterations());
pFitConfig.setMaxFunctionEvaluations(fitConfig.getMaxFunctionEvaluations());
// MLE settings
pFitConfig.setModelCamera(fitConfig.isModelCamera());
pFitConfig.setBias(0);
pFitConfig.setReadNoise(0);
pFitConfig.setAmplification(0);
pFitConfig.setEmCCD(fitConfig.isEmCCD());
pFitConfig.setSearchMethod(fitConfig.getSearchMethod());
pFitConfig.setRelativeThreshold(fitConfig.getRelativeThreshold());
pFitConfig.setAbsoluteThreshold(fitConfig.getAbsoluteThreshold());
pFitConfig.setGradientLineMinimisation(fitConfig.isGradientLineMinimisation());
// LSE settings
pFitConfig.setFitCriteria(fitConfig.getFitCriteria());
pFitConfig.setSignificantDigits(fitConfig.getSignificantDigits());
pFitConfig.setDelta(fitConfig.getDelta());
pFitConfig.setLambda(fitConfig.getLambda());
return true;
}
use of gdsc.smlm.fitting.FitConfiguration in project GDSC-SMLM by aherbert.
the class DoubletAnalysis method runAnalysis.
/**
* Run analysis.
*/
private void runAnalysis() {
if (doubletResults == null) {
IJ.error(TITLE, "No doublet results in memory");
return;
}
// Ask the user to set filters
if (!showAnalysisDialog())
return;
showResults(doubletResults, analysisShowResults);
// Store the effect of fitting as a doublet
ArrayList<DoubletBonus> data = new ArrayList<DoubletBonus>(doubletResults.size());
// True positive and False positives at residuals = 0
double tp = 0;
double fp = 0;
Logger logger = (analysisLogging) ? new IJLogger() : 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
FitConfiguration filterFitConfig2 = filterFitConfig.clone();
filterFitConfig2.setCoordinateShift(Integer.MAX_VALUE);
final int size = 2 * config.getRelativeFitting() + 1;
Rectangle regionBounds = new Rectangle(0, 0, size, size);
final double otherDriftAngle = 180 - analysisDriftAngle;
// Process all the results
for (DoubletResult result : doubletResults) {
// Filter the singles that would be accepted
if (result.good1) {
filterFitConfig.setNoise(result.noise);
FitStatus fitStatus0 = filterFitConfig.validatePeak(0, result.fitResult1.getInitialParameters(), result.fitResult1.getParameters());
double tp1 = 0, fp1 = 0;
if (fitStatus0 == FitStatus.OK) {
tp1 = result.tp1;
fp1 = result.fp1;
} else if (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, fp2 = 0;
// Basic spot criteria (SNR, Photons, width)
filterFitConfig2.setNoise(result.noise);
FitStatus fitStatus1 = filterFitConfig2.validatePeak(0, result.fitResult2.getInitialParameters(), result.fitResult2.getParameters());
FitStatus fitStatus2 = filterFitConfig2.validatePeak(1, result.fitResult2.getInitialParameters(), result.fitResult2.getParameters());
// Log basic failures
boolean[] accept = new boolean[2];
if (fitStatus1 == FitStatus.OK) {
accept[0] = true;
} else if (analysisLogging)
logFailure(logger, 1, result, fitStatus1);
if (fitStatus2 == FitStatus.OK) {
accept[1] = true;
} else if (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]) {
if (result.gap < minGap) {
accept[0] = accept[1] = false;
if (analysisLogging)
logger.info("Reject Doublet (%.2f): Fitted coordinates below min gap (%g<%g)\n", result.getMaxScore(), result.gap, minGap);
}
}
if (accept[0] || accept[1]) {
// The logic in here will be copied to the FitWorker.quadrantAnalysis routine.
double[] params = result.fitResult1.getParameters();
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 * FastMath.min(regionBounds.width, regionBounds.height);
}
// Set an upper limit on the shift that is not too far outside the fit window
final double maxShiftX, maxShiftY;
final double factor = Gaussian2DFunction.SD_TO_HWHM_FACTOR;
if (fitConfig.isWidth0Fitting()) {
// 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.getInitialPeakStdDev0();
maxShiftY = regionBounds.height * 0.5 + factor * fitConfig.getInitialPeakStdDev1();
}
for (int n = 0; n < 2; n++) {
if (!accept[n])
continue;
// Reset
accept[n] = false;
final double xShift = newParams[Gaussian2DFunction.X_POSITION + n * 6] - params[Gaussian2DFunction.X_POSITION];
final double yShift = newParams[Gaussian2DFunction.Y_POSITION + n * 6] - params[Gaussian2DFunction.Y_POSITION];
if (Math.abs(xShift) > maxShiftX || Math.abs(yShift) > maxShiftY) {
if (analysisLogging)
logger.info("Reject P%d (%.2f): Fitted coordinates moved outside fit region (x=%g,y=%g)\n", 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
if (result.a[n] > analysisDriftAngle && result.a[n] < otherDriftAngle) {
if (analysisLogging)
logger.info("Reject P%d (%.2f): Fitted coordinates moved into wrong quadrant (x=%g,y=%g,a=%f)", n + 1, result.getMaxScore(), xShift, yShift, result.a[n]);
continue;
}
// Note: The FitWorker also checks for drift to another candidate.
}
// 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, numberOfMolecules, useMaxResiduals);
if (showJaccardPlot)
plotJaccard(residualsScore, (useMaxResiduals) ? _residualsScoreMax : _residualsScoreAv);
createAnalysisTable();
StringBuilder sb = new StringBuilder(analysisPrefix);
sb.append(analysisTitle).append('\t');
sb.append((useMaxResiduals) ? "Max" : "Average").append('\t');
sb.append(SELECTION_CRITERIA[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.getWidthFactor()).append('\t');
sb.append(filterFitConfig.getPrecisionThreshold()).append('\t');
sb.append(filterFitConfig.isPrecisionUsingBackground()).append('\t');
}
sb.append(analysisDriftAngle).append('\t');
sb.append(minGap).append('\t');
addJaccardScores(sb);
analysisTable.append(sb.toString());
saveTemplate(sb.toString());
}
use of gdsc.smlm.fitting.FitConfiguration in project GDSC-SMLM by aherbert.
the class DoubletAnalysis method itemStateChanged.
/*
* (non-Javadoc)
*
* @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
*/
public void itemStateChanged(ItemEvent e) {
if (e.getSource() instanceof Choice) {
// Update the settings from the template
Choice choice = (Choice) e.getSource();
String templateName = choice.getSelectedItem();
// Get the configuration template
GlobalSettings template = ConfigurationTemplate.getTemplate(templateName);
if (textCoordinateShiftFactor != null) {
if (template != null) {
if (template.isFitEngineConfiguration()) {
FitConfiguration fitConfig = template.getFitEngineConfiguration().getFitConfiguration();
cbSmartFilter.setState(fitConfig.isSmartFilter());
textCoordinateShiftFactor.setText("" + fitConfig.getCoordinateShiftFactor());
textSignalStrength.setText("" + fitConfig.getSignalStrength());
textMinPhotons.setText("" + fitConfig.getMinPhotons());
textMinWidthFactor.setText("" + fitConfig.getMinWidthFactor());
textWidthFactor.setText("" + fitConfig.getWidthFactor());
textPrecisionThreshold.setText("" + fitConfig.getPrecisionThreshold());
cbLocalBackground.setState(fitConfig.isPrecisionUsingBackground());
}
} else {
// Reset
cbSmartFilter.setState(false);
textCoordinateShiftFactor.setText("0");
textSignalStrength.setText("0");
textMinPhotons.setText("0");
textMinWidthFactor.setText("0");
textWidthFactor.setText("0");
textPrecisionThreshold.setText("0");
cbLocalBackground.setState(false);
}
} else {
if (template != null) {
if (template.isFitEngineConfiguration()) {
boolean custom = ConfigurationTemplate.isCustomTemplate(templateName);
FitEngineConfiguration config2 = template.getFitEngineConfiguration();
FitConfiguration fitConfig2 = config2.getFitConfiguration();
if (custom && fitConfig2.getInitialPeakStdDev0() > 0)
textInitialPeakStdDev0.setText("" + fitConfig2.getInitialPeakStdDev0());
textDataFilterType.select(config2.getDataFilterType().ordinal());
textDataFilter.select(config2.getDataFilter(0).ordinal());
textSmooth.setText("" + config2.getSmooth(0));
textSearch.setText("" + config2.getSearch());
textBorder.setText("" + config2.getBorder());
textFitting.setText("" + config2.getFitting());
textFitSolver.select(fitConfig2.getFitSolver().ordinal());
textFitFunction.select(fitConfig2.getFitFunction().ordinal());
// Copy settings not in the dialog for the fit solver
fitConfig.setMaxIterations(fitConfig2.getMaxIterations());
fitConfig.setMaxFunctionEvaluations(fitConfig2.getMaxFunctionEvaluations());
// MLE settings
fitConfig.setModelCamera(fitConfig2.isModelCamera());
fitConfig.setSearchMethod(fitConfig2.getSearchMethod());
fitConfig.setRelativeThreshold(fitConfig2.getRelativeThreshold());
fitConfig.setAbsoluteThreshold(fitConfig2.getAbsoluteThreshold());
fitConfig.setGradientLineMinimisation(fitConfig2.isGradientLineMinimisation());
// LSE settings
fitConfig.setFitCriteria(fitConfig2.getFitCriteria());
fitConfig.setSignificantDigits(fitConfig2.getSignificantDigits());
fitConfig.setDelta(fitConfig2.getDelta());
fitConfig.setLambda(fitConfig2.getLambda());
}
} else {
// Ignore
}
}
} else if (e.getSource() instanceof Checkbox) {
Checkbox checkbox = (Checkbox) e.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.getWidthFactor());
textPrecisionThreshold.setText("" + filterFitConfig.getPrecisionThreshold());
cbLocalBackground.setState(filterFitConfig.isPrecisionUsingBackground());
} else {
if (!updateFitConfiguration(config))
return;
textInitialPeakStdDev0.setText("" + fitConfig.getInitialPeakStdDev0());
textDataFilterType.select(config.getDataFilterType().ordinal());
textDataFilter.select(config.getDataFilter(0).ordinal());
textSmooth.setText("" + config.getSmooth(0));
textSearch.setText("" + config.getSearch());
textBorder.setText("" + config.getBorder());
textFitting.setText("" + config.getFitting());
textFitSolver.select(fitConfig.getFitSolver().ordinal());
textFitFunction.select(fitConfig.getFitFunction().ordinal());
textMatchDistance.setText("" + matchDistance);
textLowerDistance.setText("" + lowerDistance);
textSignalFactor.setText("" + signalFactor);
textLowerFactor.setText("" + lowerSignalFactor);
}
}
}
Aggregations