use of uk.ac.sussex.gdsc.smlm.results.PeakResults in project GDSC-SMLM by aherbert.
the class BenchmarkSpotFit method runFitting.
private BenchmarkSpotFitResult runFitting() {
// Extract all the results in memory into a list per frame. This can be cached
boolean refresh = false;
Pair<Integer, TIntObjectHashMap<List<Coordinate>>> coords = coordinateCache.get();
if (coords.getKey() != simulationParameters.id) {
// Do not get integer coordinates
// The Coordinate objects will be PeakResultPoint objects that store the original PeakResult
// from the MemoryPeakResults
coords = Pair.of(simulationParameters.id, ResultsMatchCalculator.getCoordinates(results, false));
coordinateCache.set(coords);
refresh = true;
}
final TIntObjectHashMap<List<Coordinate>> actualCoordinates = coords.getValue();
// Extract all the candidates into a list per frame. This can be cached if the settings have not
// changed
final int width = (config.isIncludeNeighbours()) ? config.getFittingWidth() : 0;
CandidateData candidateData = candidateDataCache.get();
if (refresh || candidateData == null || candidateData.differentSettings(filterResult.id, settings, width)) {
candidateData = subsetFilterResults(filterResult.filterResults, width);
candidateDataCache.set(candidateData);
}
final StopWatch stopWatch = StopWatch.createStarted();
final ImageStack stack = imp.getImageStack();
clearFitResults();
// Save results to memory
final MemoryPeakResults peakResults = new MemoryPeakResults();
peakResults.copySettings(this.results);
peakResults.setName(TITLE);
config.configureOutputUnits();
final FitConfiguration fitConfig = config.getFitConfiguration();
peakResults.setCalibration(fitConfig.getCalibration());
MemoryPeakResults.addResults(peakResults);
// Create a pool of workers
final int nThreads = Prefs.getThreads();
final BlockingQueue<Integer> jobs = new ArrayBlockingQueue<>(nThreads * 2);
final List<Worker> workers = new LinkedList<>();
final List<Thread> threads = new LinkedList<>();
final Ticker ticker = ImageJUtils.createTicker(stack.getSize(), nThreads, "Fitting frames ...");
final PeakResults syncResults = SynchronizedPeakResults.create(peakResults, nThreads);
for (int i = 0; i < nThreads; i++) {
final Worker worker = new Worker(jobs, stack, actualCoordinates, candidateData.filterCandidates, syncResults, ticker);
final Thread t = new Thread(worker);
workers.add(worker);
threads.add(t);
t.start();
}
// Fit the frames
final long startTime = System.nanoTime();
for (int i = 1; i <= stack.getSize(); i++) {
put(jobs, i);
}
// Finish all the worker threads by passing in a null job
for (int i = 0; i < threads.size(); i++) {
put(jobs, -1);
}
// Wait for all to finish
for (int i = 0; i < threads.size(); i++) {
try {
threads.get(i).join();
} catch (final InterruptedException ex) {
Thread.currentThread().interrupt();
throw new ConcurrentRuntimeException(ex);
}
}
final long runTime = System.nanoTime() - startTime;
threads.clear();
ImageJUtils.finished();
if (ImageJUtils.isInterrupted()) {
return null;
}
stopWatch.stop();
final String timeString = stopWatch.toString();
IJ.log("Spot fit time : " + timeString);
IJ.showStatus("Collecting results ...");
if (fitConfig.isFitCameraCounts()) {
// Convert to photons for consistency
results.convertToPreferredUnits();
}
final TIntObjectHashMap<FilterCandidates> fitResults = new TIntObjectHashMap<>();
for (final Worker w : workers) {
fitResults.putAll(w.results);
}
// Assign a unique ID to each result
int count = 0;
// Materialise into an array since we use it twice
final FilterCandidates[] candidates = fitResults.values(new FilterCandidates[fitResults.size()]);
for (final FilterCandidates result : candidates) {
for (int i = 0; i < result.fitResult.length; i++) {
final MultiPathFitResult fitResult = result.fitResult[i];
count += count(fitResult.getSingleFitResult());
count += count(fitResult.getMultiFitResult());
count += count(fitResult.getDoubletFitResult());
count += count(fitResult.getMultiDoubletFitResult());
}
}
final PreprocessedPeakResult[] preprocessedPeakResults = new PreprocessedPeakResult[count];
count = 0;
for (final FilterCandidates result : candidates) {
for (int i = 0; i < result.fitResult.length; i++) {
final MultiPathFitResult fitResult = result.fitResult[i];
count = store(fitResult.getSingleFitResult(), count, preprocessedPeakResults);
count = store(fitResult.getMultiFitResult(), count, preprocessedPeakResults);
count = store(fitResult.getDoubletFitResult(), count, preprocessedPeakResults);
count = store(fitResult.getMultiDoubletFitResult(), count, preprocessedPeakResults);
}
}
final BenchmarkSpotFitResult newSpotFitResults = new BenchmarkSpotFitResult(simulationParameters.id, fitResults);
newSpotFitResults.distanceInPixels = distanceInPixels;
newSpotFitResults.lowerDistanceInPixels = lowerDistanceInPixels;
newSpotFitResults.stopWatch = stopWatch;
summariseResults(newSpotFitResults, runTime, preprocessedPeakResults, count, candidateData, actualCoordinates);
IJ.showStatus("");
spotFitResults.set(newSpotFitResults);
return newSpotFitResults;
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResults 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;
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResults in project GDSC-SMLM by aherbert.
the class ResultsManager method save.
private static boolean save(ResultsFileSettings resultsSettings, MemoryPeakResults source) {
// Assume the directory exists
String resultsFilename;
try {
resultsFilename = new File(resultsSettings.getResultsDirectory(), source.getName() + ".results." + ResultsProtosHelper.getExtension(resultsSettings.getFileFormat())).getCanonicalPath();
} catch (final IOException ex) {
return false;
}
PeakResults results;
switch(resultsSettings.getFileFormat()) {
case BINARY:
results = new BinaryFilePeakResults(resultsFilename, source.hasDeviations(), source.hasEndFrame(), source.hasId(), resultsSettings.getShowPrecision());
break;
case TEXT:
final TextFilePeakResults f = new TextFilePeakResults(resultsFilename, source.hasDeviations(), source.hasEndFrame(), source.hasId(), resultsSettings.getShowPrecision());
f.setDistanceUnit(resultsSettings.getDistanceUnit());
f.setIntensityUnit(resultsSettings.getIntensityUnit());
f.setAngleUnit(resultsSettings.getAngleUnit());
f.setComputePrecision(true);
results = f;
break;
case MALK:
results = new MalkFilePeakResults(resultsFilename);
break;
case TSF:
results = new TsfPeakResultsWriter(resultsFilename);
break;
default:
throw new IllegalArgumentException("Unsupported file format: " + resultsSettings.getFileFormat());
}
results.copySettings(source);
results.begin();
results.addAll(source.toArray());
results.end();
ImageJUtils.log("Saved %s to %s", source.getName(), resultsFilename);
return true;
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResults in project GDSC-SMLM by aherbert.
the class ResultsManager method run.
@Override
public void run(String arg) {
extraOptions = ImageJUtils.isExtraOptions();
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
if ("load".equals(arg)) {
batchLoad();
return;
}
if ("save".equals(arg)) {
batchSave();
return;
}
if (StringUtils.startsWith(arg, "clear")) {
runClearMemory(arg);
return;
}
if (!showDialog()) {
return;
}
final MemoryPeakResults results = loadResults(settings.inputOption);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
IJ.showStatus("");
return;
}
IJ.showStatus("Loaded " + TextUtils.pleural(results.size(), "result"));
boolean saved = false;
if (resultsSettings.getResultsInMemorySettings().getInMemory() && fileInput) {
if (!addResultsToMemory(results, settings.inputFilename)) {
IJ.showStatus("");
return;
}
saved = true;
}
if (resultsSettings.getResultsTableSettings().getResultsTableFormatValue() <= 0 && resultsSettings.getResultsImageSettings().getImageTypeValue() <= 0 && TextUtils.isNullOrEmpty(resultsSettings.getResultsFileSettings().getResultsFilename())) {
// No outputs. Error if results were not saved to memory
if (!saved) {
IJ.error(TITLE, "No output selected");
}
return;
}
final Rectangle bounds = results.getBounds(true);
final boolean showDeviations = resultsSettings.getShowDeviations() && canShowDeviations(results);
final boolean showEndFrame = canShowEndFrame(results);
final boolean showId = canShowId(results);
final boolean showCategory = canShowCategory(results);
// Display the configured output
final PeakResultsList outputList = new PeakResultsList();
outputList.copySettings(results);
final int tableFormat = resultsSettings.getResultsTableSettings().getResultsTableFormatValue();
if (tableFormat == ResultsTableFormat.IMAGEJ_VALUE) {
addImageJTableResults(outputList, resultsSettings.getResultsTableSettings(), showDeviations, showEndFrame, results.is3D(), showId, showCategory);
} else if (tableFormat == ResultsTableFormat.INTERACTIVE_VALUE) {
showInteractiveTable(results, resultsSettings.getResultsTableSettings());
}
addImageResults(outputList, resultsSettings.getResultsImageSettings(), bounds, (extraOptions) ? FLAG_EXTRA_OPTIONS : 0);
addFileResults(outputList, showDeviations, showEndFrame, showId, showCategory);
if (outputList.numberOfOutputs() == 0) {
// This occurs when only using the interactive table
IJ.showStatus("Processed " + TextUtils.pleural(results.size(), "result"));
return;
}
IJ.showStatus("Processing outputs ...");
// Reduce to single object for speed
final PeakResults output = (outputList.numberOfOutputs() == 1) ? outputList.toArray()[0] : outputList;
output.begin();
// Note: We could add a batch iterator to the MemoryPeakResults.
// However the speed increase will be marginal as the main time
// taken is in processing the outputs.
// Process in batches to provide progress
final Counter progress = new Counter();
final int totalProgress = results.size();
final int batchSize = Math.max(100, totalProgress / 10);
final FixedPeakResultList batch = new FixedPeakResultList(batchSize);
IJ.showProgress(0);
results.forEach((PeakResultProcedureX) result -> {
batch.add(result);
if (batch.size == batchSize) {
if (IJ.escapePressed()) {
batch.clear();
return true;
}
output.addAll(batch.results);
batch.clear();
IJ.showProgress(progress.incrementAndGet(batchSize), totalProgress);
}
return false;
});
// Will be empty if interrupted
if (batch.isNotEmpty()) {
output.addAll(batch.toArray());
}
IJ.showProgress(1);
output.end();
if (output.size() == results.size()) {
IJ.showStatus("Processed " + TextUtils.pleural(results.size(), "result"));
} else {
IJ.showStatus(String.format("A %d/%s", output.size(), TextUtils.pleural(results.size(), "result")));
}
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResults in project GDSC-SMLM by aherbert.
the class PeakFit method initialiseFitting.
/**
* Set-up the fitting using all the configured properties. Prepare the output results.
*
* @return true, if successful
*/
public boolean initialiseFitting() {
if (source == null) {
return false;
}
// Do this to ensure the serialised configuration is correct
updateFitConfiguration(config);
results.setSource(source);
String name = source.getName();
if (!TextUtils.isNullOrEmpty(resultsSuffix)) {
name += " " + resultsSuffix;
}
if (maximaIdentification) {
name += " (Maxima)";
} else if (fitMaxima) {
name += " (" + getSolverName() + " Fit Maxima)";
} else {
name += " (" + getSolverName() + ")";
}
results.setName(name);
results.setBounds(bounds);
// Calibration cal = calibration.clone();
// Account for the frame integration
// TODO - Should we change this so that if integrate frames is used then the data
// are converted to ExtendedPeakResult with a start and end frame
// cal.exposureTime *= integrateFrames;
// if (interlacedData)
// {
// cal.exposureTime *= ((double)dataBlock / (dataBlock + dataSkip));
// }
final CalibrationWriter cal = fitConfig.getCalibrationWriter();
cal.setTimeUnit(TimeUnit.FRAME);
results.setCalibration(cal.getCalibration());
results.setPsf(fitConfig.getPsf());
results.setConfiguration(SettingsManager.toJson(config.getFitEngineSettings()));
// This is added first as it cannot be closed. If the table is closed then the
// number of results at the end is reported incorrectly.
addMemoryResults(results, false);
addTableResults(results);
ResultsManager.addImageResults(results, resultsSettings.getResultsImageSettings(), bounds, (extraOptions) ? ResultsManager.FLAG_EXTRA_OPTIONS : 0);
addFileResults(results);
addDefaultResults(results);
results.begin();
if (simpleFit && settings.showImage) {
for (final PeakResults r : results.toArray()) {
if (r instanceof ImageJImagePeakResults) {
final ImagePlus i = ((ImageJImagePeakResults) r).getImagePlus();
ImageJUtils.log("Super-resolution image title = " + i.getTitle());
WindowManager.toFront(i.getWindow());
}
}
}
return true;
}
Aggregations