use of uk.ac.sussex.gdsc.smlm.ij.plugins.PeakFit.FitEngineConfigurationProvider 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.ij.plugins.PeakFit.FitEngineConfigurationProvider in project GDSC-SMLM by aherbert.
the class AstigmatismModelManager method showConfigurationDialog.
private boolean showConfigurationDialog() {
fitConfig = config.getFitConfiguration();
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addHelp(HelpUrls.getUrl("astigmatism-model-manager"));
gd.addMessage("Configuration settings for the single-molecule localisation microscopy plugins");
PeakFit.addCameraOptions(gd, fitConfig);
CalibrationWriter calibration = fitConfig.getCalibrationWriter();
gd.addNumericField("Calibration (nm/px)", calibration.getNmPerPixel(), 2);
// gd.addNumericField("Exposure_time (ms)", calibration.getExposureTime(), 2);
PeakFit.addPsfOptions(gd, fitConfig);
final FitEngineConfigurationProvider provider = new PeakFit.SimpleFitEngineConfigurationProvider(config);
PeakFit.addFittingOptions(gd, provider);
gd.addChoice("Fit_solver", SettingsManager.getFitSolverNames(), FitProtosHelper.getName(fitConfig.getFitSolver()));
gd.addCheckbox("Log_fit_progress", pluginSettings.getLogFitProgress());
gd.addMessage("--- Peak filtering ---\nDiscard fits that shift; are too low; or expand/contract");
gd.addCheckbox("Smart_filter", fitConfig.isSmartFilter());
gd.addCheckbox("Disable_simple_filter", fitConfig.isDisableSimpleFilter());
gd.addSlider("Shift_factor", 0.01, 2, fitConfig.getCoordinateShiftFactor());
gd.addNumericField("Signal_strength", fitConfig.getSignalStrength(), 2);
gd.addNumericField("Min_photons", fitConfig.getMinPhotons(), 0);
gd.addSlider("Min_width_factor", 0, 0.99, fitConfig.getMinWidthFactor());
// Fitting may need to be extra wide
final double w = fitConfig.getMaxWidthFactor();
gd.addSlider("Width_factor", 1.01, Math.max(10, w), w);
PeakFit.addPrecisionOptions(gd, new PeakFit.SimpleFitConfigurationProvider(fitConfig));
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
// In case a template update the calibration
calibration = fitConfig.getCalibrationWriter();
calibration.setCameraType(SettingsManager.getCameraTypeValues()[gd.getNextChoiceIndex()]);
calibration.setNmPerPixel(gd.getNextNumber());
// Arbitrary
calibration.setExposureTime(100);
fitConfig.setCalibration(calibration.getCalibration());
fitConfig.setPsfType(PeakFit.getPsfTypeValues()[gd.getNextChoiceIndex()]);
config.setFitting(gd.getNextNumber());
// Some enum values are not supported
fitConfig.setFitSolver(SettingsManager.getFitSolverValues()[gd.getNextChoiceIndex()]);
pluginSettings.setLogFitProgress(gd.getNextBoolean());
fitConfig.setSmartFilter(gd.getNextBoolean());
fitConfig.setDisableSimpleFilter(gd.getNextBoolean());
fitConfig.setCoordinateShiftFactor(gd.getNextNumber());
fitConfig.setSignalStrength(gd.getNextNumber());
fitConfig.setMinPhotons(gd.getNextNumber());
fitConfig.setMinWidthFactor(gd.getNextNumber());
fitConfig.setMaxWidthFactor(gd.getNextNumber());
fitConfig.setPrecisionThreshold(gd.getNextNumber());
gd.collectOptions();
// Check arguments
try {
ParameterUtils.isAboveZero("nm per pixel", calibration.getNmPerPixel());
ParameterUtils.isAboveZero("Initial SD0", fitConfig.getInitialXSd());
if (fitConfig.getPsf().getParametersCount() > 1) {
ParameterUtils.isAboveZero("Initial SD1", fitConfig.getInitialYSd());
}
ParameterUtils.isAboveZero("Fitting_width", config.getFitting());
if (!fitConfig.isSmartFilter()) {
ParameterUtils.isPositive("Coordinate Shift factor", fitConfig.getCoordinateShiftFactor());
ParameterUtils.isPositive("Signal strength", fitConfig.getSignalStrength());
ParameterUtils.isPositive("Min photons", fitConfig.getMinPhotons());
ParameterUtils.isPositive("Min width factor", fitConfig.getMinWidthFactor());
ParameterUtils.isPositive("Width factor", fitConfig.getMaxWidthFactor());
ParameterUtils.isPositive("Precision threshold", fitConfig.getPrecisionThreshold());
}
} catch (final IllegalArgumentException ex) {
IJ.error(TITLE, ex.getMessage());
return false;
}
if (gd.invalidNumber()) {
return false;
}
final int flags = PeakFit.FLAG_NO_SAVE;
if (!PeakFit.configureSmartFilter(config, flags)) {
return false;
}
PeakFit.configureFitSolver(config, null, null, flags);
return true;
}
use of uk.ac.sussex.gdsc.smlm.ij.plugins.PeakFit.FitEngineConfigurationProvider in project GDSC-SMLM by aherbert.
the class Configuration method showDialog.
/**
* Show the current properties.
*
* @param fitEngineConfiguration the fit engine configuration
* @param save the save
* @return true, if successful
*/
public boolean showDialog(FitEngineConfiguration fitEngineConfiguration, boolean save) {
this.config = fitEngineConfiguration;
fitConfig = config.getFitConfiguration();
pluginSettings = Settings.load();
pluginSettings.save();
final CalibrationReader calibrationReader = fitConfig.getCalibrationReader();
ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addHelp(HelpUrls.getUrl("fit-configuration"));
gd.addMessage("Configuration settings for the single-molecule localisation microscopy plugins");
final String[] templates = ConfigurationTemplate.getTemplateNames(true);
gd.addChoice("Template", templates, templates[0]);
PeakFit.addCameraOptions(gd, fitConfig);
gd.addNumericField("Calibration (nm/px)", calibrationReader.getNmPerPixel(), 2);
gd.addNumericField("Exposure_time (ms)", calibrationReader.getExposureTime(), 2);
gd.addMessage("--- Gaussian parameters ---");
PeakFit.addPsfOptions(gd, fitConfig);
gd.addMessage("--- Maxima identification ---");
final FitEngineConfigurationProvider provider = this::getFitEngineConfiguration;
PeakFit.addDataFilterOptions(gd, provider);
PeakFit.addSearchOptions(gd, provider);
PeakFit.addBorderOptions(gd, provider);
PeakFit.addFittingOptions(gd, provider);
gd.addMessage("--- Gaussian fitting ---");
gd.addChoice("Fit_solver", SettingsManager.getFitSolverNames(), FitProtosHelper.getName(fitConfig.getFitSolver()));
// Parameters specific to each Fit solver are collected in a second dialog
gd.addNumericField("Fail_limit", config.getFailuresLimit(), 0);
gd.addNumericField("Pass_rate", config.getPassRate(), 2);
gd.addCheckbox("Include_neighbours", config.isIncludeNeighbours());
gd.addSlider("Neighbour_height", 0.01, 1, config.getNeighbourHeightThreshold());
gd.addSlider("Residuals_threshold", 0.01, 1, config.getResidualsThreshold());
PeakFit.addDuplicateDistanceOptions(gd, provider);
gd.addMessage("--- Peak filtering ---\nDiscard fits that shift; are too low; or expand/contract");
gd.addCheckbox("Smart_filter", fitConfig.isSmartFilter());
gd.addCheckbox("Disable_simple_filter", fitConfig.isDisableSimpleFilter());
gd.addSlider("Shift_factor", 0.01, 2, fitConfig.getCoordinateShiftFactor());
gd.addNumericField("Signal_strength", fitConfig.getSignalStrength(), 2);
gd.addNumericField("Min_photons", fitConfig.getMinPhotons(), 0);
gd.addSlider("Min_width_factor", 0, 0.99, fitConfig.getMinWidthFactor());
gd.addSlider("Width_factor", 1, 4.5, fitConfig.getMaxWidthFactor());
PeakFit.addPrecisionOptions(gd, this::getFitConfiguration);
// Add a mouse listener to the config file field
if (ImageJUtils.isShowGenericDialog()) {
final Vector<TextField> numerics = gd.getNumericFields();
final Vector<Checkbox> checkboxes = gd.getCheckboxes();
final Vector<Choice> choices = gd.getChoices();
final Iterator<TextField> nu = numerics.iterator();
final Iterator<Checkbox> cb = checkboxes.iterator();
final Iterator<Choice> ch = choices.iterator();
final Choice textTemplate = ch.next();
textTemplate.addItemListener(this::itemStateChanged);
textCameraType = ch.next();
textNmPerPixel = nu.next();
textExposure = nu.next();
textPsf = ch.next();
textDataFilterType = ch.next();
textDataFilterMethod = ch.next();
textSmooth = nu.next();
textSearch = nu.next();
textBorder = nu.next();
textFitting = nu.next();
textFitSolver = ch.next();
textFailuresLimit = nu.next();
textPassRate = nu.next();
textIncludeNeighbours = cb.next();
textNeighbourHeightThreshold = nu.next();
textResidualsThreshold = nu.next();
textDuplicateDistance = nu.next();
textSmartFilter = cb.next();
textDisableSimpleFilter = cb.next();
textCoordinateShiftFactor = nu.next();
textSignalStrength = nu.next();
textMinPhotons = nu.next();
textMinWidthFactor = nu.next();
textWidthFactor = nu.next();
textPrecisionThreshold = nu.next();
updateFilterInput();
textSmartFilter.addItemListener(this::itemStateChanged);
textDisableSimpleFilter.addItemListener(this::itemStateChanged);
}
if (save) {
gd.enableYesNoCancel("Save", "Save template");
}
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
// In case a template updated the calibration
final CalibrationWriter calibrationWriter = fitConfig.getCalibrationWriter();
// Ignore the template
gd.getNextChoice();
calibrationWriter.setCameraType(SettingsManager.getCameraTypeValues()[gd.getNextChoiceIndex()]);
calibrationWriter.setNmPerPixel(gd.getNextNumber());
calibrationWriter.setExposureTime(gd.getNextNumber());
fitConfig.setCalibration(calibrationWriter.getCalibration());
fitConfig.setPsfType(PeakFit.getPsfTypeValues()[gd.getNextChoiceIndex()]);
config.setDataFilterType(gd.getNextChoiceIndex());
config.setDataFilter(gd.getNextChoiceIndex(), Math.abs(gd.getNextNumber()), false, 0);
config.setSearch(gd.getNextNumber());
config.setBorder(gd.getNextNumber());
config.setFitting(gd.getNextNumber());
// Some enum values are not supported
fitConfig.setFitSolver(SettingsManager.getFitSolverValues()[gd.getNextChoiceIndex()]);
config.setFailuresLimit((int) gd.getNextNumber());
config.setPassRate(gd.getNextNumber());
config.setIncludeNeighbours(gd.getNextBoolean());
config.setNeighbourHeightThreshold(gd.getNextNumber());
config.setResidualsThreshold(gd.getNextNumber());
config.setDuplicateDistance(gd.getNextNumber());
fitConfig.setSmartFilter(gd.getNextBoolean());
fitConfig.setDisableSimpleFilter(gd.getNextBoolean());
fitConfig.setCoordinateShiftFactor(gd.getNextNumber());
fitConfig.setSignalStrength(gd.getNextNumber());
fitConfig.setMinPhotons(gd.getNextNumber());
fitConfig.setMinWidthFactor(gd.getNextNumber());
fitConfig.setMaxWidthFactor(gd.getNextNumber());
fitConfig.setPrecisionThreshold(gd.getNextNumber());
gd.collectOptions();
// Check arguments
try {
ParameterUtils.isAboveZero("nm per pixel", calibrationWriter.getNmPerPixel());
ParameterUtils.isAboveZero("Exposure time", calibrationWriter.getExposureTime());
if (fitConfig.getPsfTypeValue() != PSFType.ASTIGMATIC_GAUSSIAN_2D_VALUE) {
ParameterUtils.isAboveZero("Initial SD0", fitConfig.getInitialXSd());
if (fitConfig.getPsf().getParametersCount() > 1) {
ParameterUtils.isAboveZero("Initial SD1", fitConfig.getInitialYSd());
}
}
ParameterUtils.isAboveZero("Search_width", config.getSearch());
ParameterUtils.isAboveZero("Fitting_width", config.getFitting());
ParameterUtils.isPositive("Neighbour height threshold", config.getNeighbourHeightThreshold());
ParameterUtils.isPositive("Residuals threshold", config.getResidualsThreshold());
ParameterUtils.isPositive("Duplicate distance", config.getDuplicateDistance());
if (!fitConfig.isSmartFilter()) {
ParameterUtils.isPositive("Coordinate Shift factor", fitConfig.getCoordinateShiftFactor());
ParameterUtils.isPositive("Signal strength", fitConfig.getSignalStrength());
ParameterUtils.isPositive("Min photons", fitConfig.getMinPhotons());
ParameterUtils.isPositive("Min width factor", fitConfig.getMinWidthFactor());
ParameterUtils.isPositive("Width factor", fitConfig.getMaxWidthFactor());
ParameterUtils.isPositive("Precision threshold", fitConfig.getPrecisionThreshold());
}
} catch (final IllegalArgumentException ex) {
IJ.error(TITLE, ex.getMessage());
return false;
}
if (gd.invalidNumber()) {
return false;
}
final int flags = PeakFit.FLAG_NO_SAVE;
if (!PeakFit.configurePsfModel(config, flags)) {
return false;
}
if (!PeakFit.configureResultsFilter(config, flags)) {
return false;
}
if (!PeakFit.configureDataFilter(config, flags)) {
return false;
}
PeakFit.configureFitSolver(config, null, null, flags);
if (save) {
final boolean saveToFile = !gd.wasOKed();
if (saveToFile) {
gd = new ExtendedGenericDialog(TITLE);
gd.addFilenameField("Template_filename", pluginSettings.templateFilename);
gd.addMessage("Add notes to the template ...");
gd.addTextAreas(pluginSettings.notes, null, 10, 60);
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
pluginSettings.save();
final String filename = gd.getNextString();
pluginSettings.notes = gd.getNextText();
if (filename != null) {
pluginSettings.templateFilename = FileUtils.replaceExtension(filename, ".txt");
final File file = new File(pluginSettings.templateFilename);
final String name = FileUtils.removeExtension(file.getName());
final TemplateSettings.Builder settings = TemplateSettings.newBuilder();
settings.addNotes(pluginSettings.notes);
settings.setCalibration(fitConfig.getCalibration());
settings.setFitEngineSettings(config.getFitEngineSettings());
// Note: No results settings are currently supported
settings.setPsf(fitConfig.getPsf());
if (!ConfigurationTemplate.saveTemplate(name, settings.build(), file)) {
IJ.error(TITLE, "Failed to save to file: " + pluginSettings.templateFilename);
}
}
} else {
SettingsManager.writeSettings(config, 0);
}
}
return true;
}
Aggregations