use of uk.ac.sussex.gdsc.smlm.data.config.FitProtos.FitSolver in project GDSC-SMLM by aherbert.
the class PeakFit method configureFitSolver.
/**
* Show a dialog to configure the fit solver. The updated settings are saved to the settings file.
* An error message is shown if the dialog is cancelled or the configuration is invalid.
*
* <p>The bounds are used to validate the camera model. The camera model must be large enough to
* cover the source bounds. If larger then it will be cropped. Optionally an internal region of
* the input image can be specified. This is relative to the width and height of the input image.
* If no camera model is present then the bounds can be null.
*
* @param config the configuration
* @param sourceBounds the source image bounds (used to validate the camera model dimensions)
* @param bounds the crop bounds (relative to the input image, used to validate the camera model
* dimensions)
* @param flags the flags
* @return True if the configuration succeeded
*/
public static boolean configureFitSolver(FitEngineConfiguration config, Rectangle sourceBounds, Rectangle bounds, int flags) {
final boolean extraOptions = BitFlagUtils.anySet(flags, FLAG_EXTRA_OPTIONS);
final boolean ignoreCalibration = BitFlagUtils.anySet(flags, FLAG_IGNORE_CALIBRATION);
final boolean saveSettings = BitFlagUtils.anyNotSet(flags, FLAG_NO_SAVE);
final FitConfiguration fitConfig = config.getFitConfiguration();
final CalibrationWriter calibration = fitConfig.getCalibrationWriter();
final FitSolver fitSolver = fitConfig.getFitSolver();
final boolean isLvm = fitSolver == FitSolver.LVM_LSE || fitSolver == FitSolver.LVM_WLSE || fitSolver == FitSolver.LVM_MLE;
// Support the deprecated backtracking FastMLE solver as a plain FastMLE solver
final boolean isFastMml = fitSolver == FitSolver.FAST_MLE || fitSolver == FitSolver.BACKTRACKING_FAST_MLE;
final boolean isSteppingFunctionSolver = isLvm || isFastMml;
if (fitSolver == FitSolver.MLE) {
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
if (!ignoreCalibration) {
gd.addMessage("Maximum Likelihood Estimation requires CCD-type camera parameters");
gd.addNumericField("Camera_bias", calibration.getBias(), 2, 6, "count");
gd.addCheckbox("Model_camera_noise", fitConfig.isModelCamera());
gd.addNumericField("Read_noise", calibration.getReadNoise(), 2, 6, "count");
gd.addNumericField("Quantum_efficiency", calibration.getQuantumEfficiency(), 2, 6, "electron/photon");
gd.addCheckbox("EM-CCD", calibration.isEmCcd());
} else {
gd.addMessage("Maximum Likelihood Estimation requires additional parameters");
}
final String[] searchNames = SettingsManager.getSearchMethodNames();
gd.addChoice("Search_method", searchNames, FitProtosHelper.getName(fitConfig.getSearchMethod()));
gd.addStringField("Relative_threshold", MathUtils.rounded(fitConfig.getRelativeThreshold()));
gd.addStringField("Absolute_threshold", MathUtils.rounded(fitConfig.getAbsoluteThreshold()));
gd.addNumericField("Max_iterations", fitConfig.getMaxIterations(), 0);
gd.addNumericField("Max_function_evaluations", fitConfig.getMaxFunctionEvaluations(), 0);
if (extraOptions) {
gd.addCheckbox("Gradient_line_minimisation", fitConfig.isGradientLineMinimisation());
}
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
if (!ignoreCalibration) {
calibration.setBias(Math.abs(gd.getNextNumber()));
fitConfig.setModelCamera(gd.getNextBoolean());
calibration.setReadNoise(Math.abs(gd.getNextNumber()));
calibration.setQuantumEfficiency(Math.abs(gd.getNextNumber()));
calibration.setCameraType((gd.getNextBoolean()) ? CameraType.EMCCD : CameraType.CCD);
fitConfig.setCalibration(calibration.getCalibration());
}
fitConfig.setSearchMethod(SettingsManager.getSearchMethodValues()[gd.getNextChoiceIndex()]);
fitConfig.setRelativeThreshold(getThresholdNumber(gd));
fitConfig.setAbsoluteThreshold(getThresholdNumber(gd));
fitConfig.setMaxIterations((int) gd.getNextNumber());
fitConfig.setMaxFunctionEvaluations((int) gd.getNextNumber());
if (extraOptions) {
fitConfig.setGradientLineMinimisation(gd.getNextBoolean());
} else {
// This option is for the Conjugate Gradient optimiser and makes it less stable
fitConfig.setGradientLineMinimisation(false);
}
if (saveSettings) {
saveFitEngineSettings(config);
}
try {
ParameterUtils.isAboveZero("Relative threshold", fitConfig.getRelativeThreshold());
ParameterUtils.isAboveZero("Absolute threshold", fitConfig.getAbsoluteThreshold());
ParameterUtils.isAboveZero("Max iterations", fitConfig.getMaxIterations());
ParameterUtils.isAboveZero("Max function evaluations", fitConfig.getMaxFunctionEvaluations());
fitConfig.getFunctionSolver();
} catch (final IllegalArgumentException | IllegalStateException ex) {
IJ.error(TITLE, ex.getMessage());
return false;
}
} else if (isSteppingFunctionSolver) {
final boolean requireCalibration = !ignoreCalibration && fitSolver != FitSolver.LVM_LSE;
// Collect options for LVM fitting
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
final String fitSolverName = FitProtosHelper.getName(fitSolver);
gd.addMessage(fitSolverName + " requires additional parameters");
gd.addStringField("Relative_threshold", MathUtils.rounded(fitConfig.getRelativeThreshold()));
gd.addStringField("Absolute_threshold", MathUtils.rounded(fitConfig.getAbsoluteThreshold()));
gd.addStringField("Parameter_relative_threshold", MathUtils.rounded(fitConfig.getParameterRelativeThreshold()));
gd.addStringField("Parameter_absolute_threshold", MathUtils.rounded(fitConfig.getParameterAbsoluteThreshold()));
gd.addNumericField("Max_iterations", fitConfig.getMaxIterations(), 0);
if (isLvm) {
gd.addNumericField("Lambda", fitConfig.getLambda(), 4);
}
if (isFastMml) {
gd.addCheckbox("Fixed_iterations", fitConfig.isFixedIterations());
// This works because the proto configuration enum matches the named enum
final String[] lineSearchNames = SettingsManager.getNames((Object[]) FastMleSteppingFunctionSolver.LineSearchMethod.values());
gd.addChoice("Line_search_method", lineSearchNames, lineSearchNames[fitConfig.getLineSearchMethod().getNumber()]);
}
gd.addCheckbox("Use_clamping", fitConfig.isUseClamping());
gd.addCheckbox("Dynamic_clamping", fitConfig.isUseDynamicClamping());
final PSF psf = fitConfig.getPsf();
final boolean isAstigmatism = psf.getPsfType() == PSFType.ASTIGMATIC_GAUSSIAN_2D;
final int nParams = PsfHelper.getParameterCount(psf);
if (extraOptions) {
gd.addNumericField("Clamp_background", fitConfig.getClampBackground(), 2);
gd.addNumericField("Clamp_signal", fitConfig.getClampSignal(), 2);
gd.addNumericField("Clamp_x", fitConfig.getClampX(), 2);
gd.addNumericField("Clamp_y", fitConfig.getClampY(), 2);
if (isAstigmatism) {
gd.addNumericField("Clamp_z", fitConfig.getClampZ(), 2);
} else {
if (nParams > 1 || !fitConfig.isFixedPsf()) {
gd.addNumericField("Clamp_sx", fitConfig.getClampXSd(), 2);
}
if (nParams > 1) {
gd.addNumericField("Clamp_sy", fitConfig.getClampYSd(), 2);
}
if (nParams > 2) {
gd.addNumericField("Clamp_angle", fitConfig.getClampAngle(), 2);
}
}
}
// Extra parameters are needed for calibrated fit solvers
if (requireCalibration) {
switch(calibration.getCameraType()) {
case CCD:
case EMCCD:
case SCMOS:
break;
default:
IJ.error(TITLE, fitSolverName + " requires camera calibration");
return false;
}
gd.addMessage(fitSolverName + " requires calibration for camera: " + CalibrationProtosHelper.getName(calibration.getCameraType()));
if (calibration.isScmos()) {
final String[] models = CameraModelManager.listCameraModels(true);
gd.addChoice("Camera_model_name", models, fitConfig.getCameraModelName());
} else {
gd.addNumericField("Camera_bias", calibration.getBias(), 2, 6, "Count");
gd.addNumericField("Gain", calibration.getCountPerPhoton(), 2, 6, "Count/photon");
gd.addNumericField("Read_noise", calibration.getReadNoise(), 2, 6, "Count");
}
}
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
fitConfig.setRelativeThreshold(getThresholdNumber(gd));
fitConfig.setAbsoluteThreshold(getThresholdNumber(gd));
fitConfig.setParameterRelativeThreshold(getThresholdNumber(gd));
fitConfig.setParameterAbsoluteThreshold(getThresholdNumber(gd));
fitConfig.setMaxIterations((int) gd.getNextNumber());
if (isLvm) {
fitConfig.setLambda(gd.getNextNumber());
}
if (isFastMml) {
fitConfig.setFixedIterations(gd.getNextBoolean());
fitConfig.setLineSearchMethod(gd.getNextChoiceIndex());
}
fitConfig.setUseClamping(gd.getNextBoolean());
fitConfig.setUseDynamicClamping(gd.getNextBoolean());
if (extraOptions) {
fitConfig.setClampBackground(Math.abs(gd.getNextNumber()));
fitConfig.setClampSignal(Math.abs(gd.getNextNumber()));
fitConfig.setClampX(Math.abs(gd.getNextNumber()));
fitConfig.setClampY(Math.abs(gd.getNextNumber()));
if (isAstigmatism) {
fitConfig.setClampZ(Math.abs(gd.getNextNumber()));
} else {
if (nParams > 1 || !fitConfig.isFixedPsf()) {
fitConfig.setClampXSd(Math.abs(gd.getNextNumber()));
}
if (nParams > 1) {
fitConfig.setClampYSd(Math.abs(gd.getNextNumber()));
}
if (nParams > 2) {
fitConfig.setClampAngle(Math.abs(gd.getNextNumber()));
}
}
}
if (requireCalibration) {
if (calibration.isScmos()) {
fitConfig.setCameraModelName(gd.getNextChoice());
} else {
calibration.setBias(Math.abs(gd.getNextNumber()));
calibration.setCountPerPhoton(Math.abs(gd.getNextNumber()));
calibration.setReadNoise(Math.abs(gd.getNextNumber()));
fitConfig.setCalibration(calibration.getCalibration());
}
}
// camera model is set.
if (calibration.isScmos()) {
fitConfig.setCameraModel(CameraModelManager.load(fitConfig.getCameraModelName()));
if (!checkCameraModel(fitConfig, sourceBounds, bounds, true)) {
return false;
}
}
if (saveSettings) {
saveFitEngineSettings(config);
}
try {
if (isLvm) {
ParameterUtils.isAboveZero("Lambda", fitConfig.getLambda());
}
// This call will check if the configuration is OK (including convergence criteria)
fitConfig.getFunctionSolver();
} catch (final IllegalArgumentException | IllegalStateException ex) {
IJ.error(TITLE, ex.getMessage());
return false;
}
} else {
IJ.error(TITLE, "Unknown fit solver: " + fitSolver);
return false;
}
if (config.isIncludeNeighbours() && !fitConfig.getFunctionSolver().isBounded()) {
IJ.error(TITLE, "Including neighbours requires a bounded fit solver");
return false;
}
return true;
}
use of uk.ac.sussex.gdsc.smlm.data.config.FitProtos.FitSolver in project GDSC-SMLM by aherbert.
the class PeakFit method getSolverName.
/**
* Gets the solver name.
*
* @param fitConfig the fit config
* @return the solver name
*/
public static String getSolverName(FitConfiguration fitConfig) {
final FitSolver solver = fitConfig.getFitSolver();
String name = FitProtosHelper.getName(solver);
if (solver == FitSolver.MLE) {
name += " " + FitProtosHelper.getName(fitConfig.getSearchMethod());
}
return name;
}
Aggregations