use of org.apache.commons.lang3.concurrent.ConcurrentRuntimeException in project GDSC-SMLM by aherbert.
the class BenchmarkSmartSpotRanking method runAnalysis.
private void runAnalysis() {
// Extract all the results in memory into a list per frame. This can be cached
boolean refresh = false;
final Pair<Integer, TIntObjectHashMap<List<Coordinate>>> coords = coordinateCache.get();
TIntObjectHashMap<List<Coordinate>> actualCoordinates;
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
actualCoordinates = ResultsMatchCalculator.getCoordinates(results, false);
coordinateCache.set(Pair.of(simulationParameters.id, actualCoordinates));
refresh = true;
} else {
actualCoordinates = coords.getValue();
}
// Extract all the candidates into a list per frame. This can be cached if the settings have not
// changed.
CandidateData candidateData = candidateDataCache.get();
if (refresh || candidateData == null || candidateData.differentSettings(filterResult.id, settings)) {
candidateData = subsetFilterResults(filterResult.filterResults);
candidateDataCache.set(candidateData);
}
final TIntObjectHashMap<FilterCandidates> filterCandidates = candidateData.filterCandidates;
final ImageStack stack = imp.getImageStack();
// 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(filterCandidates.size(), nThreads);
for (int i = 0; i < nThreads; i++) {
final Worker worker = new Worker(jobs, stack, actualCoordinates, filterCandidates, ticker);
final Thread t = new Thread(worker);
workers.add(worker);
threads.add(t);
t.start();
}
// Process the frames
filterCandidates.forEachKey(value -> {
put(jobs, value);
return true;
});
// 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("Unexpected interrupt", ex);
}
}
threads.clear();
IJ.showProgress(1);
if (ImageJUtils.isInterrupted()) {
IJ.showStatus("Aborted");
return;
}
IJ.showStatus("Collecting results ...");
final TIntObjectHashMap<RankResults> rankResults = new TIntObjectHashMap<>();
for (final Worker w : workers) {
rankResults.putAll(w.results);
}
summariseResults(rankResults, candidateData);
IJ.showStatus("");
}
use of org.apache.commons.lang3.concurrent.ConcurrentRuntimeException in project GDSC-SMLM by aherbert.
the class BenchmarkSpotFilter method runAnalysis.
private BenchmarkSpotFilterResult runAnalysis(FitEngineConfiguration config, boolean batchSummary) {
if (ImageJUtils.isInterrupted()) {
return null;
}
final MaximaSpotFilter spotFilter = config.createSpotFilter();
if (!batchMode) {
IJ.showStatus("Computing results ...");
}
final ImageStack stack = imp.getImageStack();
float background = 0;
if (spotFilter.isAbsoluteIntensity()) {
if (Float.isNaN(resultsBackground)) {
// To allow the signal factor to be computed we need to lower the image by the background so
// that the intensities correspond to the results amplitude.
// Just assume the simulation background is uniform.
final StandardResultProcedure s = new StandardResultProcedure(results, IntensityUnit.PHOTON);
s.getB();
resultsBackground = (float) (MathUtils.sum(s.background) / results.size());
}
background = this.resultsBackground;
}
// Create the weights if needed
if (cameraModel.isPerPixelModel() && spotFilter.isWeighted() && weights == null) {
bounds = cameraModel.getBounds();
weights = cameraModel.getNormalisedWeights(bounds);
}
// Create a pool of workers
final int nThreads = Prefs.getThreads();
final BlockingQueue<Integer> jobs = new ArrayBlockingQueue<>(nThreads * 2);
final List<Worker> workers = new LocalList<>(nThreads);
final List<Thread> threads = new LocalList<>(nThreads);
for (int i = 0; i < nThreads; i++) {
final Worker worker = new Worker(jobs, stack, spotFilter, background, simulationCoords);
final Thread t = new Thread(worker);
workers.add(worker);
threads.add(t);
t.start();
}
// Fit the frames
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("Unexpected interrupt", ex);
}
}
threads.clear();
if (ImageJUtils.isInterrupted()) {
return null;
}
if (!batchMode) {
IJ.showProgress(-1);
IJ.showStatus("Collecting results ...");
}
TIntObjectHashMap<FilterResult> filterResults = null;
time = 0;
for (int i = 0; i < workers.size(); i++) {
final Worker w = workers.get(i);
time += w.time;
if (filterResults == null) {
filterResults = w.results;
} else {
filterResults.putAll(w.results);
w.results.clear();
w.results.compact();
}
}
if (filterResults == null) {
throw new NullPointerException();
}
filterResults.compact();
if (!batchMode) {
IJ.showStatus("Summarising results ...");
}
// Show a table of the results
final BenchmarkSpotFilterResult filterResult = summariseResults(filterResults, config, spotFilter, batchSummary);
if (!batchMode) {
IJ.showStatus("");
}
return filterResult;
}
use of org.apache.commons.lang3.concurrent.ConcurrentRuntimeException in project GDSC-SMLM by aherbert.
the class ImageJImagePeakResults method end.
@Override
public void end() {
// Wait for previous image to finish rendering
while (!imageLock.acquire()) {
try {
if (IJ.debugMode) {
IJ.log("Waiting for final image");
}
Thread.sleep(50);
} catch (final InterruptedException ex) {
// Reset interrupt status
Thread.currentThread().interrupt();
throw new ConcurrentRuntimeException("Unexpected interruption", ex);
}
}
// We have the lock
try {
createImage();
imp.updateAndDraw();
} finally {
imageLock.release();
}
if (rollingWindowSize > 0) {
imp.setDimensions(1, 1, imp.getStackSize());
}
imageActive = false;
}
use of org.apache.commons.lang3.concurrent.ConcurrentRuntimeException in project GDSC-SMLM by aherbert.
the class PsfDrift method computeDrift.
private void computeDrift() {
// Create a grid of XY offset positions between 0-1 for PSF insert
final double[] grid = new double[settings.gridSize];
for (int i = 0; i < grid.length; i++) {
grid[i] = (double) i / settings.gridSize;
}
// Configure fitting region
final int w = 2 * settings.regionSize + 1;
centrePixel = w / 2;
// Check region size using the image PSF
final double newPsfWidth = imp.getWidth() / settings.scale;
if (Math.ceil(newPsfWidth) > w) {
ImageJUtils.log(TITLE + ": Fitted region size (%d) is smaller than the scaled PSF (%.1f)", w, newPsfWidth);
}
// Create robust PSF fitting settings
final double a = psfSettings.getPixelSize() * settings.scale;
final double sa = PsfCalculator.squarePixelAdjustment(psfSettings.getPixelSize() * (psfSettings.getFwhm() / Gaussian2DFunction.SD_TO_FWHM_FACTOR), a);
fitConfig.setInitialPeakStdDev(sa / a);
fitConfig.setBackgroundFitting(settings.backgroundFitting);
fitConfig.setNotSignalFitting(false);
fitConfig.setComputeDeviations(false);
fitConfig.setDisableSimpleFilter(true);
// Create the PSF over the desired z-depth
final int depth = (int) Math.round(settings.zDepth / psfSettings.getPixelDepth());
int startSlice = psfSettings.getCentreImage() - depth;
int endSlice = psfSettings.getCentreImage() + depth;
final int nSlices = imp.getStackSize();
startSlice = MathUtils.clip(1, nSlices, startSlice);
endSlice = MathUtils.clip(1, nSlices, endSlice);
final ImagePsfModel psf = createImagePsf(startSlice, endSlice, settings.scale);
final int minz = startSlice - psfSettings.getCentreImage();
final int maxz = endSlice - psfSettings.getCentreImage();
final int nZ = maxz - minz + 1;
final int gridSize2 = grid.length * grid.length;
total = nZ * gridSize2;
// Store all the fitting results
final int nStartPoints = getNumberOfStartPoints();
results = new double[total * nStartPoints][];
// TODO - Add ability to iterate this, adjusting the current offset in the PSF
// each iteration
// Create a pool of workers
final int threadCount = Prefs.getThreads();
final Ticker ticker = ImageJUtils.createTicker(total, threadCount, "Fitting...");
final BlockingQueue<Job> jobs = new ArrayBlockingQueue<>(threadCount * 2);
final List<Thread> threads = new LinkedList<>();
for (int i = 0; i < threadCount; i++) {
final Worker worker = new Worker(jobs, psf, w, fitConfig, ticker);
final Thread t = new Thread(worker);
threads.add(t);
t.start();
}
// Fit
outer: for (int z = minz, i = 0; z <= maxz; z++) {
for (int x = 0; x < grid.length; x++) {
for (int y = 0; y < grid.length; y++, i++) {
if (IJ.escapePressed()) {
break outer;
}
put(jobs, new Job(z, grid[x], grid[y], i));
}
}
}
// If escaped pressed then do not need to stop the workers, just return
if (ImageJUtils.isInterrupted()) {
ImageJUtils.finished();
return;
}
// Finish all the worker threads by passing in a null job
for (int i = 0; i < threads.size(); i++) {
put(jobs, new Job());
}
// 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("Unexpected interrupt", ex);
}
}
threads.clear();
ImageJUtils.finished();
// Plot the average and SE for the drift curve
// Plot the recall
final double[] zPosition = new double[nZ];
final double[] avX = new double[nZ];
final double[] seX = new double[nZ];
final double[] avY = new double[nZ];
final double[] seY = new double[nZ];
final double[] recall = new double[nZ];
for (int z = minz, i = 0; z <= maxz; z++, i++) {
final Statistics statsX = new Statistics();
final Statistics statsY = new Statistics();
for (int s = 0; s < nStartPoints; s++) {
int resultPosition = i * gridSize2 + s * total;
final int endResultPosition = resultPosition + gridSize2;
while (resultPosition < endResultPosition) {
if (results[resultPosition] != null) {
statsX.add(results[resultPosition][0]);
statsY.add(results[resultPosition][1]);
}
resultPosition++;
}
}
zPosition[i] = z * psfSettings.getPixelDepth();
avX[i] = statsX.getMean();
seX[i] = statsX.getStandardError();
avY[i] = statsY.getMean();
seY[i] = statsY.getStandardError();
recall[i] = (double) statsX.getN() / (nStartPoints * gridSize2);
}
// Find the range from the z-centre above the recall limit
int centre = 0;
for (int slice = startSlice, i = 0; slice <= endSlice; slice++, i++) {
if (slice == psfSettings.getCentreImage()) {
centre = i;
break;
}
}
if (recall[centre] < settings.recallLimit) {
return;
}
int start = centre;
int end = centre;
for (int i = centre; i-- > 0; ) {
if (recall[i] < settings.recallLimit) {
break;
}
start = i;
}
for (int i = centre; ++i < recall.length; ) {
if (recall[i] < settings.recallLimit) {
break;
}
end = i;
}
final int iterations = 1;
LoessInterpolator loess = null;
if (settings.smoothing > 0) {
loess = new LoessInterpolator(settings.smoothing, iterations);
}
final double[][] smoothx = displayPlot("Drift X", "X (nm)", zPosition, avX, seX, loess, start, end);
final double[][] smoothy = displayPlot("Drift Y", "Y (nm)", zPosition, avY, seY, loess, start, end);
displayPlot("Recall", "Recall", zPosition, recall, null, null, start, end);
windowOrganiser.tile();
// Ask the user if they would like to store them in the image
final GenericDialog gd = new GenericDialog(TITLE);
gd.enableYesNoCancel();
gd.hideCancelButton();
startSlice = psfSettings.getCentreImage() - (centre - start);
endSlice = psfSettings.getCentreImage() + (end - centre);
ImageJUtils.addMessage(gd, "Save the drift to the PSF?\n \nSlices %d (%s nm) - %d (%s nm) above recall limit", startSlice, MathUtils.rounded(zPosition[start]), endSlice, MathUtils.rounded(zPosition[end]));
gd.addMessage("Optionally average the end points to set drift outside the limits.\n" + "(Select zero to ignore)");
gd.addSlider("Number_of_points", 0, 10, settings.positionsToAverage);
gd.showDialog();
if (gd.wasOKed()) {
settings.positionsToAverage = Math.abs((int) gd.getNextNumber());
final Map<Integer, Offset> oldOffset = psfSettings.getOffsetsMap();
final boolean useOldOffset = settings.useOffset && !oldOffset.isEmpty();
final LocalList<double[]> offset = new LocalList<>();
final double pitch = psfSettings.getPixelSize();
int index = 0;
for (int i = start, slice = startSlice; i <= end; slice++, i++) {
index = findCentre(zPosition[i], smoothx, index);
if (index == -1) {
ImageJUtils.log("Failed to find the offset for depth %.2f", zPosition[i]);
continue;
}
// The offset should store the difference to the centre in pixels so divide by the pixel
// pitch
double cx = smoothx[1][index] / pitch;
double cy = smoothy[1][index] / pitch;
if (useOldOffset) {
final Offset o = oldOffset.get(slice);
if (o != null) {
cx += o.getCx();
cy += o.getCy();
}
}
offset.add(new double[] { slice, cx, cy });
}
addMissingOffsets(startSlice, endSlice, nSlices, offset);
final Offset.Builder offsetBuilder = Offset.newBuilder();
final ImagePSF.Builder imagePsfBuilder = psfSettings.toBuilder();
for (final double[] o : offset) {
final int slice = (int) o[0];
offsetBuilder.setCx(o[1]);
offsetBuilder.setCy(o[2]);
imagePsfBuilder.putOffsets(slice, offsetBuilder.build());
}
imagePsfBuilder.putNotes(TITLE, String.format("Solver=%s, Region=%d", PeakFit.getSolverName(fitConfig), settings.regionSize));
imp.setProperty("Info", ImagePsfHelper.toString(imagePsfBuilder));
}
}
use of org.apache.commons.lang3.concurrent.ConcurrentRuntimeException in project GDSC-SMLM by aherbert.
the class PsfEstimator method calculateStatistics.
private boolean calculateStatistics(PeakFit fitter, double[] params, double[] paramsDev) {
debug(" Fitting PSF");
swapStatistics();
// Create the fit engine using the PeakFit plugin
final FitConfiguration fitConfig = config.getFitConfiguration();
fitConfig.setInitialPeakStdDev0((float) params[1]);
try {
fitConfig.setInitialPeakStdDev1((float) params[2]);
fitConfig.setInitialAngle((float) Math.toRadians(params[0]));
} catch (IllegalStateException ex) {
// Ignore this as the current PSF is not a 2 axis and theta Gaussian PSF
}
final ImageStack stack = imp.getImageStack();
final Rectangle roi = stack.getProcessor(1).getRoi();
ImageSource source = new IJImageSource(imp);
// Allow interlaced data by wrapping the image source
if (interlacedData) {
source = new InterlacedImageSource(source, dataStart, dataBlock, dataSkip);
}
// Allow frame aggregation by wrapping the image source
if (integrateFrames > 1) {
source = new AggregatedImageSource(source, integrateFrames);
}
fitter.initialiseImage(source, roi, true);
fitter.addPeakResults(this);
fitter.initialiseFitting();
final FitEngine engine = fitter.createFitEngine();
// Use random slices
final int[] slices = new int[stack.getSize()];
for (int i = 0; i < slices.length; i++) {
slices[i] = i + 1;
}
RandomUtils.shuffle(slices, UniformRandomProviders.create());
IJ.showStatus("Fitting ...");
// Use multi-threaded code for speed
int sliceIndex;
for (sliceIndex = 0; sliceIndex < slices.length; sliceIndex++) {
final int slice = slices[sliceIndex];
IJ.showProgress(size(), settings.getNumberOfPeaks());
final ImageProcessor ip = stack.getProcessor(slice);
// stack processor does not set the bounds required by ImageConverter
ip.setRoi(roi);
final FitJob job = new FitJob(slice, ImageJImageConverter.getData(ip), roi);
engine.run(job);
if (sampleSizeReached() || ImageJUtils.isInterrupted()) {
break;
}
}
if (ImageJUtils.isInterrupted()) {
IJ.showProgress(1);
engine.end(true);
return false;
}
// Wait until we have enough results
while (!sampleSizeReached() && !engine.isQueueEmpty()) {
IJ.showProgress(size(), settings.getNumberOfPeaks());
try {
Thread.sleep(50);
} catch (final InterruptedException ex) {
Thread.currentThread().interrupt();
throw new ConcurrentRuntimeException("Unexpected interruption", ex);
}
}
// End now if we have enough samples
engine.end(sampleSizeReached());
ImageJUtils.finished();
// This count will be an over-estimate given that the provider is ahead of the consumer
// in this multi-threaded system
debug(" Processed %d/%d slices (%d peaks)", sliceIndex, slices.length, size());
setParams(ANGLE, params, paramsDev, sampleNew[ANGLE]);
setParams(X, params, paramsDev, sampleNew[X]);
setParams(Y, params, paramsDev, sampleNew[Y]);
if (settings.getShowHistograms()) {
final HistogramPlotBuilder builder = new HistogramPlotBuilder(TITLE).setNumberOfBins(settings.getHistogramBins());
final WindowOrganiser wo = new WindowOrganiser();
for (int ii = 0; ii < 3; ii++) {
if (sampleNew[ii].getN() == 0) {
continue;
}
final StoredDataStatistics stats = StoredDataStatistics.create(sampleNew[ii].getValues());
builder.setData(stats).setName(NAMES[ii]).setPlotLabel("Mean = " + MathUtils.rounded(stats.getMean()) + ". Median = " + MathUtils.rounded(sampleNew[ii].getPercentile(50))).show(wo);
}
wo.tile();
}
if (size() < 2) {
log("ERROR: Insufficient number of fitted peaks, terminating ...");
return false;
}
return true;
}
Aggregations