use of uk.ac.sussex.gdsc.smlm.data.config.ConfigurationException in project GDSC-SMLM by aherbert.
the class CreateData method run.
@Override
public void run(String arg) {
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
extraOptions = ImageJUtils.isExtraOptions();
simpleMode = (arg != null && arg.contains("simple"));
benchmarkMode = (arg != null && arg.contains("benchmark"));
spotMode = (arg != null && arg.contains("spot"));
trackMode = (arg != null && arg.contains("track"));
if ("load".equals(arg)) {
loadBenchmarkData();
return;
}
// Each localisation set is a collection of localisations that represent all localisations
// with the same ID that are on in the same image time frame (Note: the simulation
// can create many localisations per fluorophore per time frame which is useful when
// modelling moving particles)
List<LocalisationModelSet> localisationSets = null;
// Each fluorophore contains the on and off times when light was emitted
List<? extends FluorophoreSequenceModel> fluorophores = null;
if (simpleMode || benchmarkMode || spotMode) {
if (!showSimpleDialog()) {
return;
}
resetMemory();
// 1 second frames
settings.setExposureTime(1000);
areaInUm = settings.getSize() * settings.getPixelPitch() * settings.getSize() * settings.getPixelPitch() / 1e6;
// Number of spots per frame
int count = 0;
int[] nextN = null;
SpatialDistribution dist;
if (benchmarkMode) {
// --------------------
// BENCHMARK SIMULATION
// --------------------
// Draw the same point on the image repeatedly
count = 1;
dist = createFixedDistribution();
try {
reportAndSaveFittingLimits(dist);
} catch (final Exception ex) {
// This will be from the computation of the CRLB
IJ.error(TITLE, ex.getMessage());
return;
}
} else if (spotMode) {
// ---------------
// SPOT SIMULATION
// ---------------
// The spot simulation draws 0 or 1 random point per frame.
// Ensure we have 50% of the frames with a spot.
nextN = new int[settings.getParticles() * 2];
Arrays.fill(nextN, 0, settings.getParticles(), 1);
RandomUtils.shuffle(nextN, UniformRandomProviders.create());
// Only put spots in the central part of the image
final double border = settings.getSize() / 4.0;
dist = createUniformDistribution(border);
} else {
// -----------------
// SIMPLE SIMULATION
// -----------------
// The simple simulation draws n random points per frame to achieve a specified density.
// No points will appear in multiple frames.
// Each point has a random number of photons sampled from a range.
// We can optionally use a mask. Create his first as it updates the areaInUm
dist = createDistribution();
// Randomly sample (i.e. not uniform density in all frames)
if (settings.getSamplePerFrame()) {
final double mean = areaInUm * settings.getDensity();
ImageJUtils.log("Mean samples = %f", mean);
if (mean < 0.5) {
final GenericDialog gd = new GenericDialog(TITLE);
gd.addMessage("The mean samples per frame is low: " + MathUtils.rounded(mean) + "\n \nContinue?");
gd.enableYesNoCancel();
gd.hideCancelButton();
gd.showDialog();
if (!gd.wasOKed()) {
return;
}
}
final PoissonSampler poisson = new PoissonSampler(createRandomGenerator(), mean);
final StoredDataStatistics samples = new StoredDataStatistics(settings.getParticles());
while (samples.getSum() < settings.getParticles()) {
samples.add(poisson.sample());
}
nextN = new int[samples.getN()];
for (int i = 0; i < nextN.length; i++) {
nextN[i] = (int) samples.getValue(i);
}
} else {
// Use the density to get the number per frame
count = (int) Math.max(1, Math.round(areaInUm * settings.getDensity()));
}
}
UniformRandomProvider rng = null;
localisationSets = new ArrayList<>(settings.getParticles());
final int minPhotons = (int) settings.getPhotonsPerSecond();
final int range = (int) settings.getPhotonsPerSecondMaximum() - minPhotons + 1;
if (range > 1) {
rng = createRandomGenerator();
}
// Add frames at the specified density until the number of particles has been reached
int id = 0;
int time = 0;
while (id < settings.getParticles()) {
// Allow the number per frame to be specified
if (nextN != null) {
if (time >= nextN.length) {
break;
}
count = nextN[time];
}
// Simulate random positions in the frame for the specified density
time++;
for (int j = 0; j < count; j++) {
final double[] xyz = dist.next();
// Ignore within border. We do not want to draw things we cannot fit.
// if (!distBorder.isWithinXy(xyz))
// continue;
// Simulate random photons
final int intensity = minPhotons + ((rng != null) ? rng.nextInt(range) : 0);
final LocalisationModel m = new LocalisationModel(id, time, xyz, intensity, LocalisationModel.CONTINUOUS);
// Each localisation can be a separate localisation set
final LocalisationModelSet set = new LocalisationModelSet(id, time);
set.add(m);
localisationSets.add(set);
id++;
}
}
} else {
if (!showDialog()) {
return;
}
resetMemory();
areaInUm = settings.getSize() * settings.getPixelPitch() * settings.getSize() * settings.getPixelPitch() / 1e6;
int totalSteps;
double correlation = 0;
ImageModel imageModel;
if (trackMode) {
// ----------------
// TRACK SIMULATION
// ----------------
// In track mode we create fixed lifetime fluorophores that do not overlap in time.
// This is the simplest simulation to test moving molecules.
settings.setSeconds((int) Math.ceil(settings.getParticles() * (settings.getExposureTime() + settings.getTOn()) / 1000));
totalSteps = 0;
final double simulationStepsPerFrame = (settings.getStepsPerSecond() * settings.getExposureTime()) / 1000.0;
imageModel = new FixedLifetimeImageModel(settings.getStepsPerSecond() * settings.getTOn() / 1000.0, simulationStepsPerFrame, createRandomGenerator());
} else {
// ---------------
// FULL SIMULATION
// ---------------
// The full simulation draws n random points in space.
// The same molecule may appear in multiple frames, move and blink.
//
// Points are modelled as fluorophores that must be activated and then will
// blink and photo-bleach. The molecules may diffuse and this can be simulated
// with many steps per image frame. All steps from a frame are collected
// into a localisation set which can be drawn on the output image.
final SpatialIllumination activationIllumination = createIllumination(settings.getPulseRatio(), settings.getPulseInterval());
// Generate additional frames so that each frame has the set number of simulation steps
totalSteps = (int) Math.ceil(settings.getSeconds() * settings.getStepsPerSecond());
// Since we have an exponential decay of activations
// ensure half of the particles have activated by 30% of the frames.
final double eAct = totalSteps * 0.3 * activationIllumination.getAveragePhotons();
// Q. Does tOn/tOff change depending on the illumination strength?
imageModel = new ActivationEnergyImageModel(eAct, activationIllumination, settings.getStepsPerSecond() * settings.getTOn() / 1000.0, settings.getStepsPerSecond() * settings.getTOffShort() / 1000.0, settings.getStepsPerSecond() * settings.getTOffLong() / 1000.0, settings.getNBlinksShort(), settings.getNBlinksLong(), createRandomGenerator());
imageModel.setUseGeometricDistribution(settings.getNBlinksGeometricDistribution());
// Only use the correlation if selected for the distribution
if (PHOTON_DISTRIBUTION[PHOTON_CORRELATED].equals(settings.getPhotonDistribution())) {
correlation = settings.getCorrelation();
}
}
imageModel.setPhotonBudgetPerFrame(true);
imageModel.setDiffusion2D(settings.getDiffuse2D());
imageModel.setRotation2D(settings.getRotate2D());
IJ.showStatus("Creating molecules ...");
final SpatialDistribution distribution = createDistribution();
final List<CompoundMoleculeModel> compounds = createCompoundMolecules();
if (compounds == null) {
return;
}
final List<CompoundMoleculeModel> molecules = imageModel.createMolecules(compounds, settings.getParticles(), distribution, settings.getRotateInitialOrientation());
// Activate fluorophores
IJ.showStatus("Creating fluorophores ...");
// Note: molecules list will be converted to compounds containing fluorophores
fluorophores = imageModel.createFluorophores(molecules, totalSteps);
if (fluorophores.isEmpty()) {
IJ.error(TITLE, "No fluorophores created");
return;
}
// Map the fluorophore ID to the compound for mixtures
if (compounds.size() > 1) {
idToCompound = new TIntIntHashMap(fluorophores.size());
for (final FluorophoreSequenceModel l : fluorophores) {
idToCompound.put(l.getId(), l.getLabel());
}
}
IJ.showStatus("Creating localisations ...");
// TODO - Output a molecule Id for each fluorophore if using compound molecules. This allows
// analysis
// of the ratio of trimers, dimers, monomers, etc that could be detected.
totalSteps = checkTotalSteps(totalSteps, fluorophores);
if (totalSteps == 0) {
return;
}
imageModel.setPhotonDistribution(createPhotonDistribution());
try {
imageModel.setConfinementDistribution(createConfinementDistribution());
} catch (final ConfigurationException ex) {
// We asked the user if it was OK to continue and they said no
return;
}
// This should be optimised
imageModel.setConfinementAttempts(10);
final List<LocalisationModel> localisations = imageModel.createImage(molecules, settings.getFixedFraction(), totalSteps, settings.getPhotonsPerSecond() / settings.getStepsPerSecond(), correlation, settings.getRotateDuringSimulation());
// Re-adjust the fluorophores to the correct time
if (settings.getStepsPerSecond() != 1) {
final double scale = 1.0 / settings.getStepsPerSecond();
for (final FluorophoreSequenceModel f : fluorophores) {
f.adjustTime(scale);
}
}
// Integrate the frames
localisationSets = combineSimulationSteps(localisations);
localisationSets = filterToImageBounds(localisationSets);
}
datasetNumber.getAndIncrement();
final List<LocalisationModel> localisations = drawImage(localisationSets);
if (localisations == null || localisations.isEmpty()) {
IJ.error(TITLE, "No localisations created");
return;
}
fluorophores = removeFilteredFluorophores(fluorophores, localisations);
final double signalPerFrame = showSummary(fluorophores, localisations);
if (!benchmarkMode) {
final boolean fullSimulation = (!(simpleMode || spotMode));
saveSimulationParameters(localisations.size(), fullSimulation, signalPerFrame);
}
IJ.showStatus("Saving data ...");
saveFluorophores(fluorophores);
saveImageResults(results);
saveLocalisations(localisations);
// The settings for the filenames may have changed
SettingsManager.writeSettings(settings.build());
IJ.showStatus("Done");
}
use of uk.ac.sussex.gdsc.smlm.data.config.ConfigurationException 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.smlm.data.config.ConfigurationException in project GDSC-SMLM by aherbert.
the class CreateData method checkConfiguration.
private static void checkConfiguration(String message) {
final GenericDialog gd = new GenericDialog(TITLE);
gd.addMessage(TextUtils.wrap("Warning: " + message, 80));
gd.setOKLabel("Continue");
gd.showDialog();
if (gd.wasCanceled()) {
throw new ConfigurationException(message);
}
}
use of uk.ac.sussex.gdsc.smlm.data.config.ConfigurationException in project GDSC-SMLM by aherbert.
the class ImageJTablePeakResults method begin.
@Override
public void begin() {
tableActive = false;
// Set-up unit processing that requires the calibration
toPixelConverter = new IdentityTypeConverter<>(null);
calculator = null;
canComputePrecision = false;
rounder = RounderUtils.create(roundingPrecision);
// We must correctly convert all the PSF parameter types
helper = new PeakResultConversionHelper(getCalibration(), getPsf());
helper.setIntensityUnit(intensityUnit);
helper.setDistanceUnit(distanceUnit);
helper.setAngleUnit(angleUnit);
converters = helper.getConverters();
if (hasCalibration()) {
if (showPrecision) {
if (computePrecision) {
try {
calculator = Gaussian2DPeakResultHelper.create(getPsf(), getCalibrationReader(), Gaussian2DPeakResultHelper.LSE_PRECISION);
canComputePrecision = true;
} catch (final ConfigurationException ex) {
// Cannot compute precision
} catch (final ConversionException ex) {
// Cannot compute precision
}
}
}
try {
if (helper.hasDistanceConverter()) {
toPixelConverter = UnitConverterUtils.createConverter(distanceUnit, DistanceUnit.PIXEL, getCalibrationReader().getNmPerPixel());
}
} catch (final ConversionException ex) {
// Gracefully fail so ignore this
}
}
ic = converters[PeakResult.INTENSITY];
outIndices = SimpleArrayUtils.natural(converters.length);
if (!showZ) {
final TIntArrayList list = new TIntArrayList(outIndices);
list.remove(PeakResult.Z);
outIndices = list.toArray();
}
// Update the calibration if converters were created
if (helper.isCalibrationChanged()) {
setCalibration(helper.getCalibration());
}
createSourceText();
createResultsWindow();
if (clearAtStart) {
tp.clear();
}
size = 0;
// Let some results appear before drawing.
// ImageJ will auto-layout columns if it has less than 10 rows
nextRepaintSize = 9;
tableActive = true;
}
use of uk.ac.sussex.gdsc.smlm.data.config.ConfigurationException in project GDSC-SMLM by aherbert.
the class PsfImagePeakResults method preBegin.
@Override
protected void preBegin() {
// this.displayFlags should be OK so don't call super.preBegin()
requirePsfParameters = true;
int flags = 0;
if ((displayFlags & DISPLAY_SIGNAL) != 0) {
flags |= Gaussian2DPeakResultHelper.AMPLITUDE;
}
if (fixedWidth) {
// Check if we need the amplitude for the fixed width PSF
requirePsfParameters = flags != 0;
} else if (calculatedPrecision) {
flags |= Gaussian2DPeakResultHelper.LSE_PRECISION;
// To convert the precision to pixels
if (!hasCalibration()) {
throw new ConfigurationException("nm/pixel is required when drawing using the precision");
}
dc = UnitConverterUtils.createConverter(DistanceUnit.NM, DistanceUnit.PIXEL, getCalibrationReader().getNmPerPixel());
} else {
// We need to know the parameters for the Gaussian 2D PSF
final int[] indices = PsfHelper.getGaussian2DWxWyIndices(getPsf());
isx = indices[0];
isy = indices[1];
try {
ia = PsfHelper.getGaussian2DAngleIndex(getPsf());
} catch (final ConfigurationException ex) {
// No rotation angle
ia = 0;
}
}
if (flags != 0) {
calculator = Gaussian2DPeakResultHelper.create(getPsf(), getCalibrationReader(), flags);
}
}
Aggregations