use of uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter 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;
}
use of uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter in project GDSC-SMLM by aherbert.
the class ConvertResults method showDialog.
private static boolean showDialog(MemoryPeakResults results) {
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addMessage("Convert the current units for the results");
gd.addHelp(HelpUrls.getUrl("convert-results"));
final CalibrationReader cr = CalibrationWriter.create(results.getCalibration());
gd.addChoice("Distance_unit", SettingsManager.getDistanceUnitNames(), cr.getDistanceUnitValue());
gd.addNumericField("Calibration (nm/px)", cr.getNmPerPixel(), 2);
gd.addChoice("Intensity_unit", SettingsManager.getIntensityUnitNames(), cr.getIntensityUnitValue());
gd.addNumericField("Gain (Count/photon)", cr.getCountPerPhoton(), 2);
gd.addChoice("Angle_unit", SettingsManager.getAngleUnitNames(), cr.getAngleUnitValue());
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
final CalibrationWriter cw = results.getCalibrationWriterSafe();
final DistanceUnit distanceUnit = SettingsManager.getDistanceUnitValues()[gd.getNextChoiceIndex()];
cw.setNmPerPixel(Math.abs(gd.getNextNumber()));
final IntensityUnit intensityUnit = SettingsManager.getIntensityUnitValues()[gd.getNextChoiceIndex()];
cw.setCountPerPhoton(Math.abs(gd.getNextNumber()));
final AngleUnit angleUnit = SettingsManager.getAngleUnitValues()[gd.getNextChoiceIndex()];
// Don't set the calibration with bad values
if (distanceUnit.getNumber() > 0 && !(cw.getNmPerPixel() > 0)) {
IJ.error(TITLE, "Require positive nm/pixel for conversion");
return false;
}
if (intensityUnit.getNumber() > 0 && !(cw.getCountPerPhoton() > 0)) {
IJ.error(TITLE, "Require positive Count/photon for conversion");
return false;
}
final Calibration newCalibration = cw.getCalibration();
results.setCalibration(newCalibration);
if (!results.convertToUnits(distanceUnit, intensityUnit, angleUnit)) {
IJ.error(TITLE, "Conversion failed");
return false;
}
return true;
}
use of uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter in project GDSC-SMLM by aherbert.
the class CalibrateResults method showDialog.
private boolean showDialog(MemoryPeakResults results) {
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addHelp(HelpUrls.getUrl("calibrate-results"));
final Calibration oldCalibration = results.getCalibration();
final boolean existingCalibration = oldCalibration != null;
if (!existingCalibration) {
gd.addMessage("No calibration found, using defaults");
}
final CalibrationWriter cw = results.getCalibrationWriterSafe();
gd.addStringField("Name", results.getName(), Math.max(Math.min(results.getName().length(), 60), 20));
if (existingCalibration) {
gd.addCheckbox("Update_all_linked_results", settings.updateAll);
}
PeakFit.addCameraOptions(gd, PeakFit.FLAG_QUANTUM_EFFICIENCY, cw);
gd.addNumericField("Calibration (nm/px)", cw.getNmPerPixel(), 2);
gd.addNumericField("Exposure_time (ms)", cw.getExposureTime(), 2);
gd.showDialog();
if (gd.wasCanceled()) {
return false;
}
final String name = gd.getNextString();
if (!results.getName().equals(name)) {
// If the name is changed then remove and add back to memory
final MemoryPeakResults existingResults = MemoryPeakResults.removeResults(results.getName());
if (existingResults != null) {
results = existingResults;
results.setName(name);
MemoryPeakResults.addResults(results);
}
}
if (existingCalibration) {
settings.updateAll = gd.getNextBoolean();
}
cw.setCameraType(SettingsManager.getCameraTypeValues()[gd.getNextChoiceIndex()]);
cw.setNmPerPixel(Math.abs(gd.getNextNumber()));
cw.setExposureTime(Math.abs(gd.getNextNumber()));
gd.collectOptions();
final Calibration newCalibration = cw.getCalibration();
results.setCalibration(newCalibration);
if (settings.updateAll) {
// be missed.
for (final MemoryPeakResults r : MemoryPeakResults.getAllResults()) {
if (r.getCalibration() == oldCalibration) {
r.setCalibration(newCalibration);
}
}
}
return true;
}
use of uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter in project GDSC-SMLM by aherbert.
the class AstigmatismModelManager method guessScale.
private void guessScale() {
final CalibrationWriter cw = CalibrationWriter.create(pluginSettings.getCalibration());
// It does not matter if we already have settings, try and update them anyway
final Calibration cal = imp.getCalibration();
double scale = guessScale(cal.getXUnit(), cal.pixelWidth);
if (scale != 0) {
cw.setNmPerPixel(scale);
pluginSettings.setCalibration(cw.getBuilder());
}
scale = guessScale(cal.getZUnit(), cal.pixelDepth);
if (scale != 0) {
pluginSettings.setNmPerSlice(scale);
}
}
use of uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter in project GDSC-SMLM by aherbert.
the class CreateData method drawImage.
// StoredDataStatistics rawPhotons = new StoredDataStatistics();
// StoredDataStatistics drawPhotons = new StoredDataStatistics();
// private synchronized void addRaw(double d)
// {
// //rawPhotons.add(d);
// }
//
// private synchronized void addDraw(double d)
// {
// //drawPhotons.add(d);
// }
/**
* Create an image from the localisations using the configured PSF width. Draws a new stack image.
*
* <p>Note that the localisations are filtered using the signal. The input list of localisations
* will be updated.
*
* @param localisationSets the localisation sets
* @return The localisations
*/
private List<LocalisationModel> drawImage(final List<LocalisationModelSet> localisationSets) {
if (localisationSets.isEmpty()) {
return null;
}
// Create a new list for all localisation that are drawn (i.e. pass the signal filters)
List<LocalisationModelSet> newLocalisations = Collections.synchronizedList(new ArrayList<LocalisationModelSet>(localisationSets.size()));
photonsRemoved = new AtomicInteger();
removedT1 = new AtomicInteger();
removedTn = new AtomicInteger();
photonStats = new SummaryStatistics();
// Add drawn spots to memory
results = new MemoryPeakResults();
final CalibrationWriter c = new CalibrationWriter();
c.setDistanceUnit(DistanceUnit.PIXEL);
c.setIntensityUnit(IntensityUnit.PHOTON);
c.setNmPerPixel(settings.getPixelPitch());
c.setExposureTime(settings.getExposureTime());
c.setCameraType(settings.getCameraType());
if (settings.getCameraType() == CameraType.SCMOS) {
c.setCameraModelName(settings.getCameraModelName());
} else {
final CreateDataSettingsHelper helper = new CreateDataSettingsHelper(settings);
c.setCountPerPhoton(helper.getTotalGainSafe());
c.setBias(settings.getBias());
c.setReadNoise(helper.getReadNoiseInCounts());
c.setQuantumEfficiency(helper.getQuantumEfficiency());
}
results.setCalibration(c.getCalibration());
results.setSortAfterEnd(true);
results.begin();
maxT = localisationSets.get(localisationSets.size() - 1).getTime();
// Display image
final ImageStack stack = new ImageStack(settings.getSize(), settings.getSize(), maxT);
final double psfSd = getPsfSd();
if (psfSd <= 0) {
return null;
}
final PsfModel psfModel = createPsfModel(localisationSets);
if (psfModel == null) {
return null;
}
// Create the camera noise model
createPerPixelCameraModelData(cameraModel);
createBackgroundPixels();
final int threadCount = Prefs.getThreads();
IJ.showStatus("Drawing image ...");
// Multi-thread for speed
final PeakResults syncResults = SynchronizedPeakResults.create(results, threadCount);
final ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
final List<Future<?>> futures = new LinkedList<>();
// Count all the frames to process
final Ticker ticker = ImageJUtils.createTicker(maxT, threadCount);
// Collect statistics on the number of photons actually simulated
// Process all frames
int index = 0;
int lastT = -1;
for (final LocalisationModelSet l : localisationSets) {
if (ImageJUtils.isInterrupted()) {
break;
}
if (l.getTime() != lastT) {
lastT = l.getTime();
futures.add(threadPool.submit(new ImageGenerator(localisationSets, newLocalisations, index, lastT, psfModel.copy(), syncResults, stack, poissonNoise, createRandomGenerator(), ticker)));
}
index++;
}
// Finish processing data
ConcurrencyUtils.waitForCompletionUnchecked(futures);
futures.clear();
if (ImageJUtils.isInterrupted()) {
IJ.showProgress(1);
return null;
}
// Do all the frames that had no localisations
float[] limits = null;
for (int t = 1; t <= maxT; t++) {
if (ImageJUtils.isInterrupted()) {
break;
}
final Object pixels = stack.getPixels(t);
if (pixels == null) {
futures.add(threadPool.submit(new ImageGenerator(localisationSets, newLocalisations, maxT, t, null, syncResults, stack, poissonNoise, createRandomGenerator(), ticker)));
} else if (limits == null) {
limits = MathUtils.limits((float[]) pixels);
}
}
// Finish
ConcurrencyUtils.waitForCompletionUnchecked(futures);
futures.clear();
threadPool.shutdown();
IJ.showProgress(1);
if (ImageJUtils.isInterrupted() || limits == null) {
return null;
}
results.end();
if (photonsRemoved.get() > 0) {
ImageJUtils.log("Removed %d localisations with less than %.1f rendered photons", photonsRemoved.get(), settings.getMinPhotons());
}
if (removedT1.get() > 0) {
ImageJUtils.log("Removed %d localisations with no neighbours @ SNR %.2f", removedT1.get(), settings.getMinSnrT1());
}
if (removedTn.get() > 0) {
ImageJUtils.log("Removed %d localisations with valid neighbours @ SNR %.2f", removedTn.get(), settings.getMinSnrTN());
}
if (photonStats.getN() > 0) {
ImageJUtils.log("Average photons rendered = %s +/- %s", MathUtils.rounded(photonStats.getMean()), MathUtils.rounded(photonStats.getStandardDeviation()));
}
// System.out.printf("rawPhotons = %f\n", rawPhotons.getMean());
// System.out.printf("drawPhotons = %f\n", drawPhotons.getMean());
// new HistogramPlotBuilder("draw photons", drawPhotons, "photons", true, 0, 1000);
// Update with all those localisation that have been drawn
localisationSets.clear();
localisationSets.addAll(newLocalisations);
newLocalisations = null;
IJ.showStatus("Displaying image ...");
ImageStack newStack = stack;
if (!settings.getRawImage()) {
// Get the global limits and ensure all values can be represented
final Object[] imageArray = stack.getImageArray();
limits = MathUtils.limits((float[]) imageArray[0]);
for (int j = 1; j < imageArray.length; j++) {
limits = MathUtils.limits(limits, (float[]) imageArray[j]);
}
// float limits0 = limits[0];
// Leave bias in place
final float limits0 = 0;
// Check if the image will fit in a 16-bit range
if ((limits[1] - limits0) < 65535) {
// Convert to 16-bit
newStack = new ImageStack(stack.getWidth(), stack.getHeight(), stack.getSize());
// Account for rounding
final float min = (float) (limits0 - 0.5);
for (int j = 0; j < imageArray.length; j++) {
final float[] image = (float[]) imageArray[j];
final short[] pixels = new short[image.length];
for (int k = 0; k < pixels.length; k++) {
pixels[k] = (short) (image[k] - min);
}
newStack.setPixels(pixels, j + 1);
// Free memory
imageArray[j] = null;
// Attempt to stay within memory (check vs 32MB)
if (MemoryUtils.getFreeMemory() < 33554432L) {
MemoryUtils.runGarbageCollectorOnce();
}
}
for (int k = 2; k-- > 0; ) {
limits[k] = (float) Math.floor(limits[k] - min);
}
} else {
// Keep as 32-bit but round to whole numbers
for (int j = 0; j < imageArray.length; j++) {
final float[] pixels = (float[]) imageArray[j];
for (int k = 0; k < pixels.length; k++) {
pixels[k] = Math.round(pixels[k]);
}
}
for (int k = 2; k-- > 0; ) {
limits[k] = Math.round(limits[k]);
}
}
}
// Show image
final ImagePlus imp = ImageJUtils.display(CREATE_DATA_IMAGE_TITLE, newStack);
final ij.measure.Calibration cal = new ij.measure.Calibration();
String unit = "nm";
double unitPerPixel = settings.getPixelPitch();
if (unitPerPixel > 100) {
unit = "um";
unitPerPixel /= 1000.0;
}
cal.setUnit(unit);
cal.pixelHeight = cal.pixelWidth = unitPerPixel;
final Rectangle bounds = cameraModel.getBounds();
if (bounds != null) {
cal.xOrigin = -bounds.x;
cal.yOrigin = -bounds.y;
}
imp.setCalibration(cal);
imp.setDimensions(1, 1, newStack.getSize());
imp.setDisplayRange(limits[0], limits[1]);
imp.updateAndDraw();
saveImage(imp);
final IJImageSource imageSource = new IJImageSource(imp);
// Shift simulation image source to correct location
results.setSource(imageSource);
results.setName(CREATE_DATA_IMAGE_TITLE + " (" + TITLE + ")");
// Bounds are relative to the image source
results.setBounds(new Rectangle(settings.getSize(), settings.getSize()));
results.setPsf(createPsf(psfSd));
MemoryPeakResults.addResults(results);
setBenchmarkResults(imp, results);
if (benchmarkMode && benchmarkParameters != null) {
benchmarkParameters.setPhotons(results);
}
final List<LocalisationModel> localisations = toLocalisations(localisationSets);
savePulses(localisations, results);
// Saved the fixed and moving localisations into different datasets
saveFixedAndMoving(results);
saveCompoundMolecules(results);
return localisations;
}
Aggregations