use of ij.ImagePlus in project GDSC-SMLM by aherbert.
the class SpotAnalysis method createProfile.
private void createProfile(ImagePlus imp, Rectangle bounds, double psfWidth, double blur) {
areaBounds = bounds;
this.imp = imp;
area = bounds.width * bounds.height;
clearSelectedFrames();
// Get a profile through the images
IJ.showStatus("Calculating raw profile");
final int nSlices = imp.getStackSize();
ImageStack rawSpot = new ImageStack(bounds.width, bounds.height, nSlices);
double[][] profile = extractSpotProfile(imp, bounds, rawSpot);
// Retain the existing display range
double min = 0, max = Double.POSITIVE_INFINITY;
if (rawImp != null) {
min = rawImp.getDisplayRangeMin();
max = rawImp.getDisplayRangeMax();
}
rawImp = showSpot(rawSpotTitle, rawSpot);
if (max != Double.POSITIVE_INFINITY) {
rawImp.setDisplayRange(min, max);
}
rawMean = profile[0];
rawSd = profile[1];
// Check if there are fitted results in memory
addCandidateFrames(imp.getTitle());
updateProfilePlots();
if (blur > 0) {
IJ.showStatus("Calculating blur ...");
ImageStack stack = imp.getImageStack();
ImageStack newStack = new ImageStack(stack.getWidth(), stack.getHeight(), stack.getSize());
// Multi-thread the blur stage
ExecutorService threadPool = Executors.newFixedThreadPool(Prefs.getThreads());
List<Future<?>> futures = new LinkedList<Future<?>>();
Utils.setShowProgress(false);
blurCount = 0;
// TODO - See if this is faster if processing multiple slices in each worker
int slices = 5;
for (int n = 1; n <= nSlices; n += slices) {
futures.add(threadPool.submit(new BlurWorker(stack, n, slices, bounds, blur * psfWidth, newStack)));
}
IJ.showStatus("Calculating blur ... Finishing");
Utils.waitForCompletion(futures);
threadPool.shutdown();
Utils.setShowProgress(false);
IJ.showStatus("Calculating blur ... Drawing");
ImageStack blurSpot = new ImageStack(bounds.width, bounds.height, nSlices);
extractSpotProfile(new ImagePlus("Blur", newStack), bounds, blurSpot);
// Retain the existing display range
max = Double.POSITIVE_INFINITY;
if (blurImp != null) {
min = blurImp.getDisplayRangeMin();
max = blurImp.getDisplayRangeMax();
}
blurImp = showSpot(blurSpotTitle, blurSpot);
if (max != Double.POSITIVE_INFINITY) {
blurImp.setDisplayRange(min, max);
}
IJ.showStatus("");
} else {
blurImp = null;
}
// Add a z-projection of the blur/original image
ZProjector project = new ZProjector((blurImp == null) ? rawImp : blurImp);
project.setMethod(ZProjector.AVG_METHOD);
project.doProjection();
showSpot(avgSpotTitle, project.getProjection().getImageStack());
if (!candidateFrames.isEmpty())
// Set the first candidate frame
rawImp.setSlice(candidateFrames.get(0));
else
updateCurrentSlice(rawImp.getCurrentSlice());
IJ.showStatus("");
}
use of ij.ImagePlus in project GDSC-SMLM by aherbert.
the class CreateData method getImageHWHM.
/**
* Get the PSF half-width at half-maxima from the Image PSF
*
* @return
*/
private double getImageHWHM() {
ImagePlus imp = WindowManager.getImage(settings.psfImageName);
if (imp == null) {
IJ.error(TITLE, "Unable to create the PSF model from image: " + settings.psfImageName);
return -1;
}
Object o = XmlUtils.fromXML(imp.getProperty("Info").toString());
if (!(o != null && o instanceof PSFSettings)) {
IJ.error(TITLE, "Unknown PSF settings for image: " + imp.getTitle());
return -1;
}
PSFSettings psfSettings = (PSFSettings) o;
if (psfSettings.fwhm <= 0) {
IJ.error(TITLE, "Unknown PSF FWHM setting for image: " + imp.getTitle());
return -1;
}
if (psfSettings.nmPerPixel <= 0) {
IJ.error(TITLE, "Unknown PSF nm/pixel setting for image: " + imp.getTitle());
return -1;
}
// output image
return 0.5 * psfSettings.fwhm * psfSettings.nmPerPixel / settings.pixelPitch;
}
use of ij.ImagePlus 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
* @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();
t1Removed = new AtomicInteger();
tNRemoved = new AtomicInteger();
photonStats = new SummaryStatistics();
// Add drawn spots to memory
results = new MemoryPeakResults();
Calibration c = new Calibration(settings.pixelPitch, settings.getTotalGain(), settings.exposureTime);
c.setEmCCD((settings.getEmGain() > 1));
c.setBias(settings.bias);
c.setReadNoise(settings.readNoise * ((settings.getCameraGain() > 0) ? settings.getCameraGain() : 1));
c.setAmplification(settings.getAmplification());
results.setCalibration(c);
results.setSortAfterEnd(true);
results.begin();
maxT = localisationSets.get(localisationSets.size() - 1).getTime();
// Display image
ImageStack stack = new ImageStack(settings.size, settings.size, maxT);
final double psfSD = getPsfSD();
if (psfSD <= 0)
return null;
ImagePSFModel imagePSFModel = null;
if (imagePSF) {
// Create one Image PSF model that can be copied
imagePSFModel = createImagePSF(localisationSets);
if (imagePSFModel == null)
return null;
}
IJ.showStatus("Drawing image ...");
// Multi-thread for speed
// Note that the default Executors.newCachedThreadPool() will continue to make threads if
// new tasks are added. We need to limit the tasks that can be added using a fixed size
// blocking queue.
// http://stackoverflow.com/questions/1800317/impossible-to-make-a-cached-thread-pool-with-a-size-limit
// ExecutorService threadPool = Executors.newCachedThreadPool();
ExecutorService threadPool = Executors.newFixedThreadPool(Prefs.getThreads());
List<Future<?>> futures = new LinkedList<Future<?>>();
// Count all the frames to process
frame = 0;
totalFrames = maxT;
// Collect statistics on the number of photons actually simulated
// Process all frames
int i = 0;
int lastT = -1;
for (LocalisationModelSet l : localisationSets) {
if (Utils.isInterrupted())
break;
if (l.getTime() != lastT) {
lastT = l.getTime();
futures.add(threadPool.submit(new ImageGenerator(localisationSets, newLocalisations, i, lastT, createPSFModel(imagePSFModel), results, stack, poissonNoise, new RandomDataGenerator(createRandomGenerator()))));
}
i++;
}
// Finish processing data
Utils.waitForCompletion(futures);
futures.clear();
if (Utils.isInterrupted()) {
IJ.showProgress(1);
return null;
}
// Do all the frames that had no localisations
for (int t = 1; t <= maxT; t++) {
if (Utils.isInterrupted())
break;
if (stack.getPixels(t) == null) {
futures.add(threadPool.submit(new ImageGenerator(localisationSets, newLocalisations, maxT, t, null, results, stack, poissonNoise, new RandomDataGenerator(createRandomGenerator()))));
}
}
// Finish
Utils.waitForCompletion(futures);
threadPool.shutdown();
IJ.showProgress(1);
if (Utils.isInterrupted()) {
return null;
}
results.end();
// Clear memory
imagePSFModel = null;
threadPool = null;
futures.clear();
futures = null;
if (photonsRemoved.get() > 0)
Utils.log("Removed %d localisations with less than %.1f rendered photons", photonsRemoved.get(), settings.minPhotons);
if (t1Removed.get() > 0)
Utils.log("Removed %d localisations with no neighbours @ SNR %.2f", t1Removed.get(), settings.minSNRt1);
if (tNRemoved.get() > 0)
Utils.log("Removed %d localisations with valid neighbours @ SNR %.2f", tNRemoved.get(), settings.minSNRtN);
if (photonStats.getN() > 0)
Utils.log("Average photons rendered = %s +/- %s", Utils.rounded(photonStats.getMean()), Utils.rounded(photonStats.getStandardDeviation()));
//System.out.printf("rawPhotons = %f\n", rawPhotons.getMean());
//System.out.printf("drawPhotons = %f\n", drawPhotons.getMean());
//Utils.showHistogram("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.rawImage) {
// Get the global limits and ensure all values can be represented
Object[] imageArray = stack.getImageArray();
float[] limits = Maths.limits((float[]) imageArray[0]);
for (int j = 1; j < imageArray.length; j++) limits = Maths.limits(limits, (float[]) imageArray[j]);
// Leave bias in place
limits[0] = 0;
// Check if the image will fit in a 16-bit range
if ((limits[1] - limits[0]) < 65535) {
// Convert to 16-bit
newStack = new ImageStack(stack.getWidth(), stack.getHeight(), stack.getSize());
// Account for rounding
final float min = (float) (limits[0] - 0.5);
for (int j = 0; j < imageArray.length; j++) {
float[] image = (float[]) imageArray[j];
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 (MemoryPeakResults.freeMemory() < 33554432L)
MemoryPeakResults.runGCOnce();
}
} else {
// Keep as 32-bit but round to whole numbers
for (int j = 0; j < imageArray.length; j++) {
float[] pixels = (float[]) imageArray[j];
for (int k = 0; k < pixels.length; k++) {
pixels[k] = Math.round(pixels[k]);
}
}
}
}
// Show image
ImagePlus imp = Utils.display(CREATE_DATA_IMAGE_TITLE, newStack);
ij.measure.Calibration cal = new ij.measure.Calibration();
String unit = "nm";
double unitPerPixel = settings.pixelPitch;
if (unitPerPixel > 100) {
unit = "um";
unitPerPixel /= 1000.0;
}
cal.setUnit(unit);
cal.pixelHeight = cal.pixelWidth = unitPerPixel;
imp.setCalibration(cal);
imp.setDimensions(1, 1, newStack.getSize());
imp.resetDisplayRange();
imp.updateAndDraw();
saveImage(imp);
results.setSource(new IJImageSource(imp));
results.setName(CREATE_DATA_IMAGE_TITLE + " (" + TITLE + ")");
results.setConfiguration(createConfiguration((float) psfSD));
results.setBounds(new Rectangle(0, 0, settings.size, settings.size));
MemoryPeakResults.addResults(results);
setBenchmarkResults(imp, results);
if (benchmarkMode && benchmarkParameters != null)
benchmarkParameters.setPhotons(results);
List<LocalisationModel> localisations = toLocalisations(localisationSets);
savePulses(localisations, results, CREATE_DATA_IMAGE_TITLE);
// Saved the fixed and moving localisations into different datasets
saveFixedAndMoving(results, CREATE_DATA_IMAGE_TITLE);
return localisations;
}
use of ij.ImagePlus in project GDSC-SMLM by aherbert.
the class CreateData method loadBenchmarkData.
/**
* Load benchmark data using an open image and a XYZ text file.
*/
private void loadBenchmarkData() {
if (!showLoadDialog()) {
//resetMemory();
return;
}
// Load the image
ImagePlus imp = WindowManager.getImage(benchmarkImage);
if (imp == null) {
IJ.error(TITLE, "No benchmark image: " + benchmarkImage);
//resetMemory();
return;
}
// Load the results
MemoryPeakResults results = getSimulationResults();
if (results == null) {
IJ.error(TITLE, "No benchmark results: " + benchmarkResultsName);
//resetMemory();
return;
}
results.setName(imp.getTitle() + " (Results)");
results.setBounds(new Rectangle(0, 0, imp.getWidth(), imp.getHeight()));
results.setSource(new IJImageSource(imp));
// Get the calibration
simulationParameters = showSimulationParametersDialog(imp, results);
if (simulationParameters != null) {
setBackground(results);
setNoise(results, imp);
setBenchmarkResults(imp, results);
IJ.showStatus("Loaded " + Utils.pleural(results.size(), "result"));
} else {
resetMemory();
}
}
use of ij.ImagePlus in project GDSC-SMLM by aherbert.
the class CMOSAnalysis method simulate.
private void simulate() {
// Create the offset, variance and gain for each pixel
int n = size * size;
float[] pixelOffset = new float[n];
float[] pixelVariance = new float[n];
float[] pixelGain = new float[n];
IJ.showStatus("Creating random per-pixel readout");
long start = System.currentTimeMillis();
RandomGenerator rg = new Well19937c();
PoissonDistribution pd = new PoissonDistribution(rg, offset, PoissonDistribution.DEFAULT_EPSILON, PoissonDistribution.DEFAULT_MAX_ITERATIONS);
ExponentialDistribution ed = new ExponentialDistribution(rg, variance, ExponentialDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
totalProgress = n;
stepProgress = Utils.getProgressInterval(totalProgress);
for (int i = 0; i < n; i++) {
if (i % n == 0)
IJ.showProgress(i, n);
// Q. Should these be clipped to a sensible range?
pixelOffset[i] = (float) pd.sample();
pixelVariance[i] = (float) ed.sample();
pixelGain[i] = (float) (gain + rg.nextGaussian() * gainSD);
}
IJ.showProgress(1);
// Avoid all the file saves from updating the progress bar and status line
Utils.setShowStatus(false);
Utils.setShowProgress(false);
JLabel statusLine = Utils.getStatusLine();
progressBar = Utils.getProgressBar();
// Save to the directory as a stack
ImageStack simulationStack = new ImageStack(size, size);
simulationStack.addSlice("Offset", pixelOffset);
simulationStack.addSlice("Variance", pixelVariance);
simulationStack.addSlice("Gain", pixelGain);
simulationImp = new ImagePlus("PerPixel", simulationStack);
// Only the info property is saved to the TIFF file
simulationImp.setProperty("Info", String.format("Offset=%s; Variance=%s; Gain=%s +/- %s", Utils.rounded(offset), Utils.rounded(variance), Utils.rounded(gain), Utils.rounded(gainSD)));
IJ.save(simulationImp, new File(directory, "perPixelSimulation.tif").getPath());
// Create thread pool and workers
ExecutorService executor = Executors.newFixedThreadPool(getThreads());
TurboList<Future<?>> futures = new TurboList<Future<?>>(nThreads);
// Simulate the zero exposure input.
// Simulate 20 - 200 photon images.
int[] photons = new int[] { 0, 20, 50, 100, 200 };
totalProgress = photons.length * frames;
stepProgress = Utils.getProgressInterval(totalProgress);
progress = 0;
progressBar.show(0);
// For saving stacks
int blockSize = 10;
int nPerThread = (int) Math.ceil((double) frames / nThreads);
// Convert to fit the block size
nPerThread = (int) Math.ceil((double) nPerThread / blockSize) * blockSize;
long seed = start;
for (int p : photons) {
statusLine.setText("Simulating " + Utils.pleural(p, "photon"));
// Create the directory
File out = new File(directory, String.format("photon%03d", p));
if (!out.exists())
out.mkdir();
for (int from = 0; from < frames; ) {
int to = Math.min(from + nPerThread, frames);
futures.add(executor.submit(new SimulationWorker(seed++, out.getPath(), simulationStack, from, to, blockSize, p)));
from = to;
}
// Wait for all to finish
for (int t = futures.size(); t-- > 0; ) {
try {
// The future .get() method will block until completed
futures.get(t).get();
} catch (Exception e) {
// This should not happen.
e.printStackTrace();
}
}
futures.clear();
}
Utils.setShowStatus(true);
Utils.setShowProgress(true);
IJ.showProgress(1);
executor.shutdown();
Utils.log("Simulation time = " + Utils.timeToString(System.currentTimeMillis() - start));
}
Aggregations