use of gdsc.core.utils.Statistics in project GDSC-SMLM by aherbert.
the class CreateData method showSummary.
private double showSummary(List<? extends FluorophoreSequenceModel> fluorophores, List<LocalisationModel> localisations) {
IJ.showStatus("Calculating statistics ...");
createSummaryTable();
Statistics[] stats = new Statistics[NAMES.length];
for (int i = 0; i < stats.length; i++) {
stats[i] = (settings.showHistograms || alwaysRemoveOutliers[i]) ? new StoredDataStatistics() : new Statistics();
}
// Find the largest timepoint
ImagePlus outputImp = WindowManager.getImage(benchmarkImageId);
int nFrames;
if (outputImp == null) {
sortLocalisationsByTime(localisations);
nFrames = localisations.get(localisations.size() - 1).getTime();
} else {
nFrames = outputImp.getStackSize();
}
int[] countHistogram = new int[nFrames + 1];
// Use the localisations that were drawn to create the sampled on/off times
rebuildNeighbours(localisations);
// Assume that there is at least one localisation
LocalisationModel first = localisations.get(0);
// The current localisation
int currentId = first.getId();
// The last time this localisation was on
int lastT = first.getTime();
// Number of blinks
int blinks = 0;
// On-time of current pulse
int currentT = 0;
double signal = 0;
final double centreOffset = settings.size * 0.5;
// Used to convert the sampled times in frames into seconds
final double framesPerSecond = 1000.0 / settings.exposureTime;
final double gain = (settings.getTotalGain() > 0) ? settings.getTotalGain() : 1;
for (LocalisationModel l : localisations) {
if (l.getData() == null)
System.out.println("No localisation data. This should not happen!");
final double noise = (l.getData() != null) ? l.getData()[1] : 1;
final double intensity = (l.getData() != null) ? l.getData()[4] : l.getIntensity();
final double intensityInPhotons = intensity / gain;
// Q. What if the noise is zero, i.e. no background photon / read noise?
// Just ignore it at current.
final double snr = intensity / noise;
stats[SIGNAL].add(intensityInPhotons);
stats[NOISE].add(noise / gain);
if (noise != 0)
stats[SNR].add(snr);
//if (l.isContinuous())
if (l.getNext() != null && l.getPrevious() != null) {
stats[SIGNAL_CONTINUOUS].add(intensityInPhotons);
if (noise != 0)
stats[SNR_CONTINUOUS].add(snr);
}
int id = l.getId();
// Check if this a new fluorophore
if (currentId != id) {
// Add previous fluorophore
stats[SAMPLED_BLINKS].add(blinks);
stats[SAMPLED_T_ON].add(currentT / framesPerSecond);
stats[TOTAL_SIGNAL].add(signal);
// Reset
blinks = 0;
currentT = 1;
currentId = id;
signal = intensityInPhotons;
} else {
signal += intensityInPhotons;
// Check if the current fluorophore pulse is broken (i.e. a blink)
if (l.getTime() - 1 > lastT) {
blinks++;
stats[SAMPLED_T_ON].add(currentT / framesPerSecond);
currentT = 1;
stats[SAMPLED_T_OFF].add(((l.getTime() - 1) - lastT) / framesPerSecond);
} else {
// Continuous on-time
currentT++;
}
}
lastT = l.getTime();
countHistogram[lastT]++;
stats[X].add((l.getX() - centreOffset) * settings.pixelPitch);
stats[Y].add((l.getY() - centreOffset) * settings.pixelPitch);
stats[Z].add(l.getZ() * settings.pixelPitch);
}
// Final fluorophore
stats[SAMPLED_BLINKS].add(blinks);
stats[SAMPLED_T_ON].add(currentT / framesPerSecond);
stats[TOTAL_SIGNAL].add(signal);
// Samples per frame
for (int t = 1; t < countHistogram.length; t++) stats[SAMPLES].add(countHistogram[t]);
if (fluorophores != null) {
for (FluorophoreSequenceModel f : fluorophores) {
stats[BLINKS].add(f.getNumberOfBlinks());
// On-time
for (double t : f.getOnTimes()) stats[T_ON].add(t);
// Off-time
for (double t : f.getOffTimes()) stats[T_OFF].add(t);
}
} else {
// show no blinks
stats[BLINKS].add(0);
stats[T_ON].add(1);
//stats[T_OFF].add(0);
}
if (results != null) {
final boolean emCCD = (settings.getEmGain() > 1);
// Convert depth-of-field to pixels
final double depth = settings.depthOfField / settings.pixelPitch;
for (PeakResult r : results.getResults()) {
final double precision = r.getPrecision(settings.pixelPitch, gain, emCCD);
stats[PRECISION].add(precision);
// The error stores the z-depth in pixels
if (Math.abs(r.error) < depth)
stats[PRECISION_IN_FOCUS].add(precision);
stats[WIDTH].add(r.getSD());
}
// Compute density per frame. Multithread for speed
if (settings.densityRadius > 0) {
IJ.showStatus("Calculating density ...");
ExecutorService threadPool = Executors.newFixedThreadPool(Prefs.getThreads());
List<Future<?>> futures = new LinkedList<Future<?>>();
final ArrayList<float[]> coords = new ArrayList<float[]>();
int t = results.getHead().getFrame();
final Statistics densityStats = stats[DENSITY];
final float radius = (float) (settings.densityRadius * getHWHM());
final Rectangle bounds = results.getBounds();
currentIndex = 0;
finalIndex = results.getTail().getFrame();
// Store the density for each result.
int[] allDensity = new int[results.size()];
int allIndex = 0;
for (PeakResult r : results.getResults()) {
if (t != r.getFrame()) {
allIndex += runDensityCalculation(threadPool, futures, coords, densityStats, radius, bounds, allDensity, allIndex);
}
coords.add(new float[] { r.getXPosition(), r.getYPosition() });
t = r.getFrame();
}
runDensityCalculation(threadPool, futures, coords, densityStats, radius, bounds, allDensity, allIndex);
Utils.waitForCompletion(futures);
threadPool.shutdownNow();
threadPool = null;
IJ.showProgress(1);
// Split results into singles (density = 0) and clustered (density > 0)
MemoryPeakResults singles = copyMemoryPeakResults("No Density");
MemoryPeakResults clustered = copyMemoryPeakResults("Density");
int i = 0;
for (PeakResult r : results.getResults()) {
// Store density in the original value field
r.origValue = allDensity[i];
if (allDensity[i++] == 0)
singles.add(r);
else
clustered.add(r);
}
}
}
StringBuilder sb = new StringBuilder();
sb.append(datasetNumber).append("\t");
sb.append((fluorophores == null) ? localisations.size() : fluorophores.size()).append("\t");
sb.append(stats[SAMPLED_BLINKS].getN() + (int) stats[SAMPLED_BLINKS].getSum()).append("\t");
sb.append(localisations.size()).append("\t");
sb.append(nFrames).append("\t");
sb.append(Utils.rounded(areaInUm)).append("\t");
sb.append(Utils.rounded(localisations.size() / (areaInUm * nFrames), 4)).append("\t");
sb.append(Utils.rounded(getHWHM(), 4)).append("\t");
double s = getPsfSD();
sb.append(Utils.rounded(s, 4)).append("\t");
s *= settings.pixelPitch;
final double sa = PSFCalculator.squarePixelAdjustment(s, settings.pixelPitch) / settings.pixelPitch;
sb.append(Utils.rounded(sa, 4)).append("\t");
// Width not valid for the Image PSF
int nStats = (imagePSF) ? stats.length - 1 : stats.length;
for (int i = 0; i < nStats; i++) {
double centre = (alwaysRemoveOutliers[i]) ? ((StoredDataStatistics) stats[i]).getStatistics().getPercentile(50) : stats[i].getMean();
sb.append(Utils.rounded(centre, 4)).append("\t");
}
if (java.awt.GraphicsEnvironment.isHeadless()) {
IJ.log(sb.toString());
return stats[SIGNAL].getMean();
} else {
summaryTable.append(sb.toString());
}
// Show histograms
if (settings.showHistograms) {
IJ.showStatus("Calculating histograms ...");
boolean[] chosenHistograms = getChoosenHistograms();
WindowOrganiser wo = new WindowOrganiser();
boolean requireRetile = false;
for (int i = 0; i < NAMES.length; i++) {
if (chosenHistograms[i]) {
wo.add(Utils.showHistogram(TITLE, (StoredDataStatistics) stats[i], NAMES[i], (integerDisplay[i]) ? 1 : 0, (settings.removeOutliers || alwaysRemoveOutliers[i]) ? 2 : 0, settings.histogramBins * ((integerDisplay[i]) ? 100 : 1)));
requireRetile = requireRetile || Utils.isNewWindow();
}
}
wo.tile();
}
IJ.showStatus("");
return stats[SIGNAL].getMean();
}
use of gdsc.core.utils.Statistics in project GDSC-SMLM by aherbert.
the class CMOSAnalysis method run.
private void run() {
long start = System.currentTimeMillis();
// Avoid all the file saves from updating the progress bar and status line
Utils.setShowProgress(false);
Utils.setShowStatus(false);
JLabel statusLine = Utils.getStatusLine();
progressBar = Utils.getProgressBar();
// Create thread pool and workers
ExecutorService executor = Executors.newFixedThreadPool(getThreads());
TurboList<Future<?>> futures = new TurboList<Future<?>>(nThreads);
TurboList<ImageWorker> workers = new TurboList<ImageWorker>(nThreads);
double[][][] data = new double[subDirs.size()][2][];
double[] pixelOffset = null, pixelVariance = null;
Statistics statsOffset = null, statsVariance = null;
// For each sub-directory compute the mean and variance
final int nSubDirs = subDirs.size();
boolean error = false;
for (int n = 0; n < nSubDirs; n++) {
SubDir sd = subDirs.getf(n);
statusLine.setText("Analysing " + sd.name);
// Open the series
SeriesImageSource source = new SeriesImageSource(sd.name, sd.path.getPath());
//source.setLogProgress(true);
if (!source.open()) {
error = true;
IJ.error(TITLE, "Failed to open image series: " + sd.path.getPath());
break;
}
// So the bar remains at 99% when workers have finished
totalProgress = source.getFrames() + 1;
stepProgress = Utils.getProgressInterval(totalProgress);
progress = 0;
progressBar.show(0);
ArrayMoment moment = (rollingAlgorithm) ? new RollingArrayMoment() : new SimpleArrayMoment();
final BlockingQueue<ImageJob> jobs = new ArrayBlockingQueue<ImageJob>(nThreads * 2);
for (int i = 0; i < nThreads; i++) {
final ImageWorker worker = new ImageWorker(jobs, moment);
workers.add(worker);
futures.add(executor.submit(worker));
}
// Process the data
for (float[] pixels = source.next(); pixels != null; pixels = source.next()) {
put(jobs, new ImageJob(pixels));
}
// Finish all the worker threads by passing in a null job
for (int i = 0; i < nThreads; i++) {
put(jobs, new ImageJob(null));
}
// 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();
}
}
// Create the final aggregate statistics
for (ImageWorker w : workers) moment.add(w.moment);
data[n][0] = moment.getFirstMoment();
data[n][1] = moment.getVariance();
// Reset
futures.clear();
workers.clear();
Statistics s = new Statistics(data[n][0]);
if (n != 0) {
// Compute mean ADU
Statistics signal = new Statistics();
double[] mean = data[n][0];
for (int i = 0; i < pixelOffset.length; i++) signal.add(mean[i] - pixelOffset[i]);
Utils.log("%s Mean = %s +/- %s. Signal = %s +/- %s ADU", sd.name, Utils.rounded(s.getMean()), Utils.rounded(s.getStandardDeviation()), Utils.rounded(signal.getMean()), Utils.rounded(signal.getStandardDeviation()));
// TODO - optionally save
ImageStack stack = new ImageStack(source.getWidth(), source.getHeight());
stack.addSlice("Mean", Utils.toFloat(data[n][0]));
stack.addSlice("Variance", Utils.toFloat(data[n][1]));
IJ.save(new ImagePlus("PerPixel", stack), new File(directory, "perPixel" + sd.name + ".tif").getPath());
} else {
pixelOffset = data[0][0];
pixelVariance = data[0][1];
statsOffset = s;
statsVariance = new Statistics(pixelVariance);
Utils.log("%s Offset = %s +/- %s. Variance = %s +/- %s", sd.name, Utils.rounded(s.getMean()), Utils.rounded(s.getStandardDeviation()), Utils.rounded(statsVariance.getMean()), Utils.rounded(statsVariance.getStandardDeviation()));
}
}
Utils.setShowStatus(true);
Utils.setShowProgress(true);
IJ.showProgress(1);
executor.shutdown();
if (error)
return;
// Compute the gain
statusLine.setText("Computing gain");
double[] pixelGain = new double[pixelOffset.length];
// Ignore first as this is the 0 exposure image
for (int i = 0; i < pixelGain.length; i++) {
// Use equation 2.5 from the Huang et al paper.
double bibiT = 0;
double biaiT = 0;
for (int n = 1; n < nSubDirs; n++) {
double bi = data[n][0][i] - pixelOffset[i];
double ai = data[n][1][i] - pixelVariance[i];
bibiT += bi * bi;
biaiT += bi * ai;
}
pixelGain[i] = biaiT / bibiT;
}
Statistics statsGain = new Statistics(pixelGain);
Utils.log("Gain Mean = %s +/- %s", Utils.rounded(statsGain.getMean()), Utils.rounded(statsGain.getStandardDeviation()));
// Histogram of offset, variance and gain
int bins = Utils.getBinsSturges(pixelGain.length);
WindowOrganiser wo = new WindowOrganiser();
showHistogram("Offset", pixelOffset, bins, statsOffset, wo);
showHistogram("Variance", pixelVariance, bins, statsVariance, wo);
showHistogram("Gain", pixelGain, bins, statsGain, wo);
wo.tile();
// Save
measuredStack = new ImageStack(size, size);
measuredStack.addSlice("Offset", Utils.toFloat(pixelOffset));
measuredStack.addSlice("Variance", Utils.toFloat(pixelVariance));
measuredStack.addSlice("Gain", Utils.toFloat(pixelGain));
IJ.save(new ImagePlus("PerPixel", measuredStack), new File(directory, "perPixel.tif").getPath());
// Remove the status from the ij.io.ImageWriter class
IJ.showStatus("");
Utils.log("Analysis time = " + Utils.timeToString(System.currentTimeMillis() - start));
}
use of gdsc.core.utils.Statistics in project GDSC-SMLM by aherbert.
the class CreateData method setNoise.
/**
* Sets the noise in the results if missing.
*
* @param results
* the results
*/
private void setNoise(MemoryPeakResults results, ImagePlus imp) {
// Loaded results do not have noise
for (PeakResult r : results.getResults()) if (r.noise != 0)
return;
// Compute noise per frame
ImageStack stack = imp.getImageStack();
final int width = stack.getWidth();
final int height = stack.getHeight();
final IJImageSource source = new IJImageSource(imp);
final float[] noise = new float[source.getFrames() + 1];
for (int slice = 1; slice < noise.length; slice++) {
stack.getPixels(slice);
float[] data = source.next();
// Use the trimmed method as there may be a lot of spots in the frame
noise[slice] = (float) FitWorker.estimateNoise(data, width, height, NoiseEstimator.Method.QUICK_RESIDUALS_LEAST_TRIMMED_OF_SQUARES);
}
Statistics stats = new Statistics(Arrays.copyOfRange(noise, 1, noise.length));
System.out.printf("Noise = %.3f +/- %.3f (%d)\n", stats.getMean(), stats.getStandardDeviation(), stats.getN());
for (PeakResult p : results.getResults()) {
if (p.getFrame() < noise.length)
p.noise = noise[p.getFrame()];
}
}
use of gdsc.core.utils.Statistics in project GDSC-SMLM by aherbert.
the class TraceDiffusion method summarise.
private void summarise(Trace[] traces, double[] fitMSDResult, int n, double[][] jdParams) {
IJ.showStatus("Calculating summary ...");
// Create summary table
createSummaryTable();
Statistics[] stats = new Statistics[NAMES.length];
for (int i = 0; i < stats.length; i++) {
stats[i] = (settings.showHistograms) ? new StoredDataStatistics() : new Statistics();
}
for (Trace trace : traces) {
stats[T_ON].add(trace.getOnTime() * exposureTime);
final double signal = trace.getSignal() / results.getGain();
stats[TOTAL_SIGNAL].add(signal);
stats[SIGNAL_PER_FRAME].add(signal / trace.size());
}
// Add to the summary table
StringBuilder sb = new StringBuilder(title);
sb.append('\t').append(createCombinedName());
sb.append("\t");
sb.append(Utils.rounded(exposureTime * 1000, 3)).append("\t");
sb.append(Utils.rounded(settings.distanceThreshold, 3)).append("\t");
sb.append(Utils.rounded(settings.distanceExclusion, 3)).append("\t");
sb.append(settings.minimumTraceLength).append("\t");
sb.append(settings.ignoreEnds).append("\t");
sb.append(settings.truncate).append("\t");
sb.append(settings.internalDistances).append("\t");
sb.append(settings.fitLength).append("\t");
sb.append(settings.msdCorrection).append("\t");
sb.append(settings.precisionCorrection).append("\t");
sb.append(settings.mle).append("\t");
sb.append(traces.length).append("\t");
sb.append(Utils.rounded(precision, 4)).append("\t");
double D = 0, s = 0;
if (fitMSDResult != null) {
D = fitMSDResult[0];
s = fitMSDResult[1];
}
sb.append(Utils.rounded(D, 4)).append("\t");
sb.append(Utils.rounded(s * 1000, 4)).append("\t");
sb.append(Utils.rounded(settings.jumpDistance * exposureTime)).append("\t");
sb.append(n).append("\t");
sb.append(Utils.rounded(beta, 4)).append("\t");
if (jdParams == null) {
sb.append("\t\t\t");
} else {
sb.append(format(jdParams[0])).append("\t");
sb.append(format(jdParams[1])).append("\t");
sb.append(Utils.rounded(ic)).append("\t");
}
for (int i = 0; i < stats.length; i++) {
sb.append(Utils.rounded(stats[i].getMean(), 3)).append("\t");
}
if (java.awt.GraphicsEnvironment.isHeadless()) {
IJ.log(sb.toString());
return;
} else {
summaryTable.append(sb.toString());
}
if (settings.showHistograms) {
IJ.showStatus("Calculating histograms ...");
for (int i = 0; i < NAMES.length; i++) {
if (displayHistograms[i]) {
showHistogram((StoredDataStatistics) stats[i], NAMES[i], alwaysRemoveOutliers[i], ROUNDED[i], false);
}
}
}
tileNewWindows();
IJ.showStatus("Finished " + TITLE);
}
use of gdsc.core.utils.Statistics in project GDSC-SMLM by aherbert.
the class SpotAnalysis method extractSpotProfile.
private double[][] extractSpotProfile(ImagePlus imp, Rectangle bounds, ImageStack rawSpot) {
final int nSlices = imp.getStackSize();
IJImageSource rawSource = new IJImageSource(imp);
double[][] profile = new double[2][nSlices];
for (int n = 0; n < nSlices; n++) {
IJ.showProgress(n, nSlices);
float[] data = rawSource.next(bounds);
rawSpot.setPixels(data, n + 1);
Statistics stats = new Statistics(data);
profile[0][n] = stats.getMean() / gain;
profile[1][n] = stats.getStandardDeviation() / gain;
}
return profile;
}
Aggregations