use of uk.ac.sussex.gdsc.smlm.results.procedures.StandardResultProcedure in project GDSC-SMLM by aherbert.
the class DensityImage method plotResults.
/**
* Draw an image of the density for each localisation. Optionally filter results below a
* threshold.
*
* @param results the results
* @param density the density
* @param scoreCalculator the score calculator
* @return the number of localisations drawn
*/
private int plotResults(MemoryPeakResults results, float[] density, ScoreCalculator scoreCalculator) {
// Filter results using 5x higher than average density of the sample in a 150nm radius:
// Annibale, et al (2011). Identification of clustering artifacts in photoactivated localization
// microscopy.
// Nature Methods, 8, pp527-528
MemoryPeakResults newResults = null;
// No filtering
float densityThreshold = Float.NEGATIVE_INFINITY;
if (settings.filterLocalisations) {
densityThreshold = scoreCalculator.getThreshold();
newResults = new MemoryPeakResults();
newResults.copySettings(results);
newResults.setName(results.getName() + " Density Filter");
}
// Draw an image - Use error so that a floating point value can be used on a single pixel
final ImageJImagePeakResults image = ImagePeakResultsFactory.createPeakResultsImage(ResultsImageType.DRAW_INTENSITY, false, false, results.getName() + " Density", results.getBounds(), results.getNmPerPixel(), settings.imageScale, 0, (settings.cumulativeImage) ? ResultsImageMode.IMAGE_ADD : ResultsImageMode.IMAGE_MAX);
image.setDisplayFlags(image.getDisplayFlags() | ImageJImagePeakResults.DISPLAY_NEGATIVES);
image.setLutName("grays");
image.setLiveImage(false);
image.begin();
final StandardResultProcedure sp = new StandardResultProcedure(newResults, DistanceUnit.PIXEL);
sp.getXyr();
for (int i = 0; i < density.length; i++) {
if (density[i] < densityThreshold) {
continue;
}
image.add(sp.x[i], sp.y[i], density[i]);
if (newResults != null) {
newResults.add(sp.peakResults[i]);
}
}
image.end();
// Add to memory
if (newResults != null && newResults.size() > 0) {
MemoryPeakResults.addResults(newResults);
}
return image.size();
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.StandardResultProcedure in project GDSC-SMLM by aherbert.
the class SpotInspector method run.
@Override
public void run(String arg) {
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
if (MemoryPeakResults.isMemoryEmpty()) {
IJ.error(TITLE, "No localisations in memory");
return;
}
if (!showDialog()) {
return;
}
// Load the results
results = ResultsManager.loadInputResults(settings.inputOption, false, DistanceUnit.PIXEL, null);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
IJ.showStatus("");
return;
}
// Check if the original image is open
ImageSource source = results.getSource();
if (source == null) {
IJ.error(TITLE, "Unknown original source image");
return;
}
source = source.getOriginal();
source.setReadHint(ReadHint.NONSEQUENTIAL);
if (!source.open()) {
IJ.error(TITLE, "Cannot open original source image: " + source.toString());
return;
}
final float stdDevMax = getStandardDeviation(results);
if (stdDevMax < 0) {
// TODO - Add dialog to get the initial peak width
IJ.error(TITLE, "Fitting configuration (for initial peak width) is not available");
return;
}
// Rank spots
rankedResults = new ArrayList<>(results.size());
// Data for the sorting
final PrecisionResultProcedure pp;
if (settings.sortOrderIndex == 1) {
pp = new PrecisionResultProcedure(results);
pp.getPrecision();
} else {
pp = null;
}
// Build procedures to get:
// Shift = position in pixels - originXY
final StandardResultProcedure sp;
if (settings.sortOrderIndex == 9) {
sp = new StandardResultProcedure(results, DistanceUnit.PIXEL);
sp.getXyr();
} else {
sp = null;
}
// SD = gaussian widths only for Gaussian PSFs
final WidthResultProcedure wp;
if (settings.sortOrderIndex >= 6 && settings.sortOrderIndex <= 8) {
wp = new WidthResultProcedure(results, DistanceUnit.PIXEL);
wp.getWxWy();
} else {
wp = null;
}
// Amplitude for Gaussian PSFs
final HeightResultProcedure hp;
if (settings.sortOrderIndex == 2) {
hp = new HeightResultProcedure(results, IntensityUnit.PHOTON);
hp.getH();
} else {
hp = null;
}
final Counter c = new Counter();
results.forEach((PeakResultProcedure) result -> {
final float[] score = getScore(result, c.getAndIncrement(), pp, sp, wp, hp, stdDevMax);
rankedResults.add(new PeakResultRank(result, score[0], score[1]));
});
Collections.sort(rankedResults, PeakResultRank::compare);
// Prepare results table
final ImageJTablePeakResults table = new ImageJTablePeakResults(false, results.getName(), true);
table.copySettings(results);
table.setTableTitle(TITLE);
table.setAddCounter(true);
table.setShowZ(results.is3D());
// TODO - Add to settings
table.setShowFittingData(true);
table.setShowNoiseData(true);
if (settings.showCalibratedValues) {
table.setDistanceUnit(DistanceUnit.NM);
table.setIntensityUnit(IntensityUnit.PHOTON);
} else {
table.setDistanceUnit(DistanceUnit.PIXEL);
table.setIntensityUnit(IntensityUnit.COUNT);
}
table.begin();
// Add a mouse listener to jump to the frame for the clicked line
textPanel = table.getResultsWindow().getTextPanel();
// We must ignore old instances of this class from the mouse listeners
id = currentId.incrementAndGet();
textPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent event) {
SpotInspector.this.mouseClicked(event);
}
});
// Add results to the table
int count = 0;
for (final PeakResultRank rank : rankedResults) {
rank.rank = count++;
table.add(rank.peakResult);
}
table.end();
if (settings.plotScore || settings.plotHistogram) {
// Get values for the plots
float[] xValues = null;
float[] yValues = null;
double yMin;
double yMax;
int spotNumber = 0;
xValues = new float[rankedResults.size()];
yValues = new float[xValues.length];
for (final PeakResultRank rank : rankedResults) {
xValues[spotNumber] = spotNumber + 1;
yValues[spotNumber++] = recoverScore(rank.score);
}
// Set the min and max y-values using 1.5 x IQR
final DescriptiveStatistics stats = new DescriptiveStatistics();
for (final float v : yValues) {
stats.addValue(v);
}
if (settings.removeOutliers) {
final double lower = stats.getPercentile(25);
final double upper = stats.getPercentile(75);
final double iqr = upper - lower;
yMin = Math.max(lower - iqr, stats.getMin());
yMax = Math.min(upper + iqr, stats.getMax());
IJ.log(String.format("Data range: %f - %f. Plotting 1.5x IQR: %f - %f", stats.getMin(), stats.getMax(), yMin, yMax));
} else {
yMin = stats.getMin();
yMax = stats.getMax();
IJ.log(String.format("Data range: %f - %f", yMin, yMax));
}
plotScore(xValues, yValues, yMin, yMax);
plotHistogram(yValues);
}
// Extract spots into a stack
final int w = source.getWidth();
final int h = source.getHeight();
final int size = 2 * settings.radius + 1;
final ImageStack spots = new ImageStack(size, size, rankedResults.size());
// To assist the extraction of data from the image source, process them in time order to allow
// frame caching. Then set the appropriate slice in the result stack
Collections.sort(rankedResults, (o1, o2) -> Integer.compare(o1.peakResult.getFrame(), o2.peakResult.getFrame()));
for (final PeakResultRank rank : rankedResults) {
final PeakResult r = rank.peakResult;
// Extract image
// Note that the coordinates are relative to the middle of the pixel (0.5 offset)
// so do not round but simply convert to int
final int x = (int) (r.getXPosition());
final int y = (int) (r.getYPosition());
// Extract a region but crop to the image bounds
int minX = x - settings.radius;
int minY = y - settings.radius;
final int maxX = Math.min(x + settings.radius + 1, w);
final int maxY = Math.min(y + settings.radius + 1, h);
int padX = 0;
int padY = 0;
if (minX < 0) {
padX = -minX;
minX = 0;
}
if (minY < 0) {
padY = -minY;
minY = 0;
}
final int sizeX = maxX - minX;
final int sizeY = maxY - minY;
float[] data = source.get(r.getFrame(), new Rectangle(minX, minY, sizeX, sizeY));
// Prevent errors with missing data
if (data == null) {
data = new float[sizeX * sizeY];
}
ImageProcessor spotIp = new FloatProcessor(sizeX, sizeY, data, null);
// Pad if necessary, i.e. the crop is too small for the stack
if (padX > 0 || padY > 0 || sizeX < size || sizeY < size) {
final ImageProcessor spotIp2 = spotIp.createProcessor(size, size);
spotIp2.insert(spotIp, padX, padY);
spotIp = spotIp2;
}
final int slice = rank.rank + 1;
spots.setPixels(spotIp.getPixels(), slice);
spots.setSliceLabel(MathUtils.rounded(rank.originalScore), slice);
}
source.close();
// Reset to the rank order
Collections.sort(rankedResults, PeakResultRank::compare);
final ImagePlus imp = ImageJUtils.display(TITLE, spots);
imp.setRoi((PointRoi) null);
// Make bigger
for (int i = 10; i-- > 0; ) {
imp.getWindow().getCanvas().zoomIn(imp.getWidth() / 2, imp.getHeight() / 2);
}
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.StandardResultProcedure 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 uk.ac.sussex.gdsc.smlm.results.procedures.StandardResultProcedure in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method createRankByIntensity.
private static float[] createRankByIntensity(MemoryPeakResults results, ImageJ3DResultsViewerSettingsOrBuilder settings) {
final StandardResultProcedure procedure = new StandardResultProcedure(results);
procedure.getI();
final float[] rank = procedure.intensity;
final double gamma = settings.getColourGamma();
// These are the same limits used by ImageJ
if (gamma > 0 && gamma < 5) {
applyGamma(rank, gamma);
}
return rank;
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.StandardResultProcedure in project GDSC-SMLM by aherbert.
the class FilterResults method analyseResults.
/**
* Analyse the results and determine the range for each filter.
*/
private boolean analyseResults() {
IJ.showStatus("Analysing results ...");
final ArrayList<String> error = new ArrayList<>();
try {
wp = new WidthResultProcedure(results, DistanceUnit.PIXEL);
wp.getW();
final float[] limits = MathUtils.limits(wp.wx);
maxWidth = limits[1];
minWidth = limits[0];
averageWidth = MathUtils.sum(wp.wx) / wp.size();
} catch (final DataException ex) {
error.add(ex.getMessage());
wp = null;
maxWidth = minWidth = 0;
}
try {
pp = new PrecisionResultProcedure(results);
pp.getPrecision();
final double[] limits = MathUtils.limits(pp.precisions);
maxPrecision = limits[1];
minPrecision = limits[0];
} catch (final DataException ex) {
error.add(ex.getMessage());
pp = null;
maxPrecision = minPrecision = 0;
}
try {
sp = new StandardResultProcedure(results, DistanceUnit.PIXEL);
sp.getXyr();
// Re-use for convenience
sp.intensity = new float[sp.x.length];
sp.background = new float[sp.x.length];
sp.z = new float[sp.x.length];
for (int i = 0; i < sp.size(); i++) {
if (i % 64 == 0) {
IJ.showProgress(i, sp.size());
}
final PeakResult result = sp.peakResults[i];
final float drift = getDrift(result, sp.x[i], sp.y[i]);
if (maxDrift < drift) {
maxDrift = drift;
}
if (minDrift > drift) {
minDrift = drift;
}
final float signal = result.getIntensity();
if (maxSignal < signal) {
maxSignal = signal;
}
if (minSignal > signal) {
minSignal = signal;
}
final float snr = getSnr(result);
if (maxSnr < snr) {
maxSnr = snr;
}
if (minSnr > snr) {
minSnr = snr;
}
// for convenience
sp.z[i] = drift;
sp.intensity[i] = signal;
sp.background[i] = snr;
}
} catch (final DataException ex) {
error.add(ex.getMessage());
sp = null;
}
if (error.size() == 3 || sp == null) {
final StringBuilder sb = new StringBuilder("Unable to analyse the results:\n");
for (final String s : error) {
sb.append(s).append(".\n");
}
IJ.error(TITLE, sb.toString());
return false;
}
ImageJUtils.finished();
return true;
}
Aggregations