use of ij.ImageStack in project GDSC-SMLM by aherbert.
the class SpotInspector method run.
/*
* (non-Javadoc)
*
* @see ij.plugin.PlugIn#run(java.lang.String)
*/
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(inputOption, false);
if (results == null || results.size() == 0) {
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();
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<PeakResultRank>(results.size());
final double a = results.getNmPerPixel();
final double gain = results.getGain();
final boolean emCCD = results.isEMCCD();
for (PeakResult r : results.getResults()) {
float[] score = getScore(r, a, gain, emCCD, stdDevMax);
rankedResults.add(new PeakResultRank(r, score[0], score[1]));
}
Collections.sort(rankedResults);
// Prepare results table. Get bias if necessary
if (showCalibratedValues) {
// Get a bias if required
Calibration calibration = results.getCalibration();
if (calibration.getBias() == 0) {
ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addMessage("Calibrated results requires a camera bias");
gd.addNumericField("Camera_bias (ADUs)", calibration.getBias(), 2);
gd.showDialog();
if (!gd.wasCanceled()) {
calibration.setBias(Math.abs(gd.getNextNumber()));
}
}
}
IJTablePeakResults table = new IJTablePeakResults(false, results.getName(), true);
table.copySettings(results);
table.setTableTitle(TITLE);
table.setAddCounter(true);
table.setShowCalibratedValues(showCalibratedValues);
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;
textPanel.addMouseListener(this);
// Add results to the table
int n = 0;
for (PeakResultRank rank : rankedResults) {
rank.rank = n++;
PeakResult r = rank.peakResult;
table.add(r.getFrame(), r.origX, r.origY, r.origValue, r.error, r.noise, r.params, r.paramsStdDev);
}
table.end();
if (plotScore || plotHistogram) {
// Get values for the plots
float[] xValues = null, yValues = null;
double yMin, yMax;
int spotNumber = 0;
xValues = new float[rankedResults.size()];
yValues = new float[xValues.length];
for (PeakResultRank rank : rankedResults) {
xValues[spotNumber] = spotNumber + 1;
yValues[spotNumber++] = recoverScore(rank.score);
}
// Set the min and max y-values using 1.5 x IQR
DescriptiveStatistics stats = new DescriptiveStatistics();
for (float v : yValues) stats.addValue(v);
if (removeOutliers) {
double lower = stats.getPercentile(25);
double upper = stats.getPercentile(75);
double iqr = upper - lower;
yMin = FastMath.max(lower - iqr, stats.getMin());
yMax = FastMath.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, yMin, yMax);
}
// Extract spots into a stack
final int w = source.getWidth();
final int h = source.getHeight();
final int size = 2 * radius + 1;
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, new Comparator<PeakResultRank>() {
public int compare(PeakResultRank o1, PeakResultRank o2) {
if (o1.peakResult.getFrame() < o2.peakResult.getFrame())
return -1;
if (o1.peakResult.getFrame() > o2.peakResult.getFrame())
return 1;
return 0;
}
});
for (PeakResultRank rank : rankedResults) {
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.params[Gaussian2DFunction.X_POSITION]);
final int y = (int) (r.params[Gaussian2DFunction.Y_POSITION]);
// Extract a region but crop to the image bounds
int minX = x - radius;
int minY = y - radius;
int maxX = FastMath.min(x + radius + 1, w);
int maxY = FastMath.min(y + radius + 1, h);
int padX = 0, padY = 0;
if (minX < 0) {
padX = -minX;
minX = 0;
}
if (minY < 0) {
padY = -minY;
minY = 0;
}
int sizeX = maxX - minX;
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) {
ImageProcessor spotIp2 = spotIp.createProcessor(size, size);
spotIp2.insert(spotIp, padX, padY);
spotIp = spotIp2;
}
int slice = rank.rank + 1;
spots.setPixels(spotIp.getPixels(), slice);
spots.setSliceLabel(Utils.rounded(rank.originalScore), slice);
}
source.close();
ImagePlus imp = Utils.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 ij.ImageStack in project GDSC-SMLM by aherbert.
the class YeastMask method createMask.
private void createMask() {
// Create the dimensions
final int hw = (int) Math.ceil(radius * 1000 / nmPerPixel);
final int hd = (int) Math.ceil(radius * 1000 / nmPerSlice);
final int width = 2 * hw + 1;
final int depth = 2 * hd + 1;
ImageStack stack = createHemiSphere(width, depth);
// Extend the centre circle of the sphere into a tube of the required length
final int h = (int) Math.ceil(length * 1000 / nmPerPixel);
if (h > 0) {
ImageStack newStack = new ImageStack(width, stack.getHeight() + h, stack.getSize());
for (int slice = 1; slice <= stack.getSize(); slice++) {
byte[] pixels = (byte[]) stack.getPixels(slice);
byte[] newPixels = new byte[width * newStack.getHeight()];
newStack.setPixels(newPixels, slice);
System.arraycopy(pixels, 0, newPixels, 0, pixels.length);
// Get the final strip to be extended
final int offset = pixels.length - width;
int target = pixels.length;
for (int i = 0; i < h; i++) {
System.arraycopy(pixels, offset, newPixels, target, width);
target += width;
}
}
stack = newStack;
}
// Copy the hemi-sphere onto the end
ImageStack newStack = new ImageStack(width, stack.getHeight() + hw, stack.getSize());
for (int slice = 1; slice <= stack.getSize(); slice++) {
byte[] pixels = (byte[]) stack.getPixels(slice);
byte[] newPixels = new byte[width * newStack.getHeight()];
newStack.setPixels(newPixels, slice);
System.arraycopy(pixels, 0, newPixels, 0, pixels.length);
// Copy the hemi-sphere
int source = 0;
int target = newPixels.length - width;
for (int i = 0; i < hw; i++) {
System.arraycopy(pixels, source, newPixels, target, width);
target -= width;
source += width;
}
}
stack = newStack;
if (excludeNucleus) {
ImageStack stack2 = createNucleusSphere(width, depth);
int xloc = (stack.getWidth() - stack2.getWidth()) / 2;
int yloc = (stack.getHeight() - stack2.getHeight()) / 2;
int offset = (stack.getSize() - stack2.getSize()) / 2;
for (int slice = 1; slice <= stack2.getSize(); slice++) {
ImageProcessor ip = stack.getProcessor(slice + offset);
ImageProcessor ip2 = stack2.getProcessor(slice);
ip.copyBits(ip2, xloc, yloc, Blitter.SUBTRACT);
}
}
if (squareOutput && stack.getWidth() != stack.getHeight()) {
ImageStack stack2 = new ImageStack(stack.getHeight(), stack.getHeight());
int end = stack.getHeight() - stack.getWidth();
for (int slice = 1; slice <= stack.getSize(); slice++) {
ImageProcessor ip = stack.getProcessor(slice);
ImageProcessor ip2 = new ByteProcessor(stack2.getWidth(), stack2.getHeight());
stack2.addSlice(ip2);
for (int xloc = 0; xloc <= end; xloc += stack.getWidth()) {
ip2.insert(ip, xloc, 0);
}
}
stack = stack2;
}
if (border > 0) {
ImageStack stack2 = new ImageStack(stack.getWidth() + 2 * border, stack.getHeight() + 2 * border);
for (int slice = 1; slice <= stack.getSize(); slice++) {
ImageProcessor ip = stack.getProcessor(slice);
ImageProcessor ip2 = new ByteProcessor(stack2.getWidth(), stack2.getHeight());
stack2.addSlice(ip2);
ip2.insert(ip, border, border);
}
stack = stack2;
}
ImagePlus imp;
if (is2D) {
// TODO - Remove this laziness since we should really just do a 2D image
int centre = stack.getSize() / 2;
imp = Utils.display(TITLE, stack.getProcessor(centre));
} else {
imp = Utils.display(TITLE, stack);
}
// Calibrate
Calibration cal = new Calibration();
cal.setUnit("um");
cal.pixelWidth = cal.pixelHeight = nmPerPixel / 1000;
cal.pixelDepth = nmPerSlice / 1000;
imp.setCalibration(cal);
}
use of ij.ImageStack in project GDSC-SMLM by aherbert.
the class YeastMask method createHemiSphere.
/**
* Create a hemi-sphere using the given pixel width and stack depth using the original cell radius
*
* @param width
* @param depth
* @return A hemi-sphere
*/
private ImageStack createHemiSphere(int width, int depth) {
// Create a sphere. This could be done exploiting symmetry to be more efficient
// but is left as a simple implementation
final double centreX = width * 0.5;
final double centreZ = depth * 0.5;
// Precompute squares for the width
double[] s = new double[width];
for (int iy = 0; iy < width; iy++) {
final double y = (centreX - (iy + 0.5)) * nmPerPixel;
s[iy] = y * y;
}
final int halfHeight = 1 + width / 2;
ImageStack stack = new ImageStack(width, halfHeight, depth);
final byte on = (byte) 255;
final double r = radius * 1000;
final double r2 = r * r;
for (int iz = 0; iz < depth; iz++) {
final double z = (centreZ - (iz + 0.5)) * nmPerSlice;
final double z2 = z * z;
byte[] mask = new byte[width * halfHeight];
for (int iy = 0, i = 0; iy < halfHeight; iy++) {
final double y2z2 = s[iy] + z2;
for (int ix = 0; ix < width; ix++, i++) {
final double d2 = s[ix] + y2z2;
if (d2 < r2)
mask[i] = on;
}
}
stack.setPixels(mask, iz + 1);
}
return stack;
}
use of ij.ImageStack in project GDSC-SMLM by aherbert.
the class TraceMolecules method buildCombinedImage.
private float[] buildCombinedImage(ImageSource source, Trace trace, float fitWidth, Rectangle bounds, double[] combinedNoise, boolean createStack) {
final int w = source.getWidth();
final int h = source.getHeight();
// Get the coordinates and the spot bounds
float[] centre = trace.getCentroid(CentroidMethod.SIGNAL_WEIGHTED);
int minX = (int) Math.floor(centre[0] - fitWidth);
int maxX = (int) Math.ceil(centre[0] + fitWidth);
int minY = (int) Math.floor(centre[1] - fitWidth);
int maxY = (int) Math.ceil(centre[1] + fitWidth);
// Account for crops at the edge of the image
minX = FastMath.max(0, minX);
maxX = FastMath.min(w, maxX);
minY = FastMath.max(0, minY);
maxY = FastMath.min(h, maxY);
int width = maxX - minX;
int height = maxY - minY;
if (width <= 0 || height <= 0) {
// The centre must be outside the image width and height
return null;
}
bounds.x = minX;
bounds.y = minY;
bounds.width = width;
bounds.height = height;
if (createStack)
slices = new ImageStack(width, height);
// Combine the images. Subtract the fitted background to zero the image.
float[] data = new float[width * height];
float sumBackground = 0;
double noise = 0;
for (PeakResult result : trace.getPoints()) {
noise += result.noise * result.noise;
float[] sourceData = source.get(result.getFrame(), bounds);
final float background = result.getBackground();
sumBackground += background;
for (int i = 0; i < data.length; i++) {
data[i] += sourceData[i] - background;
}
if (createStack)
slices.addSlice(new FloatProcessor(width, height, sourceData, null));
}
if (createStack) {
// Add a final image that is the average of the individual slices. This allows
// it to be visualised in the same intensity scale.
float[] data2 = Arrays.copyOf(data, data.length);
final int size = slices.getSize();
sumBackground /= size;
for (int i = 0; i < data2.length; i++) data2[i] = sumBackground + data2[i] / size;
slices.addSlice(new FloatProcessor(width, height, data2, null));
}
// Combined noise is the sqrt of the sum-of-squares
combinedNoise[0] = Math.sqrt(noise);
return data;
}
Aggregations