use of uk.ac.sussex.gdsc.smlm.results.Trace in project GDSC-SMLM by aherbert.
the class TrackPopulationAnalysis method getTracks.
/**
* Gets the tracks. Each track has contiguous frames and the length is enough to fit
* {@code minTrackLength} overlapping windows of the specified size:
*
* <pre>
* length >= window + minTrackLength - 1
* </pre>
*
* @param combinedResults the combined results
* @param window the window size
* @param minTrackLength the minimum track length (assumed to be {@code >= 1})
* @return the tracks
*/
private static List<Trace> getTracks(List<MemoryPeakResults> combinedResults, int window, int minTrackLength) {
final LocalList<Trace> tracks = new LocalList<>();
final Statistics stats = new Statistics();
final int minSize = window + Math.max(minTrackLength, 1) - 1;
combinedResults.forEach(results -> {
final int start = tracks.size();
// Sort by id then frame
results = results.copy();
results.sort(IdFramePeakResultComparator.INSTANCE);
final int size = results.size();
// Skip IDs not associated with clustering
int index = 0;
while (index < size && results.get(index).getId() < 1) {
index++;
}
// Initialise current id and frame
int id = results.get(index).getId() - 1;
int frame = results.get(index).getFrame();
Trace track = new Trace();
for (; index < size; index++) {
final PeakResult result = results.get(index);
// Same ID and contiguous frames
if (result.getId() != id || result.getFrame() != frame + 1) {
addTrack(minSize, tracks, track);
track = new Trace();
}
id = result.getId();
frame = result.getFrame();
track.add(result);
}
addTrack(minSize, tracks, track);
stats.reset();
for (int i = start; i < tracks.size(); i++) {
stats.add(tracks.unsafeGet(i).size());
}
final StringBuilder sb = new StringBuilder(256);
TextUtils.formatTo(sb, "%s tracks=%d, length=%s +/- %s", results.getName(), stats.getN(), MathUtils.rounded(stats.getMean(), 3), MathUtils.rounded(stats.getStandardDeviation(), 3));
// Limit of diffusion coefficient from the localisation precision.
// Just use the entire dataset for simplicity (i.e. not the tracks of min length).
final PrecisionResultProcedure pp = new PrecisionResultProcedure(results);
try {
pp.getPrecision();
final Mean mean = new Mean();
for (final double p : pp.precisions) {
mean.add(p);
}
// 2nDt = MSD (n = number of dimensions)
// D = MSD / 2nt
final CalibrationReader reader = results.getCalibrationReader();
final double t = reader.getExposureTime() / 1000.0;
// Assume computed in nm. Convert to um.
final double x = mean.getMean() / 1000;
final double d = x * x / (2 * t);
TextUtils.formatTo(sb, ", precision=%s nm, D limit=%s um^2/s", MathUtils.rounded(x * 1000, 4), MathUtils.rounded(d, 4));
} catch (final DataException ex) {
// No precision
}
IJ.log(sb.toString());
});
return tracks;
}
use of uk.ac.sussex.gdsc.smlm.results.Trace in project GDSC-SMLM by aherbert.
the class SpotAnalysis method saveTraces.
private void saveTraces() {
if (!onFrames.isEmpty() && updated) {
final GenericDialog gd = new GenericDialog(PLUGIN_TITLE);
gd.enableYesNoCancel();
gd.hideCancelButton();
gd.addMessage("The list contains unsaved selected frames.\n \nDo you want to continue?");
gd.showDialog();
if (!gd.wasOKed()) {
return;
}
}
// For all spots in the results window, get the ID and then save the traces to memory
if (!ImageJUtils.isShowing(resultsWindow)) {
return;
}
// Create a results set in memory
final MemoryPeakResults results = new MemoryPeakResults();
results.setName(PLUGIN_TITLE);
results.begin();
MemoryPeakResults.addResults(results);
final ArrayList<TraceResult> traceResults = new ArrayList<>(resultsWindow.getTextPanel().getLineCount());
for (int i = 0; i < resultsWindow.getTextPanel().getLineCount(); i++) {
final String line = resultsWindow.getTextPanel().getLine(i);
try (Scanner s = new Scanner(line)) {
s.useDelimiter("\t");
int id = -1;
double signal = -1;
// Be careful as the text panel may not contain what we expect, i.e. empty lines, etc
if (s.hasNextInt()) {
id = s.nextInt();
try {
// cx
s.nextDouble();
// cy
s.nextDouble();
signal = s.nextDouble();
} catch (final NoSuchElementException ex) {
// Ignore
}
}
if (id != -1 && signal != -1) {
final Trace trace = traces.get(id);
if (trace != null) {
results.addAll(trace.getPoints());
traceResults.add(new TraceResult(new Spot(id, signal), trace));
}
}
}
}
results.end();
saveTracesToFile(traceResults);
IJ.showStatus("Saved traces");
}
use of uk.ac.sussex.gdsc.smlm.results.Trace in project GDSC-SMLM by aherbert.
the class SpotAnalysis method saveSpot.
private void saveSpot() {
if (onFrames.isEmpty() || !updated) {
return;
}
createResultsWindow();
id++;
double signal = 0;
Trace trace = null;
final float psfWidth = Float.parseFloat(widthTextField.getText());
final float cx = areaBounds.x + areaBounds.width / 2.0f;
final float cy = areaBounds.y + areaBounds.height / 2.0f;
for (final Spot s : onFrames) {
// Get the signal again since the background may have changed.
final double spotSignal = getSignal(s.frame);
signal += spotSignal;
final float[] params = Gaussian2DPeakResultHelper.createOneAxisParams(0, (float) (spotSignal), cx, cy, 0, psfWidth);
final PeakResult result = new PeakResult(s.frame, (int) cx, (int) cy, 0, 0, 0, 0, params, null);
if (trace == null) {
trace = new Trace(result);
} else {
trace.add(result);
}
}
if (trace == null) {
return;
}
final Statistics tOn = Statistics.create(trace.getOnTimes());
final Statistics tOff = Statistics.create(trace.getOffTimes());
resultsWindow.append(String.format("%d\t%.1f\t%.1f\t%s\t%s\t%s\t%d\t%s\t%s\t%s", id, cx, cy, MathUtils.rounded(signal, 4), MathUtils.rounded(tOn.getSum() * msPerFrame, 3), MathUtils.rounded(tOff.getSum() * msPerFrame, 3), trace.getBlinks() - 1, MathUtils.rounded(tOn.getMean() * msPerFrame, 3), MathUtils.rounded(tOff.getMean() * msPerFrame, 3), imp.getTitle()));
// Save the individual on/off times for use in creating a histogram
traces.put(id, trace);
updated = false;
}
use of uk.ac.sussex.gdsc.smlm.results.Trace in project GDSC-SMLM by aherbert.
the class TraceDiffusion method getTraces.
private Trace[] getTraces(ArrayList<MemoryPeakResults> allResults) {
this.results = allResults.get(0);
// Results should be checked for calibration by this point
exposureTime = results.getCalibrationReader().getExposureTime() / 1000;
final Function<MemoryPeakResults, Trace[]> traceFunction = createTraceFunction();
final ArrayList<Trace> allTraces = new ArrayList<>();
additionalDatasets = -1;
for (final MemoryPeakResults r : allResults) {
additionalDatasets++;
Trace[] traces = traceFunction.apply(r);
traces = filterTraces(r.getName(), traces, clusteringSettings.getMinimumTraceLength(), clusteringSettings.getIgnoreEnds());
allTraces.addAll(Arrays.asList(traces));
// --- Save results ---
if (traces.length != 0) {
// Save the traces to memory
TraceMolecules.saveResults(r, traces, "Tracks");
if (clusteringSettings.getSaveTraces()) {
// Sort traces by time to assist the results source in extracting frames sequentially.
// Do this before saving to assist in debugging using the saved traces file.
TraceMolecules.sortByTime(traces);
final String newFilename = TraceMolecules.saveTraces(r, traces, createSettingsComment(), settings.tracesFilename, additionalDatasets);
// Only keep the main filename in memory
if (additionalDatasets == 0) {
settings.tracesFilename = newFilename;
}
}
}
}
final Trace[] all = allTraces.toArray(new Trace[0]);
if (additionalDatasets != 0) {
ImageJUtils.log("Multiple inputs provide %d traces", allTraces.size());
final MemoryPeakResults tracedResults = TraceManager.toPeakResults(all, results.getCalibration(), true);
tracedResults.copySettings(results);
tracedResults.setName(createCombinedName() + " Tracks");
MemoryPeakResults.addResults(tracedResults);
}
return all;
}
use of uk.ac.sussex.gdsc.smlm.results.Trace in project GDSC-SMLM by aherbert.
the class DarkTimeAnalysis method analyse.
private void analyse(MemoryPeakResults results) {
// Find min and max time frames
results.sort();
final int min = results.getFirstFrame();
final int max = results.getLastFrame();
// Trace results:
// TODO - The search distance could have units to avoid assuming the results are in pixels
final double d = settings.searchDistance / results.getCalibrationReader().getNmPerPixel();
int range = max - min + 1;
if (settings.maxDarkTime > 0) {
range = Math.max(1, (int) Math.round(settings.maxDarkTime * 1000 / msPerFrame));
}
final TrackProgress tracker = SimpleImageJTrackProgress.getInstance();
tracker.status("Analysing ...");
tracker.log("Analysing (d=%s nm (%s px) t=%s s (%d frames)) ...", MathUtils.rounded(settings.searchDistance), MathUtils.rounded(d), MathUtils.rounded(range * msPerFrame / 1000.0), range);
Trace[] traces;
if (settings.method == 0) {
final TraceManager tm = new TraceManager(results);
tm.setTracker(tracker);
tm.traceMolecules(d, range);
traces = tm.getTraces();
} else {
final ClusteringEngine engine = new ClusteringEngine(Prefs.getThreads(), algorithms[settings.method - 1], tracker);
final List<Cluster> clusters = engine.findClusters(TraceMolecules.convertToClusterPoints(results), d, range);
traces = TraceMolecules.convertToTraces(results, clusters);
}
tracker.status("Computing histogram ...");
// Build dark-time histogram
final int[] times = new int[range];
final StoredData stats = new StoredData();
for (final Trace trace : traces) {
if (trace.getBlinks() > 1) {
for (final 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];
}
final 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;
if (times[i] == total) {
// Final value at 100%
y[i] = 100.0;
truncate = i + 1;
break;
}
y[i] = (100.0 * times[i]) / total;
}
if (truncate > 0) {
x = Arrays.copyOf(x, truncate);
y = Arrays.copyOf(y, truncate);
}
final String title = "Cumulative Dark-time";
final Plot plot = new Plot(title, "Time (ms)", "Percentile");
plot.addPoints(x, y, Plot.LINE);
ImageJUtils.display(title, plot);
// Report percentile
for (int i = 0; i < y.length; i++) {
if (y[i] >= settings.percentile) {
ImageJUtils.log("Dark-time Percentile %.1f @ %s ms = %s s", settings.percentile, MathUtils.rounded(x[i]), MathUtils.rounded(x[i] / 1000));
break;
}
}
tracker.status("");
}
Aggregations