use of uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method saveResults.
/**
* Save the results to memory.
*
* @param filterResults The results from running the filter (or null)
* @param filter the filter
*/
private void saveResults(PreprocessedPeakResult[] filterResults, DirectFilter filter) {
final MemoryPeakResults newResults = createResults(filterResults, filter, true);
MemoryPeakResults.addResults(newResults);
}
use of uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method getCoordinates.
private static TIntObjectHashMap<UniqueIdPeakResult[]> getCoordinates(MemoryPeakResults results) {
final TIntObjectHashMap<UniqueIdPeakResult[]> coords = new TIntObjectHashMap<>();
if (results.size() > 0) {
// Do not use HashMap directly to build the coords object since there
// will be many calls to getEntry(). Instead sort the results and use
// a new list for each time point
results.sort();
final Counter uniqueId = new Counter();
final FrameCounter counter = new FrameCounter();
final LocalList<PeakResult> tmp = new LocalList<>();
// Add the results to the lists
results.forEach((PeakResultProcedure) result -> {
if (counter.advanceAndReset(result.getFrame()) && !tmp.isEmpty()) {
coords.put(counter.previousFrame(), tmp.toArray(new UniqueIdPeakResult[0]));
tmp.clear();
}
tmp.add(new UniqueIdPeakResult(tmp.size(), uniqueId.getAndIncrement(), result));
});
if (!tmp.isEmpty()) {
coords.put(counter.currentFrame(), tmp.toArray(new UniqueIdPeakResult[0]));
}
}
return coords;
}
use of uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method createResults.
/**
* Create peak results.
*
* @param filterResults The results from running the filter (or null)
* @param filter the filter
*/
private MemoryPeakResults createResults(PreprocessedPeakResult[] filterResults, DirectFilter filter, boolean withBorder) {
if (filterResults == null) {
final MultiPathFilter multiPathFilter = createMpf(filter, defaultMinimalFilter);
filterResults = filterResults(multiPathFilter);
}
final MemoryPeakResults newResults = new MemoryPeakResults();
newResults.copySettings(this.results);
newResults.setName(TITLE);
if (withBorder) {
// To produce the same results as the PeakFit plugin we must implement the border
// functionality used in the FitWorker. This respects the border of the spot filter.
final FitEngineConfiguration config = new FitEngineConfiguration();
updateAllConfiguration(config);
final MaximaSpotFilter spotFilter = config.createSpotFilter();
final int border = spotFilter.getBorder();
final Rectangle bounds = getBounds();
final int borderLimitX = bounds.x + bounds.width - border;
final int borderLimitY = bounds.y + bounds.height - border;
for (final PreprocessedPeakResult spot : filterResults) {
if (spot.getX() > border && spot.getX() < borderLimitX && spot.getY() > border && spot.getY() < borderLimitY) {
final double[] p = spot.toGaussian2DParameters();
final float[] params = new float[p.length];
for (int j = 0; j < p.length; j++) {
params[j] = (float) p[j];
}
final int frame = spot.getFrame();
final int origX = (int) p[Gaussian2DFunction.X_POSITION];
final int origY = (int) p[Gaussian2DFunction.Y_POSITION];
newResults.add(frame, origX, origY, 0, 0, spot.getNoise(), spot.getMeanSignal(), params, null);
}
}
} else {
for (final PreprocessedPeakResult spot : filterResults) {
final double[] p = spot.toGaussian2DParameters();
final float[] params = new float[p.length];
for (int j = 0; j < p.length; j++) {
params[j] = (float) p[j];
}
final int frame = spot.getFrame();
final int origX = (int) p[Gaussian2DFunction.X_POSITION];
final int origY = (int) p[Gaussian2DFunction.Y_POSITION];
newResults.add(frame, origX, origY, 0, 0, spot.getNoise(), spot.getMeanSignal(), params, null);
}
}
return newResults;
}
use of uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults in project GDSC-SMLM by aherbert.
the class TraceDiffusion method run.
@Override
public void run(String arg) {
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
jumpDistanceParametersRef.set(null);
extraOptions = ImageJUtils.isExtraOptions();
if (MemoryPeakResults.isMemoryEmpty()) {
IJ.error(TITLE, "No localisations in memory");
return;
}
settings = Settings.load();
// Saved by reference so just save now
settings.save();
final ArrayList<MemoryPeakResults> allResults = new ArrayList<>();
// Option to pick multiple input datasets together using a list box.
if ("multi".equals(arg) && !showMultiDialog(allResults)) {
return;
}
// This shows the dialog for selecting trace options
if (!showTraceDialog(allResults)) {
return;
}
if (allResults.isEmpty()) {
return;
}
ImageJUtils.log(TITLE + "...");
// - Trace each single dataset (and store in memory)
// - Combine trace results held in memory
final Trace[] traces = getTraces(allResults);
// This still allows a zero entry in the results table.
if (traces.length > 0 && !showDialog()) {
return;
}
final int count = traces.length;
double[] fitMsdResult = null;
int numberOfDataPoints = 0;
double[][] jdParams = null;
if (count > 0) {
calculatePrecision(traces, allResults.size() > 1);
// --- MSD Analysis ---
// Conversion constants
final double px2ToUm2 = MathUtils.pow2(results.getCalibrationReader().getNmPerPixel()) / 1e6;
final double px2ToUm2PerSecond = px2ToUm2 / exposureTime;
// Get the maximum trace length
int length = clusteringSettings.getMinimumTraceLength();
if (!clusteringSettings.getTruncate()) {
for (final Trace trace : traces) {
if (length < trace.size()) {
length = trace.size();
}
}
}
// Get the localisation error (4s^2) in um^2
final double error = (clusteringSettings.getPrecisionCorrection()) ? 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 (clusteringSettings.getMsdCorrection()) {
factors = new double[length];
for (int t = 1; t < length; t++) {
factors[t] = JumpDistanceAnalysis.getConversionfactor(t);
}
} else {
factors = SimpleArrayUtils.newArray(length, 0.0, 1.0);
}
// Extract the mean-squared distance statistics
final Statistics[] stats = new Statistics[length];
for (int i = 0; i < stats.length; i++) {
stats[i] = new Statistics();
}
final ArrayList<double[]> distances = (settings.saveTraceDistances || settings.displayTraceLength) ? new ArrayList<>(traces.length) : null;
// Store all the jump distances at the specified interval
final StoredDataStatistics jumpDistances = new StoredDataStatistics();
final int jumpDistanceInterval = clusteringSettings.getJumpDistance();
// Compute squared distances
final StoredDataStatistics msdPerMoleculeAllVsAll = new StoredDataStatistics();
final StoredDataStatistics msdPerMoleculeAdjacent = new StoredDataStatistics();
for (final Trace trace : traces) {
final PeakResultStoreList results = trace.getPoints();
// Sum the MSD and the time
final int traceLength = (clusteringSettings.getTruncate()) ? clusteringSettings.getMinimumTraceLength() : trace.size();
// Get the mean for each time separation
final double[] sumDistance = new double[traceLength + 1];
final double[] sumTime = new double[sumDistance.length];
// Do the distances to the origin (saving if necessary)
final float x0 = results.get(0).getXPosition();
final float y0 = results.get(0).getYPosition();
if (distances != null) {
final double[] msd = new double[traceLength - 1];
for (int j = 1; j < traceLength; j++) {
final int t = j;
final double d = distance2(x0, y0, 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(x0, y0, results.get(j));
if (t == jumpDistanceInterval) {
jumpDistances.add(px2ToUm2 * d);
}
sumDistance[t] += d;
sumTime[t] += t;
}
}
if (clusteringSettings.getInternalDistances()) {
// 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;
final double sumD_adjacent = Math.max(0, sumDistance[1] - error) * factors[1];
double sumT = 0;
final double 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 (settings.saveTraceDistances || (clusteringSettings.getShowHistograms() && settings.displayDHistogram)) {
dperMoleculeAllVsAll = calculateDiffusionCoefficient(msdPerMoleculeAllVsAll);
dperMoleculeAdjacent = calculateDiffusionCoefficient(msdPerMoleculeAdjacent);
}
if (settings.saveTraceDistances) {
saveTraceDistances(traces.length, distances, msdPerMoleculeAllVsAll, msdPerMoleculeAdjacent, dperMoleculeAllVsAll, dperMoleculeAdjacent);
}
if (settings.displayTraceLength) {
final StoredDataStatistics lengths = calculateTraceLengths(distances);
showHistogram(lengths, "Trace length (um)");
}
if (settings.displayTraceSize) {
final StoredDataStatistics sizes = calculateTraceSizes(traces);
showHistogram(sizes, "Trace size", true);
}
// Plot the per-trace histogram of MSD and D
if (clusteringSettings.getShowHistograms()) {
if (settings.displayMsdHistogram) {
showHistogram(msdPerMoleculeAllVsAll, "MSD/Molecule (all-vs-all)");
showHistogram(msdPerMoleculeAdjacent, "MSD/Molecule (adjacent)");
}
if (settings.displayDHistogram) {
showHistogram(dperMoleculeAllVsAll, "D/Molecule (all-vs-all)");
showHistogram(dperMoleculeAdjacent, "D/Molecule (adjacent)");
}
}
// Calculate the mean squared distance (MSD)
final double[] x = new double[stats.length];
final double[] y = new double[x.length];
final 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;
}
final String title = TITLE + " MSD";
final Plot plot = plotMsd(x, y, sd, title);
// Fit the MSD using a linear fit
fitMsdResult = fitMsd(x, y, title, plot);
// Jump Distance analysis
if (settings.saveRawData) {
saveStatistics(jumpDistances, "Jump Distance", "Distance (um^2)", false);
}
// Calculate the cumulative jump-distance histogram
final double[][] jdHistogram = JumpDistanceAnalysis.cumulativeHistogram(jumpDistances.getValues());
// Always show the jump distance histogram
jdTitle = TITLE + " Jump Distance";
jdPlot = new Plot(jdTitle, "Distance (um^2)", "Cumulative Probability");
jdPlot.addPoints(jdHistogram[0], jdHistogram[1], Plot.LINE);
display(jdTitle, jdPlot);
// Fit Jump Distance cumulative probability
numberOfDataPoints = jumpDistances.getN();
jdParams = fitJumpDistance(jumpDistances, jdHistogram);
jumpDistanceParametersRef.set(jdParams);
}
summarise(traces, fitMsdResult, numberOfDataPoints, jdParams);
}
use of uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults in project GDSC-SMLM by aherbert.
the class TraceDiffusion method createTraceFunction.
/**
* Creates the trace function for the configured trace diffusion mode.
*
* @return the function
*/
private Function<MemoryPeakResults, Trace[]> createTraceFunction() {
if (clusteringSettings.getTraceDiffusionMode() == 1) {
final DmttConfiguration config = createDmttConfiguration();
return r -> new DynamicMultipleTargetTracing(r).traceMolecules(config).toArray(new Trace[0]);
}
// Nearest neighbour
// Convert from NM to the native units of the results
final Converter c = CalibrationHelper.getDistanceConverter(results.getCalibration(), DistanceUnit.NM);
final double distanceThreshold = c.convertBack(clusteringSettings.getDistanceThreshold());
final double distanceExclusion = c.convertBack(clusteringSettings.getDistanceExclusion());
return r -> {
final TraceManager manager = new TraceManager(r);
// Run the tracing
manager.setTracker(SimpleImageJTrackProgress.getInstance());
manager.setDistanceExclusion(distanceExclusion);
manager.traceMolecules(distanceThreshold, 1);
return manager.getTraces();
};
}
Aggregations