use of ij.gui.Plot2 in project GDSC-SMLM by aherbert.
the class DarkTimeAnalysis method analyse.
private void analyse(MemoryPeakResults results) {
// Find min and max time frames
results.sort();
int min = results.getHead().getFrame();
int max = results.getTail().getEndFrame();
// Trace results
double d = searchDistance / results.getCalibration().getNmPerPixel();
int range = max - min + 1;
if (maxDarkTime > 0)
range = FastMath.max(1, (int) Math.round(maxDarkTime * 1000 / msPerFrame));
IJTrackProgress tracker = new IJTrackProgress();
tracker.status("Analysing ...");
tracker.log("Analysing (d=%s nm (%s px) t=%s s (%d frames)) ...", Utils.rounded(searchDistance), Utils.rounded(d), Utils.rounded(range * msPerFrame / 1000.0), range);
Trace[] traces;
if (method == 0) {
TraceManager tm = new TraceManager(results);
tm.setTracker(tracker);
tm.traceMolecules(d, range);
traces = tm.getTraces();
} else {
ClusteringEngine engine = new ClusteringEngine(Prefs.getThreads(), algorithms[method - 1], tracker);
List<PeakResult> peakResults = results.getResults();
ArrayList<Cluster> clusters = engine.findClusters(TraceMolecules.convertToClusterPoints(peakResults), d, range);
traces = TraceMolecules.convertToTraces(peakResults, clusters);
}
tracker.status("Computing histogram ...");
// Build dark-time histogram
int[] times = new int[range];
StoredData stats = new StoredData();
for (Trace trace : traces) {
if (trace.getNBlinks() > 1) {
for (int t : trace.getOffTimes()) {
times[t]++;
}
stats.add(trace.getOffTimes());
}
}
plotDarkTimeHistogram(stats);
// Cumulative histogram
for (int i = 1; i < times.length; i++) times[i] += times[i - 1];
int total = times[times.length - 1];
// Plot dark-time up to 100%
double[] x = new double[range];
double[] y = new double[range];
int truncate = 0;
for (int i = 0; i < x.length; i++) {
x[i] = i * msPerFrame;
y[i] = (100.0 * times[i]) / total;
if (// 100%
times[i] == total) {
truncate = i + 1;
break;
}
}
if (truncate > 0) {
x = Arrays.copyOf(x, truncate);
y = Arrays.copyOf(y, truncate);
}
String title = "Cumulative Dark-time";
Plot2 plot = new Plot2(title, "Time (ms)", "Percentile", x, y);
Utils.display(title, plot);
// Report percentile
for (int i = 0; i < y.length; i++) {
if (y[i] >= percentile) {
Utils.log("Dark-time Percentile %.1f @ %s ms = %s s", percentile, Utils.rounded(x[i]), Utils.rounded(x[i] / 1000));
break;
}
}
tracker.status("");
}
use of ij.gui.Plot2 in project GDSC-SMLM by aherbert.
the class DoubletAnalysis method showHistogram.
/**
* Show histogram.
*
* @param i
* the i
* @param histogram
* the spot histogram
*/
private void showHistogram(int i, double[] histogram) {
if (!displayHistograms[i])
return;
// Truncate to correct size
for (int j = histogram.length; j-- > 0; ) if (histogram[j] != 0) {
histogram = Arrays.copyOf(histogram, j + 1);
break;
}
String[] labels = NAMES[i].split(":");
Plot2 plot = new Plot2(labels[0], labels[1], "Count");
double max = Maths.max(histogram);
plot.setLimits(0, histogram.length, 0, max * 1.05);
plot.addPoints(Utils.newArray(histogram.length, 0, 1.0), histogram, Plot2.BAR);
PlotWindow pw = Utils.display(labels[0], plot);
if (Utils.isNewWindow())
windowOrganiser.add(pw.getImagePlus().getID());
}
use of ij.gui.Plot2 in project GDSC-SMLM by aherbert.
the class DriftCalculator method plotDrift.
private PlotWindow plotDrift(PlotWindow src, PlotWindow parent, double[][] interpolated, double[][] original, String name, int index) {
// Create plot
double[] a = Maths.limits(interpolated[0]);
double[] b = Maths.limits(original[index]);
b = Maths.limits(b, interpolated[index]);
Plot2 plot = new Plot2(name, "Frame", "Drift (px)", (float[]) null, (float[]) null);
plot.setLimits(a[0], a[1], b[0], b[1]);
// De-saturated blue
plot.setColor(new Color(0, 0, 155));
plot.addPoints(original[0], original[index], Plot2.CROSS);
plot.setColor(java.awt.Color.RED);
plot.addPoints(interpolated[0], interpolated[index], Plot2.LINE);
src = Utils.display(name, plot);
if (Utils.isNewWindow() && parent != null) {
Point location = parent.getLocation();
location.y += parent.getHeight();
src.setLocation(location);
}
return src;
}
use of ij.gui.Plot2 in project GDSC-SMLM by aherbert.
the class TraceDiffusion method run.
/*
* (non-Javadoc)
*
* @see ij.plugin.PlugIn#run(java.lang.String)
*/
public void run(String arg) {
SMLMUsageTracker.recordPlugin(this.getClass(), arg);
jumpDistanceParameters = null;
extraOptions = Utils.isExtraOptions();
if (MemoryPeakResults.isMemoryEmpty()) {
IJ.error(TITLE, "No localisations in memory");
return;
}
ArrayList<MemoryPeakResults> allResults = new ArrayList<MemoryPeakResults>();
// Option to pick multiple input datasets together using a list box.
if ("multi".equals(arg)) {
if (!showMultiDialog(allResults))
return;
}
// This shows the dialog for selecting trace options
if (!showTraceDialog(allResults))
return;
if (// Sense check
allResults.isEmpty())
return;
Utils.log(TITLE + "...");
// This optionally collects additional datasets then gets the traces:
// - Trace each single dataset (and store in memory)
// - Combine trace results held in memory
Trace[] traces = getTraces(allResults);
// This still allows a zero entry in the results table.
if (traces.length > 0)
if (!showDialog())
return;
int count = traces.length;
double[] fitMSDResult = null;
int n = 0;
double[][] jdParams = null;
if (count > 0) {
calculatePrecision(traces, allResults.size() > 1);
//--- MSD Analysis ---
// Conversion constants
final double px2ToUm2 = results.getCalibration().getNmPerPixel() * results.getCalibration().getNmPerPixel() / 1e6;
final double px2ToUm2PerSecond = px2ToUm2 / exposureTime;
// Get the maximum trace length
int length = settings.minimumTraceLength;
if (!settings.truncate) {
for (Trace trace : traces) {
if (length < trace.size())
length = trace.size();
}
}
// Get the localisation error (4s^2) in um^2
final double error = (settings.precisionCorrection) ? 4 * precision * precision / 1e6 : 0;
// Pre-calculate MSD correction factors. This accounts for the fact that the distance moved
// in the start/end frames is reduced due to the averaging of the particle location over the
// entire frame into a single point. The true MSD may be restored by applying a factor.
// Note: These are used for the calculation of the diffusion coefficients per molecule and
// the MSD passed to the Jump Distance analysis. However the error is not included in the
// jump distance analysis so will be subtracted from the fitted D coefficients later.
final double[] factors;
if (settings.msdCorrection) {
factors = new double[length];
for (int t = 1; t < length; t++) factors[t] = JumpDistanceAnalysis.getConversionfactor(t);
} else {
factors = Utils.newArray(length, 0.0, 1.0);
}
// Extract the mean-squared distance statistics
Statistics[] stats = new Statistics[length];
for (int i = 0; i < stats.length; i++) stats[i] = new Statistics();
ArrayList<double[]> distances = (saveTraceDistances || displayTraceLength) ? new ArrayList<double[]>(traces.length) : null;
// Store all the jump distances at the specified interval
StoredDataStatistics jumpDistances = new StoredDataStatistics();
final int jumpDistanceInterval = settings.jumpDistance;
// Compute squared distances
StoredDataStatistics msdPerMoleculeAllVsAll = new StoredDataStatistics();
StoredDataStatistics msdPerMoleculeAdjacent = new StoredDataStatistics();
for (Trace trace : traces) {
ArrayList<PeakResult> results = trace.getPoints();
// Sum the MSD and the time
final int traceLength = (settings.truncate) ? settings.minimumTraceLength : trace.size();
// Get the mean for each time separation
double[] sumDistance = new double[traceLength + 1];
double[] sumTime = new double[sumDistance.length];
// Do the distances to the origin (saving if necessary)
{
final float x = results.get(0).getXPosition();
final float y = results.get(0).getYPosition();
if (distances != null) {
double[] msd = new double[traceLength - 1];
for (int j = 1; j < traceLength; j++) {
final int t = j;
final double d = distance2(x, y, results.get(j));
msd[j - 1] = px2ToUm2 * d;
if (t == jumpDistanceInterval)
jumpDistances.add(msd[j - 1]);
sumDistance[t] += d;
sumTime[t] += t;
}
distances.add(msd);
} else {
for (int j = 1; j < traceLength; j++) {
final int t = j;
final double d = distance2(x, y, results.get(j));
if (t == jumpDistanceInterval)
jumpDistances.add(px2ToUm2 * d);
sumDistance[t] += d;
sumTime[t] += t;
}
}
}
if (settings.internalDistances) {
// Do the internal distances
for (int i = 1; i < traceLength; i++) {
final float x = results.get(i).getXPosition();
final float y = results.get(i).getYPosition();
for (int j = i + 1; j < traceLength; j++) {
final int t = j - i;
final double d = distance2(x, y, results.get(j));
if (t == jumpDistanceInterval)
jumpDistances.add(px2ToUm2 * d);
sumDistance[t] += d;
sumTime[t] += t;
}
}
// Add the average distance per time separation to the population
for (int t = 1; t < traceLength; t++) {
// Note: (traceLength - t) == count
stats[t].add(sumDistance[t] / (traceLength - t));
}
} else {
// Add the distance per time separation to the population
for (int t = 1; t < traceLength; t++) {
stats[t].add(sumDistance[t]);
}
}
// Fix this for the precision and MSD adjustment.
// It may be necessary to:
// - sum the raw distances for each time interval (this is sumDistance[t])
// - subtract the precision error
// - apply correction factor for the n-frames to get actual MSD
// - sum the actual MSD
double sumD = 0, sumD_adjacent = Math.max(0, sumDistance[1] - error) * factors[1];
double sumT = 0, sumT_adjacent = sumTime[1];
for (int t = 1; t < traceLength; t++) {
sumD += Math.max(0, sumDistance[t] - error) * factors[t];
sumT += sumTime[t];
}
// Calculate the average displacement for the trace (do not simply use the largest
// time separation since this will miss moving molecules that end up at the origin)
msdPerMoleculeAllVsAll.add(px2ToUm2PerSecond * sumD / sumT);
msdPerMoleculeAdjacent.add(px2ToUm2PerSecond * sumD_adjacent / sumT_adjacent);
}
StoredDataStatistics dPerMoleculeAllVsAll = null;
StoredDataStatistics dPerMoleculeAdjacent = null;
if (saveTraceDistances || (settings.showHistograms && displayDHistogram)) {
dPerMoleculeAllVsAll = calculateDiffusionCoefficient(msdPerMoleculeAllVsAll);
dPerMoleculeAdjacent = calculateDiffusionCoefficient(msdPerMoleculeAdjacent);
}
if (saveTraceDistances) {
saveTraceDistances(traces.length, distances, msdPerMoleculeAllVsAll, msdPerMoleculeAdjacent, dPerMoleculeAllVsAll, dPerMoleculeAdjacent);
}
if (displayTraceLength) {
StoredDataStatistics lengths = calculateTraceLengths(distances);
showHistogram(lengths, "Trace length (um)");
}
if (displayTraceSize) {
StoredDataStatistics sizes = calculateTraceSizes(traces);
showHistogram(sizes, "Trace size", true);
}
// Plot the per-trace histogram of MSD and D
if (settings.showHistograms) {
if (displayMSDHistogram) {
showHistogram(msdPerMoleculeAllVsAll, "MSD/Molecule (all-vs-all)");
showHistogram(msdPerMoleculeAdjacent, "MSD/Molecule (adjacent)");
}
if (displayDHistogram) {
showHistogram(dPerMoleculeAllVsAll, "D/Molecule (all-vs-all)");
showHistogram(dPerMoleculeAdjacent, "D/Molecule (adjacent)");
}
}
// Calculate the mean squared distance (MSD)
double[] x = new double[stats.length];
double[] y = new double[x.length];
double[] sd = new double[x.length];
// Intercept is the 4s^2 (in um^2)
y[0] = 4 * precision * precision / 1e6;
for (int i = 1; i < stats.length; i++) {
x[i] = i * exposureTime;
y[i] = stats[i].getMean() * px2ToUm2;
//sd[i] = stats[i].getStandardDeviation() * px2ToUm2;
sd[i] = stats[i].getStandardError() * px2ToUm2;
}
String title = TITLE + " MSD";
Plot2 plot = plotMSD(x, y, sd, title);
// Fit the MSD using a linear fit
fitMSDResult = fitMSD(x, y, title, plot);
// Jump Distance analysis
if (saveRawData)
saveStatistics(jumpDistances, "Jump Distance", "Distance (um^2)", false);
// Calculate the cumulative jump-distance histogram
double[][] jdHistogram = JumpDistanceAnalysis.cumulativeHistogram(jumpDistances.getValues());
// Always show the jump distance histogram
jdTitle = TITLE + " Jump Distance";
jdPlot = new Plot2(jdTitle, "Distance (um^2)", "Cumulative Probability", jdHistogram[0], jdHistogram[1]);
display(jdTitle, jdPlot);
// Fit Jump Distance cumulative probability
n = jumpDistances.getN();
jumpDistanceParameters = jdParams = fitJumpDistance(jumpDistances, jdHistogram);
}
summarise(traces, fitMSDResult, n, jdParams);
}
use of ij.gui.Plot2 in project GDSC-SMLM by aherbert.
the class SpotAnalysis method showProfile.
private void showProfile(String title, String yTitle, double[] xValues, double[] yValues, double[] yValues2) {
Plot2 plot = new Plot2(title, "Frame", yTitle, xValues, yValues);
double[] limits = Maths.limits(yValues);
plot.setLimits(xValues[0], xValues[xValues.length - 1], limits[0], limits[1]);
plot.draw();
plot.setColor(Color.red);
plot.addPoints(xValues, yValues2, Plot2.LINE);
plot.setColor(Color.magenta);
// Add the on-frames
if (!onFrames.isEmpty()) {
double[] onx = new double[onFrames.size()];
double[] ony = new double[onx.length];
int c = 0;
for (Spot s : onFrames) {
onx[c] = s.frame;
ony[c] = yValues[s.frame - 1];
c++;
}
plot.addPoints(onx, ony, Plot2.CIRCLE);
}
// Add the candidate frames
if (!candidateFrames.isEmpty()) {
plot.setColor(Color.cyan);
double[] onx = new double[candidateFrames.size()];
double[] ony = new double[onx.length];
int c = 0;
for (int i = 0; i < candidateFrames.size(); i++) {
int frame = candidateFrames.getQuick(i);
onx[c] = frame;
ony[c] = yValues[frame - 1];
c++;
}
plot.addPoints(onx, ony, Plot2.BOX);
plot.setColor(Color.magenta);
}
// Overlay current position
plot.addPoints(new double[] { rawImp.getCurrentSlice(), rawImp.getCurrentSlice() }, limits, Plot2.LINE);
plot.setColor(Color.blue);
Utils.display(title, plot);
}
Aggregations