use of uk.ac.sussex.gdsc.smlm.results.PeakResult in project GDSC-SMLM by aherbert.
the class TraceDiffusion method filterTraces.
/**
* Split traces to contiguous traces and filter traces that are not the minimum length. Re-assigns
* the ID for the output traces.
*
* @param name the name
* @param traces the traces
* @param minimumTraceLength the minimum trace length
* @param ignoreEnds the ignore ends
* @return The new traces
*/
private static Trace[] filterTraces(String name, Trace[] traces, int minimumTraceLength, boolean ignoreEnds) {
final LocalList<Trace> list = new LocalList<>(traces.length);
final int minLength = (ignoreEnds) ? minimumTraceLength + 2 : minimumTraceLength;
final Consumer<Trace> action = (ignoreEnds) ? t -> {
if (t.size() >= minLength) {
t.removeEnds();
list.add(t);
t.setId(list.size());
}
} : t -> {
if (t.size() >= minLength) {
list.add(t);
t.setId(list.size());
}
};
final Consumer<ArrayPeakResultStore> action2 = (ignoreEnds) ? r -> {
if (r.size() >= minLength) {
r.remove(0);
r.remove(r.size() - 1);
final Trace t = new Trace(r);
list.add(t);
t.setId(list.size());
}
} : r -> {
if (r.size() >= minLength) {
final Trace t = new Trace(r);
list.add(t);
t.setId(list.size());
}
};
final ArrayPeakResultStore results = new ArrayPeakResultStore(11);
for (final Trace trace : traces) {
if (trace.size() < minLength) {
// Too short
continue;
}
if (trace.size() == trace.getTail().getFrame() - trace.getHead().getFrame() + 1) {
// Contiguous
action.accept(trace);
} else {
// Split the trace
int t1 = trace.getHead().getFrame();
for (int i = 0; i < trace.size(); i++) {
final PeakResult peak = trace.get(i);
final int t2 = peak.getFrame();
if (t2 - t1 > 1) {
// Non-contiguous
action2.accept(results);
results.clear();
}
t1 = t2;
results.add(peak);
}
// Final trace
action2.accept(results);
results.clear();
}
}
ImageJUtils.log("Filtered results '%s' : %s split and filtered to %d using " + "minimum length %d (Ignore ends = %b)", name, TextUtils.pleural(traces.length, "trace"), list.size(), minimumTraceLength, ignoreEnds);
return list.toArray(new Trace[0]);
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResult in project GDSC-SMLM by aherbert.
the class TraceLengthAnalysis method run.
@Override
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
MemoryPeakResults results = ResultsManager.loadInputResults(settings.inputOption, false, null, null);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
return;
}
try {
distanceConverter = results.getDistanceConverter(DistanceUnit.UM);
timeConverter = results.getTimeConverter(TimeUnit.SECOND);
} catch (final Exception ex) {
IJ.error(TITLE, "Cannot convert units to um or seconds: " + ex.getMessage());
return;
}
// Get the localisation error (4s^2) in raw units^2
double precision = 0;
try {
final PrecisionResultProcedure p = new PrecisionResultProcedure(results);
p.getPrecision();
// Precision in nm using the median
precision = new Percentile().evaluate(p.precisions, 50);
// Convert from nm to um to raw units
final double rawPrecision = distanceConverter.convertBack(precision / 1e3);
// Get the localisation error (4s^2) in units^2
error = 4 * rawPrecision * rawPrecision;
} catch (final Exception ex) {
ImageJUtils.log(TITLE + " - Unable to compute precision: " + ex.getMessage());
}
// Analyse the track lengths
results = results.copy();
results.sort(IdFramePeakResultComparator.INSTANCE);
// Ensure the first result triggers an id change
lastid = results.getFirst().getId() - 1;
results.forEach(this::processTrackLength);
// For the final track
store();
msds = msdList.toArray();
lengths = lengthList.toArray();
ids = idList.toArray();
final int[] limits = MathUtils.limits(lengths);
h1 = new int[limits[1] + 1];
h2 = new int[h1.length];
x1 = SimpleArrayUtils.newArray(h1.length, 0, 1f);
y1 = new float[x1.length];
y2 = new float[x1.length];
// Sort by MSD
final int[] indices = SimpleArrayUtils.natural(msds.length);
SortUtils.sortIndices(indices, msds, false);
final double[] msds2 = msds.clone();
final int[] lengths2 = lengths.clone();
final int[] ids2 = ids.clone();
for (int i = 0; i < indices.length; i++) {
msds[i] = msds2[indices[i]];
lengths[i] = lengths2[indices[i]];
ids[i] = ids2[indices[i]];
}
// Interactive analysis
final NonBlockingExtendedGenericDialog gd = new NonBlockingExtendedGenericDialog(TITLE);
ImageJUtils.addMessage(gd, "Split traces into fixed or moving using the track diffusion coefficient (D).\n" + "Localisation error has been subtracted from jumps (%s nm).", MathUtils.rounded(precision));
final Statistics s = Statistics.create(msds);
final double av = s.getMean();
final String msg = String.format("Average D per track = %s um^2/s", MathUtils.rounded(av));
gd.addMessage(msg);
// Histogram the diffusion coefficients
final WindowOrganiser wo = new WindowOrganiser();
final HistogramPlot histogramPlot = new HistogramPlotBuilder("Trace diffusion coefficient", StoredData.create(msds), "D (um^2/s)").setRemoveOutliersOption(1).setPlotLabel(msg).build();
histogramPlot.show(wo);
final double[] xvalues = histogramPlot.getPlotXValues();
final double min = xvalues[0];
final double max = xvalues[xvalues.length - 1];
// see if we can build a nice slider range from the histogram limits
if (max - min < 5) {
// Because sliders are used when the range is <5 and floating point
gd.addSlider("D_threshold", min, max, settings.msdThreshold);
} else {
gd.addNumericField("D_threshold", settings.msdThreshold, 2, 6, "um^2/s");
}
gd.addCheckbox("Normalise", settings.normalise);
gd.addDialogListener((gd1, event) -> {
settings.msdThreshold = gd1.getNextNumber();
settings.normalise = gd1.getNextBoolean();
update();
return true;
});
if (ImageJUtils.isShowGenericDialog()) {
draw(wo);
wo.tile();
}
gd.setOKLabel("Save datasets");
gd.setCancelLabel("Close");
gd.addHelp(HelpUrls.getUrl("trace-length-analysis"));
gd.showDialog();
if (gd.wasCanceled()) {
return;
}
// Sort by ID
final PeakResult[] list = results.toArray();
Arrays.sort(list, IdFramePeakResultComparator.INSTANCE);
createResults(results, "Fixed", 0, lastIndex, list);
createResults(results, "Moving", lastIndex, msds.length, list);
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResult in project GDSC-SMLM by aherbert.
the class SpotAnalysis method saveTracesToFile.
private void saveTracesToFile(ArrayList<TraceResult> traceResults) {
final String resultsDirectory = IJ.getDirectory(PLUGIN_TITLE);
if (resultsDirectory == null) {
return;
}
// Save the traces to a single file.
// Also save the blinks and on/off times into data files for histogram analysis
final BufferedWriter[] files = new BufferedWriter[5];
try {
files[0] = openBufferedWriter(resultsDirectory + "traces.txt", String.format("#ms/frame = %s%n#Id\tcx\tcy\tsignal\tn-Blinks\tStart\tStop\t...", MathUtils.rounded(msPerFrame, 3)));
files[1] = openBufferedWriter(resultsDirectory + "tOn.txt", "");
files[2] = openBufferedWriter(resultsDirectory + "tOff.txt", "");
files[3] = openBufferedWriter(resultsDirectory + "blinks.txt", "");
files[4] = openBufferedWriter(resultsDirectory + "signal.txt", "");
for (final TraceResult traceResult : traceResults) {
final StringBuilder sb = new StringBuilder();
sb.append(traceResult.spot.frame).append('\t');
sb.append(traceResult.trace.getHead().getXPosition()).append('\t');
sb.append(traceResult.trace.getHead().getYPosition()).append('\t');
sb.append(traceResult.spot.signal).append('\t');
final int nBlinks = traceResult.trace.getBlinks() - 1;
sb.append(nBlinks);
final int[] on = traceResult.trace.getOnTimes();
final int[] off = traceResult.trace.getOffTimes();
int time = traceResult.trace.getHead().getFrame();
for (int i = 0; i < on.length; i++) {
writeLine(files[1], Double.toString(msPerFrame * on[i]));
sb.append('\t').append(time).append('\t').append(time + on[i] - 1);
if (off != null && i < off.length) {
writeLine(files[2], Double.toString(msPerFrame * off[i]));
time += on[i] + off[i];
}
}
writeLine(files[0], sb.toString());
writeLine(files[3], Integer.toString(nBlinks));
writeLine(files[4], String.format("# Id=%d, Blinks=%d, Signal=%f", traceResult.spot.frame, nBlinks, traceResult.spot.signal));
for (int k = 0; k < traceResult.trace.size(); k++) {
final PeakResult r = traceResult.trace.get(k);
writeLine(files[4], String.format("%d %f", r.getFrame(), r.getIntensity()));
}
}
} catch (final Exception ex) {
// Q. Add better handling of errors?
Logger.getLogger(getClass().getName()).log(Level.WARNING, ex, () -> "Failed to save traces to results directory: " + resultsDirectory);
} finally {
for (final BufferedWriter tracesFile : files) {
if (tracesFile != null) {
try {
tracesFile.close();
} catch (final IOException ex) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Failed to close traces file", ex);
}
}
}
}
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResult in project GDSC-SMLM by aherbert.
the class TraceExporter method splitTraces.
private MemoryPeakResults splitTraces(MemoryPeakResults results) {
if (settings.maxJump < 1) {
// Disabled
return results;
}
int id = 0;
final int lastT = 0;
for (int i = 0, size = results.size(); i < size; i++) {
final PeakResult r = results.get(i);
if (r.getId() != id) {
id = r.getId();
} else if (r.getFrame() - lastT > settings.maxJump) {
return doSplit(results);
}
}
return results;
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResult in project GDSC-SMLM by aherbert.
the class TraceExporter method doSplit.
private MemoryPeakResults doSplit(MemoryPeakResults results) {
final MemoryPeakResults results2 = new MemoryPeakResults(results.size());
results2.copySettings(results);
int nextId = results.getLast().getId();
int id = 0;
int idOut = 0;
int lastT = 0;
for (int i = 0, size = results.size(); i < size; i++) {
final PeakResult r = results.get(i);
if (r.getId() != id) {
id = r.getId();
idOut = id;
} else if (r.getFrame() - lastT > settings.maxJump) {
idOut = ++nextId;
}
final AttributePeakResult r2 = new AttributePeakResult(r);
r2.setId(idOut);
results2.add(r2);
lastT = r.getEndFrame();
}
return results2;
}
Aggregations