use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure in project GDSC-SMLM by aherbert.
the class PeakResultsReaderTest method canReadAndSimplifyGaussian2DPsf.
private static void canReadAndSimplifyGaussian2DPsf(RandomSeed seed, ResultsFileFormat fileFormat) {
final UniformRandomProvider rg = RngUtils.create(seed.getSeed());
final MemoryPeakResults out = createResults(rg, 1, false, false, false, false, false);
final CalibrationWriter cal = new CalibrationWriter(out.getCalibration());
cal.setDistanceUnit(MemoryPeakResults.PREFERRED_DISTANCE_UNIT);
cal.setIntensityUnit(MemoryPeakResults.PREFERRED_INTENSITY_UNIT);
cal.setAngleUnit(MemoryPeakResults.PREFERRED_ANGLE_UNIT);
if (fileFormat == ResultsFileFormat.TSF) {
// For now just support using the native float TSF value
cal.setNmPerPixel((float) cal.getNmPerPixel());
}
out.setCalibration(cal.getCalibration());
// Remove angle
final int ia = PsfHelper.getGaussian2DAngleIndex(out.getPsf());
out.forEach(new PeakResultProcedure() {
@Override
public void execute(PeakResult peakResult) {
peakResult.getParameters()[ia] = 0;
}
});
final String filename = createFile();
writeFile(false, fileFormat, false, false, false, false, false, false, out, filename);
MemoryPeakResults in = readFile(filename, false, false);
// Change to two-axis PSF
out.setPsf(PsfHelper.create(PSFType.TWO_AXIS_GAUSSIAN_2D));
final int twoAxisLength = PsfHelper.getParameterCount(out.getPsf()) + PeakResult.STANDARD_PARAMETERS;
out.forEach(new PeakResultProcedure() {
@Override
public void execute(PeakResult peakResult) {
peakResult.resizeParameters(twoAxisLength);
}
});
checkEqual(fileFormat, false, false, false, false, false, false, out, in);
// Remove sy
final int[] indices = PsfHelper.getGaussian2DWxWyIndices(out.getPsf());
final int isx = indices[0];
final int isy = indices[1];
out.forEach(new PeakResultProcedure() {
@Override
public void execute(PeakResult peakResult) {
final float[] p = peakResult.getParameters();
p[isy] = p[isx];
}
});
writeFile(false, fileFormat, false, false, false, false, false, false, out, filename);
in = readFile(filename, false, false);
// Change to one-axis PSF
out.setPsf(PsfHelper.create(PSFType.ONE_AXIS_GAUSSIAN_2D));
final int oneAxisLength = PsfHelper.getParameterCount(out.getPsf()) + PeakResult.STANDARD_PARAMETERS;
out.forEach(new PeakResultProcedure() {
@Override
public void execute(PeakResult peakResult) {
peakResult.resizeParameters(oneAxisLength);
}
});
checkEqual(fileFormat, false, false, false, false, false, false, out, in);
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure 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.PeakResultProcedure 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.procedures.PeakResultProcedure in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method getCoordinates.
/**
* Build a map between the peak id (time point) and a list of coordinates.
*
* @param results the results
* @param coordinateMethod the coordinate method
* @param integerCoordinates True if the values should be rounded down to integers
* @return the coordinates
*/
public static TIntObjectHashMap<List<Coordinate>> getCoordinates(MemoryPeakResults results, CoordinateMethod coordinateMethod, final boolean integerCoordinates) {
final TIntObjectHashMap<List<Coordinate>> coords = new TIntObjectHashMap<>();
if (results.size() > 0) {
// Do not use HashMap directly to build the coords object since there
// will be many calls to getEntry(). Instead sort the results and use
// a new list for each time point
results.sort();
final int minT = results.getFirstFrame();
final int maxT = results.getLastFrame();
// Create lists
final ArrayList<ArrayList<Coordinate>> tmpCoords = new ArrayList<>(maxT - minT + 1);
for (int t = minT; t <= maxT; t++) {
tmpCoords.add(new ArrayList<Coordinate>());
}
// Add the results to the lists
results.forEach((PeakResultProcedure) result -> {
final float x;
final float y;
final float z;
if (integerCoordinates) {
x = (int) result.getXPosition();
y = (int) result.getYPosition();
z = (int) result.getZPosition();
} else {
x = result.getXPosition();
y = result.getYPosition();
z = result.getZPosition();
}
final int startFrame = getStartFrame(result, coordinateMethod);
final int endFrame = getEndFrame(result, coordinateMethod);
for (int t = startFrame - minT, i = endFrame - startFrame + 1; i-- > 0; t++) {
tmpCoords.get(t).add(new PeakResultPoint(t + minT, x, y, z, result));
}
});
// Put in the map
for (int t = minT, i = 0; t <= maxT; t++, i++) {
coords.put(t, tmpCoords.get(i));
}
}
return coords;
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method getIds.
private static TIntHashSet getIds(MemoryPeakResults results) {
final TIntHashSet ids = new TIntHashSet(results.size());
results.forEach((PeakResultProcedure) result -> ids.add(result.getId()));
return ids;
}
Aggregations