use of uk.ac.sussex.gdsc.core.logging.Ticker 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.core.logging.Ticker in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method scoreFilters.
@Nullable
private FilterScoreResult[] scoreFilters(FilterSet filterSet, boolean createTextResult) {
if (filterSet.size() == 0) {
return null;
}
initialiseScoring(filterSet);
FilterScoreResult[] scoreResults = new FilterScoreResult[filterSet.size()];
if (scoreResults.length == 1) {
// No need to multi-thread this
scoreResults[0] = scoreFilter((DirectFilter) filterSet.getFilters().get(0), defaultMinimalFilter, createTextResult, coordinateStore);
} else {
// Multi-thread score all the result
final int nThreads = getThreads(scoreResults.length);
final BlockingQueue<ScoreJob> jobs = new ArrayBlockingQueue<>(nThreads * 2);
final List<Thread> threads = new LinkedList<>();
final Ticker ticker = ImageJUtils.createTicker(scoreResults.length, nThreads, "Scoring Filters");
for (int i = 0; i < nThreads; i++) {
final ScoreWorker worker = new ScoreWorker(jobs, scoreResults, createTextResult, (coordinateStore == null) ? null : coordinateStore.newInstance(), ticker);
final Thread t = new Thread(worker);
threads.add(t);
t.start();
}
int index = 0;
for (final Filter filter : filterSet.getFilters()) {
if (IJ.escapePressed()) {
break;
}
put(jobs, new ScoreJob((DirectFilter) filter, index++));
}
// Finish all the worker threads by passing in a null job
for (int i = 0; i < threads.size(); i++) {
put(jobs, new ScoreJob(null, -1));
}
// Wait for all to finish
for (int i = 0; i < threads.size(); i++) {
try {
threads.get(i).join();
} catch (final InterruptedException ex) {
Logger.getLogger(BenchmarkFilterAnalysis.class.getName()).log(Level.WARNING, "Interrupted!", ex);
Thread.currentThread().interrupt();
throw new ConcurrentRuntimeException("Unexpected interruption", ex);
}
}
threads.clear();
ImageJUtils.finished();
// In case the threads were interrupted
if (ImageJUtils.isInterrupted()) {
scoreResults = null;
}
}
finishScoring();
return scoreResults;
}
use of uk.ac.sussex.gdsc.core.logging.Ticker in project GDSC-SMLM by aherbert.
the class BenchmarkFit method runFit.
private void runFit() {
// Initialise the answer.
answer[Gaussian2DFunction.BACKGROUND] = benchmarkParameters.getBackground();
answer[Gaussian2DFunction.SIGNAL] = benchmarkParameters.getSignal();
answer[Gaussian2DFunction.X_POSITION] = benchmarkParameters.x;
answer[Gaussian2DFunction.Y_POSITION] = benchmarkParameters.y;
answer[Gaussian2DFunction.Z_POSITION] = benchmarkParameters.z;
answer[Gaussian2DFunction.X_SD] = benchmarkParameters.sd / benchmarkParameters.pixelPitch;
answer[Gaussian2DFunction.Y_SD] = benchmarkParameters.sd / benchmarkParameters.pixelPitch;
// Set up the fit region. Always round down since 0.5 is the centre of the pixel.
final int x = (int) benchmarkParameters.x;
final int y = (int) benchmarkParameters.y;
region = new Rectangle(x - regionSize, y - regionSize, 2 * regionSize + 1, 2 * regionSize + 1);
if (!new Rectangle(0, 0, imp.getWidth(), imp.getHeight()).contains(region)) {
// Check if it is incorrect by only 1 pixel
if (region.width <= imp.getWidth() + 1 && region.height <= imp.getHeight() + 1) {
ImageJUtils.log("Adjusting region %s to fit within image bounds (%dx%d)", region.toString(), imp.getWidth(), imp.getHeight());
region = new Rectangle(0, 0, imp.getWidth(), imp.getHeight());
} else {
IJ.error(TITLE, "Fit region does not fit within the image");
return;
}
}
// Adjust the centre & account for 0.5 pixel offset during fitting
answer[Gaussian2DFunction.X_POSITION] -= (region.x + 0.5);
answer[Gaussian2DFunction.Y_POSITION] -= (region.y + 0.5);
// Configure for fitting
fitConfig.setBackgroundFitting(backgroundFitting);
fitConfig.setNotSignalFitting(!signalFitting);
fitConfig.setComputeDeviations(false);
// Create the camera model
CameraModel cameraModel = fitConfig.getCameraModel();
// Crop for speed. Reset origin first so the region is within the model
cameraModel.setOrigin(0, 0);
cameraModel = cameraModel.crop(region, false);
final ImageStack stack = imp.getImageStack();
final int totalFrames = benchmarkParameters.frames;
// 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(totalFrames, nThreads, "Fitting frames ...");
for (int i = 0; i < nThreads; i++) {
final Worker worker = new Worker(jobs, stack, region, fitConfig, cameraModel, ticker);
final Thread t = new Thread(worker);
workers.add(worker);
threads.add(t);
t.start();
}
// Store all the fitting results
results = new double[totalFrames * startPoints.length][];
resultsTime = new long[results.length];
// Fit the frames
for (int i = 0; i < totalFrames; i++) {
// Only fit if there were simulated photons
if (benchmarkParameters.framePhotons[i] > 0) {
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);
}
}
threads.clear();
if (hasOffsetXy()) {
ImageJUtils.log(TITLE + ": CoM within start offset = %d / %d (%s%%)", comValid.intValue(), totalFrames, MathUtils.rounded((100.0 * comValid.intValue()) / totalFrames));
}
ImageJUtils.finished("Collecting results ...");
// Collect the results
Statistics[] stats = null;
for (int i = 0; i < workers.size(); i++) {
final Statistics[] next = workers.get(i).stats;
if (stats == null) {
stats = next;
continue;
}
for (int j = 0; j < next.length; j++) {
stats[j].add(next[j]);
}
}
workers.clear();
Objects.requireNonNull(stats, "No statistics were computed");
// Show a table of the results
summariseResults(stats, cameraModel);
// Optionally show histograms
if (showHistograms) {
IJ.showStatus("Calculating histograms ...");
final WindowOrganiser windowOrganiser = new WindowOrganiser();
final double[] convert = getConversionFactors();
final HistogramPlotBuilder builder = new HistogramPlotBuilder(TITLE).setNumberOfBins(histogramBins);
for (int i = 0; i < NAMES.length; i++) {
if (displayHistograms[i] && convert[i] != 0) {
// We will have to convert the values...
final double[] tmp = ((StoredDataStatistics) stats[i]).getValues();
for (int j = 0; j < tmp.length; j++) {
tmp[j] *= convert[i];
}
final StoredDataStatistics tmpStats = StoredDataStatistics.create(tmp);
builder.setData(tmpStats).setName(NAMES[i]).setPlotLabel(String.format("%s +/- %s", MathUtils.rounded(tmpStats.getMean()), MathUtils.rounded(tmpStats.getStandardDeviation()))).show(windowOrganiser);
}
}
windowOrganiser.tile();
}
if (saveRawData) {
final String dir = ImageJUtils.getDirectory("Data_directory", rawDataDirectory);
if (dir != null) {
saveData(stats, dir);
}
}
IJ.showStatus("");
}
use of uk.ac.sussex.gdsc.core.logging.Ticker 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 uk.ac.sussex.gdsc.core.logging.Ticker in project GDSC-SMLM by aherbert.
the class FilterResults method filterResults.
/**
* Apply the filters to the data.
*/
private void filterResults() {
checkLimits();
final MemoryPeakResults newResults = new MemoryPeakResults();
newResults.copySettings(results);
newResults.setName(results.getName() + " Filtered");
// Initialise the mask
CoordFilter maskFilter;
final ImagePlus maskImp = WindowManager.getImage(filterSettings.getMaskTitle());
if (maskImp != null) {
final int maxx = maskImp.getWidth();
final int maxy = maskImp.getHeight();
final Rectangle bounds = results.getBounds();
final double ox = bounds.getX();
final double oy = bounds.getY();
final double scaleX = bounds.getWidth() / maxx;
final double scaleY = bounds.getHeight() / maxy;
// Improve to allow stacks
if (maskImp.getStackSize() > 1) {
// 3D filter. The frame is mapped to the stack index.
final ImageStack stack = maskImp.getImageStack();
final ImageProcessor ip = stack.getProcessor(1);
maskFilter = (t, x, y) -> {
// Check stack index
if (t >= 1 && t <= stack.size()) {
int ix = (int) ((x - ox) / scaleX);
int iy = (int) ((y - oy) / scaleY);
if (ix >= 0 && ix < maxx && iy >= 0 && iy < maxy) {
ip.setPixels(stack.getPixels(t));
return ip.get(iy * maxx + ix) != 0;
}
}
return false;
};
} else {
// 2D filter.
final ImageProcessor ip = maskImp.getProcessor();
maskFilter = (t, x, y) -> {
int ix = (int) ((x - ox) / scaleX);
int iy = (int) ((y - oy) / scaleY);
return (ix >= 0 && ix < maxx && iy >= 0 && iy < maxy && ip.get(iy * maxx + ix) != 0);
};
}
} else {
maskFilter = (t, x, y) -> true;
}
// Create the ticker with size+1 as we tick at the start of the loop
final Ticker ticker = ImageJUtils.createTicker(results.size() + 1, 0);
for (int i = 0, size = results.size(); i < size; i++) {
ticker.tick();
// We stored the drift=z, intensity=signal, background=snr
if (sp.z[i] > filterSettings.getMaxDrift()) {
continue;
}
if (sp.intensity[i] < filterSettings.getMinSignal()) {
continue;
}
if (sp.background[i] < filterSettings.getMinSnr()) {
continue;
}
final PeakResult peakResult = sp.peakResults[i];
// Check the coordinates are inside the mask
if (!maskFilter.match(peakResult.getFrame(), sp.x[i], sp.y[i])) {
continue;
}
if (pp != null && pp.precisions[i] > maxPrecision) {
continue;
}
if (wp != null) {
final float width = wp.wx[i];
if (width < filterSettings.getMinWidth() || width > filterSettings.getMaxWidth()) {
continue;
}
}
// Passed all filters. Add to the results
newResults.add(peakResult);
}
ImageJUtils.finished(TextUtils.pleural(newResults.size(), "Filtered localisation"));
MemoryPeakResults.addResults(newResults);
}
Aggregations