use of uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog in project GDSC-SMLM by aherbert.
the class CreateData method showLoadDialog.
/**
* Show a dialog allowing the parameters for a benchmark simulation to be loaded.
*
* @return True if the parameters were collected
*/
private static boolean showLoadDialog() {
final String[] images = ImageJUtils.getImageList(ImageJUtils.GREY_SCALE);
if (images.length == 0) {
IJ.error(TITLE, "No greyscale benchmark images");
return false;
}
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addChoice("Image", images, benchmarkImage);
gd.addFilenameField("Results_file", benchmarkFile);
gd.addMessage(TextUtils.wrap("Specify if the results are preprocessed. This is true only if the simulation was " + "previously loaded and then saved to a GDSC SMLM file format from memory. Set to " + "false to load using a universal results loader.", 80));
gd.addCheckbox("Preprocessed_results", benchmarkAuto);
gd.addHelp(HelpUrls.getUrl("load-benchmark-data"));
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
benchmarkImage = gd.getNextChoice();
benchmarkFile = gd.getNextString();
benchmarkAuto = gd.getNextBoolean();
Prefs.set(KEY_BENCHMARK_IMAGE, benchmarkImage);
Prefs.set(KEY_BENCHMARK_RESULTS_FILE, benchmarkFile);
return true;
}
use of uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog 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.core.ij.gui.ExtendedGenericDialog in project GDSC-SMLM by aherbert.
the class BenchmarkSpotFilter method showDialog.
private boolean showDialog() {
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
settings = Settings.load();
config = settings.config;
final StringBuilder sb = new StringBuilder();
sb.append("Finds spots in the benchmark image created by CreateData plugin.\n");
final double s = simulationParameters.sd / simulationParameters.pixelPitch;
final double sa = getSa() / simulationParameters.pixelPitch;
sb.append("PSF width = ").append(MathUtils.rounded(s)).append(" px (sa = ").append(MathUtils.rounded(sa)).append(" px). HWHM = ").append(MathUtils.rounded(s * Gaussian2DFunction.SD_TO_HWHM_FACTOR)).append(" px\n");
sb.append("Simulation depth = ").append(MathUtils.rounded(simulationParameters.depth)).append(" nm");
if (simulationParameters.fixedDepth) {
sb.append(" (fixed)");
}
sb.append("\n \nConfigure the spot filter:");
gd.addMessage(sb.toString());
if (batchMode) {
// Support enumeration of single/difference spot filters
gd.addCheckbox("Mean", settings.batchMean);
gd.addCheckbox("Gaussian", settings.batchGaussian);
gd.addCheckbox("Circular", settings.batchCircular);
gd.addCheckbox("Median", settings.batchMedian);
// For difference filters we set the smoothing for the second filter
// using only one distance
gd.addMessage("Difference filter settings:");
gd.addCheckbox("Difference_filter", settings.differenceFilter);
gd.addSlider("Difference_smoothing", 1.5, 5, settings.differenceSmooth);
gd.addMessage("Local maxima search settings:");
gd.addSlider("Min_search_width", 1, 4, settings.minSearch);
gd.addSlider("Max_search_width", 1, 4, settings.maxSearch);
gd.addCheckbox("Filter_relative_distances (to HWHM)", settings.filterRelativeDistances);
} else {
gd.addChoice("Spot_filter_type", SettingsManager.getDataFilterTypeNames(), config.getDataFilterType().ordinal());
gd.addChoice("Spot_filter", SettingsManager.getDataFilterMethodNames(), config.getDataFilterMethod(0).ordinal());
gd.addCheckbox("Filter_relative_distances (to HWHM)", !config.getDataFilterParameterAbsolute(0));
gd.addSlider("Smoothing", 0, 2.5, config.getDataFilterParameterValue(0));
gd.addSlider("Search_width", 1, 4, settings.search);
}
gd.addSlider("Border", 0, 5, settings.border);
gd.addMessage("Scoring options:");
gd.addCheckbox("Score_relative_distances (to HWHM)", settings.scoreRelativeDistances);
gd.addSlider("Analysis_border", 0, 5, settings.analysisBorder);
gd.addCheckbox("Hard_border", settings.hardBorder);
gd.addChoice("Matching_method", Settings.MATCHING_METHOD, settings.matchingMethod);
gd.addSlider("Match_distance", 0.5, 3.5, settings.upperDistance);
gd.addSlider("Lower_distance", 0, 3.5, settings.lowerDistance);
gd.addSlider("Signal_factor", 0, 3.5, settings.upperSignalFactor);
gd.addSlider("Lower_factor", 0, 3.5, settings.lowerSignalFactor);
gd.addSlider("Recall_fraction", 50, 100, settings.recallFraction);
if (!batchMode) {
gd.addCheckbox("Show_plots", settings.showPlot);
gd.addCheckbox("Plot_rank_by_intensity", settings.rankByIntensity);
gd.addCheckbox("Show_failures_plots", settings.showFailuresPlot);
gd.addCheckbox("Show_TP", settings.showTP);
gd.addCheckbox("Show_FP", settings.showFP);
gd.addCheckbox("Show_FN", settings.showFN);
}
if (extraOptions) {
gd.addCheckbox("Debug", settings.debug);
}
if (batchMode) {
gd.addHelp(HelpUrls.getUrl("filter-spot-data-batch"));
} else {
gd.addHelp(HelpUrls.getUrl("filter-spot-data"));
}
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
// Here we use PSF stored in the results if supported (i.e. a Gaussian).
// The results are likely to come from the CreateData simulation.
final PSF psf = results.getPsf();
if (PsfHelper.isGaussian2D(psf)) {
config.getFitConfiguration().setPsf(results.getPsf());
} else {
config.getFitConfiguration().setInitialPeakStdDev(s);
}
if (batchMode) {
settings.batchMean = gd.getNextBoolean();
settings.batchGaussian = gd.getNextBoolean();
settings.batchCircular = gd.getNextBoolean();
settings.batchMedian = gd.getNextBoolean();
if (!(settings.batchMean || settings.batchGaussian || settings.batchCircular || settings.batchMedian)) {
return false;
}
settings.differenceFilter = gd.getNextBoolean();
settings.differenceSmooth = gd.getNextNumber();
settings.minSearch = (int) gd.getNextNumber();
settings.maxSearch = (int) gd.getNextNumber();
settings.filterRelativeDistances = gd.getNextBoolean();
} else {
config.setDataFilterType(SettingsManager.getDataFilterTypeValues()[gd.getNextChoiceIndex()]);
final int filterIndex = gd.getNextChoiceIndex();
settings.filterRelativeDistances = gd.getNextBoolean();
final double smoothing = Math.abs(gd.getNextNumber());
config.setDataFilter(SettingsManager.getDataFilterMethodValues()[filterIndex], MathUtils.roundUsingDecimalPlaces(smoothing, 3), !settings.filterRelativeDistances, 0);
settings.search = gd.getNextNumber();
}
settings.border = gd.getNextNumber();
settings.scoreRelativeDistances = gd.getNextBoolean();
settings.analysisBorder = Math.abs(gd.getNextNumber());
settings.hardBorder = gd.getNextBoolean();
settings.matchingMethod = gd.getNextChoiceIndex();
settings.upperDistance = Math.abs(gd.getNextNumber());
settings.lowerDistance = Math.abs(gd.getNextNumber());
settings.upperSignalFactor = Math.abs(gd.getNextNumber());
settings.lowerSignalFactor = Math.abs(gd.getNextNumber());
settings.recallFraction = Math.abs(gd.getNextNumber());
if (!batchMode) {
settings.showPlot = gd.getNextBoolean();
settings.rankByIntensity = gd.getNextBoolean();
settings.showFailuresPlot = gd.getNextBoolean();
settings.showTP = gd.getNextBoolean();
settings.showFP = gd.getNextBoolean();
settings.showFN = gd.getNextBoolean();
}
if (extraOptions) {
settings.debug = gd.getNextBoolean();
}
settings.save();
if (gd.invalidNumber()) {
return false;
}
if (settings.lowerDistance > settings.upperDistance) {
settings.lowerDistance = settings.upperDistance;
}
if (settings.lowerSignalFactor > settings.upperSignalFactor) {
settings.lowerSignalFactor = settings.upperSignalFactor;
}
// Set border here so that the results are consistent with single-filter mode.
config.setBorder(MathUtils.roundUsingDecimalPlaces(settings.border, 3), !settings.filterRelativeDistances);
if (!batchMode) {
// Single filter ...
config.setSearch(MathUtils.roundUsingDecimalPlaces(settings.search, 3), !settings.filterRelativeDistances);
// Allow more complicated filters to be configured
if (!PeakFit.configureDataFilter(config, PeakFit.FLAG_NO_SAVE)) {
return false;
}
}
int analysisBorder;
if (settings.scoreRelativeDistances) {
// Convert distance to PSF standard deviation units
final double hwhmMax = config.getHwhmMax();
matchDistance = settings.upperDistance * hwhmMax;
lowerMatchDistance = settings.lowerDistance * hwhmMax;
analysisBorder = (int) (settings.analysisBorder * hwhmMax);
} else {
matchDistance = settings.upperDistance;
lowerMatchDistance = settings.lowerDistance;
analysisBorder = (int) settings.analysisBorder;
}
if (analysisBorder > 0) {
border = new Rectangle(analysisBorder, analysisBorder, imp.getWidth() - 2 * analysisBorder, imp.getHeight() - 2 * analysisBorder);
} else {
border = new Rectangle(imp.getWidth(), imp.getHeight());
}
return true;
}
use of uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog in project GDSC-SMLM by aherbert.
the class BenchmarkSpotFilter method run.
@Override
public void run(String arg) {
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
extraOptions = ImageJUtils.isExtraOptions();
batchMode = "batch".equals(arg);
simulationParameters = CreateData.getSimulationParameters();
if (simulationParameters == null) {
IJ.error(TITLE, "No benchmark spot parameters in memory");
return;
}
imp = CreateData.getImage();
if (imp == null) {
IJ.error(TITLE, "No benchmark image");
return;
}
results = CreateData.getResults();
if (results == null) {
IJ.error(TITLE, "No benchmark results in memory");
return;
}
// Set-up for the simulation
try {
if (results.getCalibration() == null) {
throw new ConfigurationException("Require calibrated results");
}
if (results.getCalibrationReader().getDistanceUnit() != DistanceUnit.PIXEL) {
throw new ConfigurationException("Require results in pixel distance units");
}
if (results.getCalibrationReader().getIntensityUnit() != IntensityUnit.PHOTON) {
throw new ConfigurationException("Require results in photon units");
}
// This plugin is heavily reliant on the results being represented as a
// Gaussian2D function.
final int flags = Gaussian2DPeakResultHelper.AMPLITUDE | Gaussian2DPeakResultHelper.PIXEL_AMPLITUDE;
calculator = Gaussian2DPeakResultHelper.create(results.getPsf(), results.getCalibration(), flags);
cameraModel = CreateData.getCameraModel(simulationParameters);
} catch (final ConfigurationException ex) {
IJ.error(TITLE, "Bad configuration: " + ex.getMessage());
return;
}
if (!showDialog()) {
return;
}
// Get the simulation results into a list per frame
simulationCoords = getSimulationCoordinates();
// Clear old results to free memory
BenchmarkSpotFilterResult localFilterResult;
filterResult.set(null);
// For graphs
windowOrganiser = new WindowOrganiser();
if (batchMode) {
// Clear the cached results if the setting changed
final SettingsList settingList = new SettingsList(simulationParameters.id, settings.filterRelativeDistances, // search, maxSearch, // Ignore search distance for smart caching
settings.border, settings.scoreRelativeDistances, settings.analysisBorder, settings.hardBorder, settings.matchingMethod, settings.upperDistance, settings.lowerDistance, settings.upperSignalFactor, settings.lowerSignalFactor, settings.recallFraction);
final ArrayList<BatchResult[]> cachedResults = getCachedBatchResults(settingList);
// Batch mode to test enumeration of filters
final double sd = simulationParameters.sd / simulationParameters.pixelPitch;
final int limit = (int) Math.floor(3 * sd);
// This should be in integers otherwise we may repeat search box sizes
final int[] searchParam = SimpleArrayUtils.newArray(settings.maxSearch - settings.minSearch + 1, settings.minSearch, 1);
// Continuous parameters
final double[] pEmpty = new double[0];
final double[] mParam = (settings.batchMean) ? getRange(limit, 0.05) : pEmpty;
final double[] gParam = (settings.batchGaussian) ? getRange(limit, 0.05) : pEmpty;
// Less continuous parameters
final double[] cParam = (settings.batchCircular) ? getRange(limit, 0.5) : pEmpty;
// Discrete parameters
final double[] medParam = (settings.batchMedian) ? getRange(limit, 1) : pEmpty;
setupProgress((long) imp.getImageStackSize() * searchParam.length * (mParam.length + gParam.length + cParam.length + medParam.length), "Frame");
ArrayList<BatchResult[]> batchResults = new ArrayList<>(cachedResults.size());
double param2 = 0;
if (settings.differenceFilter && settings.differenceSmooth > 0) {
if (settings.filterRelativeDistances) {
// Convert to absolute for batch run
param2 = MathUtils.roundUsingDecimalPlaces(settings.differenceSmooth * config.getHwhmMin(), 3);
} else {
// Already an absolute value
param2 = settings.differenceSmooth;
}
config.setDataFilterType(DataFilterType.DIFFERENCE);
} else {
config.setDataFilterType(DataFilterType.SINGLE);
}
for (final int search : searchParam) {
// Batch runs use absolute distance
config.setSearch(search, true);
// Allow re-use of these if they are cached to allow quick reanalysis of results.
if (settings.batchMean) {
batchResults.add(getOrCompute(cachedResults, DataFilterMethod.MEAN, mParam, search, param2));
}
if (settings.batchGaussian) {
batchResults.add(getOrCompute(cachedResults, DataFilterMethod.GAUSSIAN, gParam, search, param2));
}
if (settings.batchCircular) {
batchResults.add(getOrCompute(cachedResults, DataFilterMethod.CIRCULAR_MEAN, cParam, search, param2));
}
if (settings.batchMean) {
batchResults.add(getOrCompute(cachedResults, DataFilterMethod.MEDIAN, medParam, search, param2));
}
}
IJ.showProgress(-1);
IJ.showStatus("");
if (ImageJUtils.isInterrupted()) {
return;
}
// Save the results in a cache
setCachedBatchResults(settingList, cachedResults);
// Analysis options
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
final boolean haveCached = cachedResults.size() > batchResults.size();
if (haveCached) {
gd.addCheckbox("Use_cached_results", settings.useCached);
}
gd.addMessage("Choose performance plots:");
for (int i = 0; i < settings.batchPlot.length; i++) {
gd.addCheckbox(Settings.batchPlotNames[i], settings.batchPlot[i]);
}
gd.addChoice("Selection", Settings.SELECTION_METHOD, settings.selectionMethod);
gd.addCheckbox("Show_plots", settings.showPlot);
gd.addCheckbox("Plot_rank_by_intensity", settings.rankByIntensity);
gd.addCheckbox("Show_failures_plots", settings.showFailuresPlot);
gd.addCheckbox("Show_TP", settings.showTP);
gd.addCheckbox("Show_FP", settings.showFP);
gd.addCheckbox("Show_FN", settings.showFN);
gd.addHelp(HelpUrls.getUrl("filter-spot-data-batch"));
gd.showDialog();
if (gd.wasCanceled()) {
return;
}
if (haveCached) {
settings.useCached = gd.getNextBoolean();
if (settings.useCached) {
batchResults = cachedResults;
}
}
for (int i = 0; i < settings.batchPlot.length; i++) {
settings.batchPlot[i] = gd.getNextBoolean();
}
settings.selectionMethod = gd.getNextChoiceIndex();
settings.showPlot = gd.getNextBoolean();
settings.rankByIntensity = gd.getNextBoolean();
settings.showFailuresPlot = gd.getNextBoolean();
settings.showTP = gd.getNextBoolean();
settings.showFP = gd.getNextBoolean();
settings.showFN = gd.getNextBoolean();
// Plot charts
for (int i = 0; i < settings.batchPlot.length; i++) {
plot(i, batchResults);
}
// Store in global singleton
localFilterResult = analyse(batchResults);
} else {
// Single filter mode
setupProgress(imp.getImageStackSize(), "Frame");
localFilterResult = runAnalysis(config);
}
ImageJUtils.clearSlowProgress();
IJ.showStatus("");
if (localFilterResult == null) {
return;
}
// Store the latest result
filterResult.set(localFilterResult);
// Debugging the matches
if (settings.debug) {
addSpotsToMemory(localFilterResult.filterResults);
}
if (settings.showFailuresPlot) {
showFailuresPlot(localFilterResult);
}
if (settings.showPlot) {
showPlot(localFilterResult);
}
if (isShowOverlay()) {
showOverlay(imp, localFilterResult);
}
windowOrganiser.tile();
}
use of uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog in project GDSC-SMLM by aherbert.
the class CreateData method showSimulationParametersDialog.
private SimulationParameters showSimulationParametersDialog(ImagePlus imp, MemoryPeakResults results) {
final int molecules = results.size();
// Get the missing parameters from the user
boolean fullSimulation = false;
double sd = -1;
if (!results.convertToPreferredUnits()) {
IJ.error(TITLE, String.format("Results should be in the preferred units (%s,%s)", UnitHelper.getName(MemoryPeakResults.PREFERRED_DISTANCE_UNIT), UnitHelper.getName(MemoryPeakResults.PREFERRED_INTENSITY_UNIT)));
return null;
}
// Get these from the data
final RawResultProcedure sp = new RawResultProcedure(results);
sp.getBixyz();
final float[] signal = sp.intensity;
float[] limits = MathUtils.limits(signal);
final double minSignal = limits[0];
final double maxSignal = limits[1];
final double signalPerFrame = MathUtils.sum(signal) / molecules;
final float[] depths = sp.z;
limits = MathUtils.limits(depths);
float depth = Math.max(Math.abs(limits[0]), Math.abs(limits[1]));
final boolean fixedDepth = Double.compare(limits[0], limits[1]) == 0;
final CalibrationWriter cal = results.getCalibrationWriter();
final String iUnits = " " + UnitHelper.getName(cal.getIntensityUnit());
final String zUnits = " " + UnitHelper.getName(cal.getDistanceUnit());
// Get this from the user
double background = -1;
// Use last simulation parameters for missing settings.
// This is good if we are re-running the plugin to load data.
Rectangle lastCameraBounds = null;
if (simulationParameters != null && simulationParameters.isLoaded()) {
fullSimulation = simulationParameters.fullSimulation;
sd = simulationParameters.sd;
background = simulationParameters.background;
if (!cal.hasBias()) {
cal.setBias(simulationParameters.bias);
}
if (!cal.hasCountPerPhoton()) {
cal.setCountPerPhoton(simulationParameters.gain);
}
if (!cal.hasQuantumEfficiency()) {
cal.setQuantumEfficiency(simulationParameters.qe);
}
if (!cal.hasReadNoise()) {
cal.setReadNoise(simulationParameters.readNoise);
}
if (!cal.hasCameraType()) {
cal.setCameraType(simulationParameters.cameraType);
}
if (!cal.hasNmPerPixel()) {
cal.setNmPerPixel(simulationParameters.pixelPitch);
}
if (!cal.hasCameraModelName()) {
cal.setCameraModelName(simulationParameters.cameraModelName);
}
lastCameraBounds = simulationParameters.cameraBounds;
}
// Show a dialog to confirm settings
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
final StringBuilder sb = new StringBuilder();
sb.append("Results contain ").append(TextUtils.pleural(molecules, "molecule")).append('\n');
sb.append("Min signal = ").append(MathUtils.rounded(minSignal)).append(iUnits).append('\n');
sb.append("Max signal = ").append(MathUtils.rounded(maxSignal)).append(iUnits).append('\n');
sb.append("Av signal = ").append(MathUtils.rounded(signalPerFrame)).append(iUnits).append('\n');
if (fixedDepth) {
sb.append("Fixed depth = ").append(MathUtils.rounded(depth)).append(zUnits).append('\n');
}
gd.addMessage(sb.toString());
gd.addCheckbox("Flourophore_simulation", fullSimulation);
gd.addNumericField("Gaussian_SD", sd, 3, 8, "nm");
gd.addNumericField("Pixel_pitch", cal.getNmPerPixel(), 3, 8, "nm");
gd.addNumericField("Background", background, 3, 8, "photon");
// Camera type does not need the full simulation settings. Plus the units are different
// so just re-implement.
gd.addChoice("Camera_type", SettingsManager.getCameraTypeNames(), CalibrationProtosHelper.getName(cal.getCameraType()), new OptionListener<Integer>() {
@Override
public boolean collectOptions(Integer field) {
cal.setCameraType(SettingsManager.getCameraTypeValues()[field]);
return collectOptions(false);
}
@Override
public boolean collectOptions() {
return collectOptions(true);
}
private boolean collectOptions(boolean silent) {
final CameraType cameraType = cal.getCameraType();
final boolean isCcd = CalibrationProtosHelper.isCcdCameraType(cameraType);
final ExtendedGenericDialog egd = new ExtendedGenericDialog(TITLE, null);
if (isCcd) {
egd.addNumericField("Total_gain", cal.getCountPerPhoton(), 3, 8, "count/photon");
egd.addNumericField("Quantum_efficiency", cal.getQuantumEfficiency(), 3, 8, "e-/photon");
egd.addNumericField("Read_noise", cal.getReadNoise(), 3, 8, "count");
egd.addNumericField("Bias", cal.getBias(), 3, 8, "count");
} else if (cameraType == CameraType.SCMOS) {
final String[] models = CameraModelManager.listCameraModels(true);
egd.addChoice("Camera_model_name", models, cal.getCameraModelName());
egd.addNumericField("Quantum_efficiency", cal.getQuantumEfficiency(), 2, 6, "electron/photon");
} else {
IJ.error("Unsupported camera type " + CalibrationProtosHelper.getName(cameraType));
return false;
}
egd.setSilent(silent);
egd.showDialog(true, gd);
if (egd.wasCanceled()) {
return false;
}
if (isCcd) {
cal.setCountPerPhoton(egd.getNextNumber());
cal.setQuantumEfficiency(egd.getNextNumber());
cal.setReadNoise(egd.getNextNumber());
cal.setBias(egd.getNextNumber());
} else if (cameraType == CameraType.SCMOS) {
cal.setCameraModelName(egd.getNextChoice());
cal.setQuantumEfficiency(Math.abs(egd.getNextNumber()));
}
return true;
}
});
if (!fixedDepth) {
gd.addNumericField("Depth", depth, 3, 8, "pixel");
}
gd.addHelp(HelpUrls.getUrl("load-benchmark-data"));
gd.showDialog();
if (gd.wasCanceled()) {
return null;
}
fullSimulation = gd.getNextBoolean();
sd = gd.getNextNumber();
cal.setNmPerPixel(gd.getNextNumber());
background = gd.getNextNumber();
cal.setCameraType(SettingsManager.getCameraTypeValues()[gd.getNextChoiceIndex()]);
float myDepth = depth;
if (!fixedDepth) {
myDepth = (float) gd.getNextNumber();
if (myDepth < depth) {
IJ.error(TITLE, String.format("Input depth is smaller than the depth guessed from the data: %f < %f", myDepth, depth));
return null;
}
depth = myDepth;
}
gd.collectOptions();
// Validate settings
Rectangle modelBounds = null;
try {
ParameterUtils.isAboveZero("Gaussian SD", sd);
ParameterUtils.isAboveZero("Pixel pitch", cal.getNmPerPixel());
ParameterUtils.isPositive("Background", background);
ParameterUtils.isAboveZero("Quantum efficiency", cal.getQuantumEfficiency());
ParameterUtils.isEqualOrBelow("Quantum efficiency", cal.getQuantumEfficiency(), 1);
if (cal.isCcdCamera()) {
ParameterUtils.isAboveZero("Total gain", cal.getCountPerPhoton());
ParameterUtils.isPositive("Read noise", cal.getReadNoise());
ParameterUtils.isPositive("Bias", cal.getBias());
} else if (cal.isScmos()) {
// Load the model
cameraModel = CameraModelManager.load(cal.getCameraModelName());
if (cameraModel == null) {
IJ.error(TITLE, "Unknown camera model for name: " + cal.getCameraModelName());
return null;
}
int ox = 0;
int oy = 0;
if (lastCameraBounds != null) {
ox = lastCameraBounds.x;
oy = lastCameraBounds.y;
}
cameraModel = PeakFit.cropCameraModel(cameraModel, new Rectangle(ox, oy, imp.getWidth(), imp.getHeight()), null, false);
modelBounds = cameraModel.getBounds();
final IJImageSource imageSource = (IJImageSource) results.getSource();
imageSource.setOrigin(modelBounds.x, modelBounds.y);
cal.clearGlobalCameraSettings();
} else {
IJ.error(TITLE, "Unknown camera type: " + cal.getCameraType());
return null;
}
} catch (final IllegalArgumentException ex) {
IJ.error(TITLE, ex.getMessage());
return null;
}
// Store calibration
results.setCalibration(cal.getCalibration());
final double a = cal.getNmPerPixel();
final double bias = cal.getBias();
final double gain = cal.getCountPerPhoton();
final double readNoise = cal.getReadNoise();
final double qe = cal.getQuantumEfficiency();
// Note: The calibration will throw an exception if the converter cannot be created.
// This is OK as the data will be invalid.
// Convert +/- depth to total depth in nm
depth = cal.getDistanceConverter(DistanceUnit.NM).convert(depth * 2);
// Compute total background variance in photons
final double backgroundVariance = background;
// Do not add EM-CCD noise factor. The Mortensen formula also includes this factor
// so this is "double-counting" the EM-CCD.
// if (emCCD)
// backgroundVariance *= 2;
// Read noise is in ADUs. Convert to Photons to get contribution to background variance
final double readNoiseInPhotons = readNoise / gain;
// Get the expected value at each pixel in photons. Assuming a Poisson distribution this
// is equal to the total variance at the pixel.
final double b2 = backgroundVariance + readNoiseInPhotons * readNoiseInPhotons;
// Convert values to photons
final TypeConverter<IntensityUnit> ic = cal.getIntensityConverter(IntensityUnit.PHOTON);
final SimulationParameters p = new SimulationParameters(molecules, fullSimulation, sd, a, ic.convert(minSignal), ic.convert(maxSignal), ic.convert(signalPerFrame), depth, fixedDepth, bias, gain, qe, readNoise, cal.getCameraType(), cal.getCameraModelName(), modelBounds, background, b2, createPsf(sd / a));
p.loaded = true;
return p;
}
Aggregations