use of uk.ac.sussex.gdsc.smlm.results.count.Counter in project GDSC-SMLM by aherbert.
the class SplitResults method splitResults.
private void splitResults(MemoryPeakResults results, ImageProcessor ip) {
IJ.showStatus("Splitting " + TextUtils.pleural(results.size(), "result"));
// Create an object mask
final ObjectAnalyzer objectAnalyzer = new ObjectAnalyzer(ip, false);
final int maxx = ip.getWidth();
final int maxy = ip.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;
// Create a results set for each object
final int maxObject = objectAnalyzer.getMaxObject();
final MemoryPeakResults[] resultsSet = new MemoryPeakResults[maxObject + 1];
for (int object = 0; object <= maxObject; object++) {
final MemoryPeakResults newResults = new MemoryPeakResults();
newResults.copySettings(results);
newResults.setName(results.getName() + " " + object);
resultsSet[object] = newResults;
}
final int[] mask = objectAnalyzer.getObjectMask();
if (settings.showObjectMask) {
final ImageProcessor objectIp = (maxObject <= 255) ? new ByteProcessor(maxx, maxy) : new ShortProcessor(maxx, maxy);
for (int i = 0; i < mask.length; i++) {
objectIp.set(i, mask[i]);
}
final ImagePlus imp = ImageJUtils.display(settings.objectMask + " Objects", objectIp);
imp.setDisplayRange(0, maxObject);
imp.updateAndDraw();
}
// Process the results mapping them to their objects
final Counter i = new Counter();
final int size = results.size();
final int step = ImageJUtils.getProgressInterval(size);
results.forEach(DistanceUnit.PIXEL, (XyrResultProcedure) (xx, yy, result) -> {
if (i.incrementAndGet() % step == 0) {
IJ.showProgress(i.getCount(), size);
}
// Map to the mask objects
final int object;
final int x = (int) ((xx - ox) / scaleX);
final int y = (int) ((yy - oy) / scaleY);
if (x < 0 || x >= maxx || y < 0 || y >= maxy) {
object = 0;
} else {
final int index = y * maxx + x;
// is within the bounds of the image processor?
if (index < 0 || index >= mask.length) {
object = 0;
} else {
object = mask[index];
}
}
resultsSet[object].add(result);
});
IJ.showProgress(1);
// Add the new results sets to memory
i.reset();
for (int object = (settings.nonMaskDataset) ? 0 : 1; object <= maxObject; object++) {
if (resultsSet[object].isNotEmpty()) {
MemoryPeakResults.addResults(resultsSet[object]);
i.increment();
}
}
IJ.showStatus("Split " + TextUtils.pleural(results.size(), "result") + " into " + TextUtils.pleural(i.getCount(), "set"));
}
use of uk.ac.sussex.gdsc.smlm.results.count.Counter 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.count.Counter in project GDSC-SMLM by aherbert.
the class TraceExporter method exportAnaDda.
@SuppressWarnings("resource")
private void exportAnaDda(MemoryPeakResults results) {
// anaDDA list of tracked localisations file format:
// https://github.com/HohlbeinLab/anaDDA
// Matlab matrix file.
// 5 columns for n rows of localisations
// 1. x coordinate (μm)
// 2. y coordinate (μm)
// 3. frame number
// 4. track id
// 5. frame time (s)
// Count the number of localisations including start/end frames
final Counter row = new Counter();
results.forEach((PeakResultProcedure) result -> {
row.increment(getLength(result));
});
// Create the matrix
final int rows = row.getCount();
final Matrix out = Mat5.newMatrix(rows, 5);
// Set up column offsets
final int col1 = rows * 1;
final int col2 = rows * 2;
final int col3 = rows * 3;
final int col4 = rows * 4;
// Frame time in seconds. This is not the frame time point converted to seconds
// but the exposure duration of the frame.
final double frameTime = results.getCalibrationReader().getExposureTime() / 1000;
row.reset();
results.forEach(DistanceUnit.UM, (XyrResultProcedure) (x, y, result) -> {
if (result.hasEndFrame()) {
for (int t = result.getFrame(); t <= result.getEndFrame(); t++) {
final int index = row.getAndIncrement();
out.setDouble(index, x);
out.setDouble(index + col1, y);
out.setDouble(index + col2, t);
out.setDouble(index + col3, result.getId());
out.setDouble(index + col4, frameTime);
}
} else {
// Column major index: row + rows * col
final int index = row.getAndIncrement();
out.setDouble(index, x);
out.setDouble(index + col1, y);
out.setDouble(index + col2, result.getFrame());
out.setDouble(index + col3, result.getId());
out.setDouble(index + col4, frameTime);
}
});
try (MatFile matFile = Mat5.newMatFile()) {
matFile.addArray("tracks", out);
Mat5.writeToFile(matFile, Paths.get(settings.directory, results.getName() + ".mat").toFile());
} catch (final IOException ex) {
handleException(ex);
}
}
use of uk.ac.sussex.gdsc.smlm.results.count.Counter in project GDSC-SMLM by aherbert.
the class AstigmatismModelManager method plotData.
private boolean plotData() {
if (results.size() <= imp.getStackSize() / 2) {
IJ.error(TITLE, "Not enough fit results " + results.size());
return false;
}
final double umPerSlice = pluginSettings.getNmPerSlice() / 1000.0;
// final double nmPerPixel = results.getNmPerPixel();
z = new double[results.size()];
x = new double[z.length];
y = new double[z.length];
intensity = new double[z.length];
final Counter counter = new Counter();
// We have fit the results so they will be in the preferred units
results.forEach(new PeakResultProcedure() {
@Override
public void execute(PeakResult peak) {
final int i = counter.getAndIncrement();
z[i] = peak.getFrame() * umPerSlice;
x[i] = (peak.getXPosition() - cx);
y[i] = (peak.getYPosition() - cy);
intensity[i] = peak.getIntensity();
}
});
final WidthResultProcedure wp = new WidthResultProcedure(results, DistanceUnit.PIXEL);
wp.getWxWy();
sx = SimpleArrayUtils.toDouble(wp.wx);
sy = SimpleArrayUtils.toDouble(wp.wy);
final WindowOrganiser wo = new WindowOrganiser();
plot(wo, z, "Intensity (photon)", intensity, "Intensity", null, null);
xyPlot = plot(wo, z, "Position (px)", x, "X", y, "Y");
widthPlot = plot(wo, z, "Width (px)", sx, "Sx", sy, "Sy");
wo.tile();
return true;
}
use of uk.ac.sussex.gdsc.smlm.results.count.Counter in project GDSC-SMLM by aherbert.
the class FilterAnalysis method showDialog.
private boolean showDialog(List<MemoryPeakResults> resultsList, boolean fileInput) {
final GenericDialog gd = new GenericDialog(TITLE);
String helpKey = "filter-analysis";
if (fileInput) {
helpKey += "-file";
}
gd.addHelp(HelpUrls.getUrl(helpKey));
int total = 0;
final Counter tp = new Counter();
for (final MemoryPeakResults r : resultsList) {
total += r.size();
r.forEach((PeakResultProcedure) result -> {
if (result.getOrigValue() != 0) {
tp.increment();
}
});
}
ImageJUtils.addMessage(gd, "%d files, %d results, %d True-Positives", resultsList.size(), total, tp.getCount());
settings = Settings.load();
settings.save();
if (!fileInput) {
gd.addCheckbox("SNR_filter", settings.snrFilter);
gd.addNumericField("Min_SNR", settings.minSnr, 0);
gd.addNumericField("Max_SNR", settings.maxSnr, 0);
gd.addNumericField("Min_Width", settings.minWidth, 2);
gd.addNumericField("Max_Width", settings.maxWidth, 2);
gd.addNumericField("Increment_Width", settings.incWidth, 2);
gd.addCheckbox("Precision_filter", settings.precisionFilter);
gd.addNumericField("Min_Precision", settings.minPrecision, 0);
gd.addNumericField("Max_Precision", settings.maxPrecision, 0);
gd.addCheckbox("Trace_filter", settings.traceFilter);
gd.addNumericField("Min_distance", settings.minDistance, 2);
gd.addNumericField("Max_distance", settings.maxDistance, 2);
gd.addNumericField("Increment_distance", settings.incDistance, 2);
gd.addNumericField("Min_time", settings.minTime, 0);
gd.addNumericField("Max_time", settings.maxTime, 0);
gd.addNumericField("Increment_time", settings.incTime, 0);
gd.addCheckbox("Hysteresis_SNR_filter", settings.hysteresisSnrFilter);
gd.addNumericField("Min_SNR_gap", settings.minSnrGap, 0);
gd.addNumericField("Max_SNR_gap", settings.maxSnrGap, 0);
gd.addNumericField("Increment_SNR_gap", settings.incSnrGap, 0);
gd.addCheckbox("Hysteresis_Precision_filter", settings.hysteresisPrecisionFilter);
gd.addNumericField("Min_Precision_gap", settings.minPrecisionGap, 0);
gd.addNumericField("Max_Precision_gap", settings.maxPrecisionGap, 0);
gd.addNumericField("Increment_Precision_gap", settings.incPrecisionGap, 0);
gd.addCheckbox("Save_filters", settings.saveFilterSets);
}
gd.addCheckbox("Show_table", settings.showResultsTable);
gd.addSlider("Plot_top_n", 0, 20, settings.plotTopN);
gd.addCheckbox("Calculate_sensitivity", settings.calculateSensitivity);
gd.addSlider("Delta", 0.01, 1, settings.delta);
gd.showDialog();
return !gd.wasCanceled() && readDialog(gd, fileInput);
}
Aggregations