use of uk.ac.sussex.gdsc.core.clustering.ClusteringEngine in project GDSC-SMLM by aherbert.
the class PcPalmClusters method doClustering.
/**
* Extract the results from the PCPALM molecules using the area ROI and then do clustering to
* obtain the histogram of molecules per cluster.
*
* @return the histogram data
*/
private HistogramData doClustering() {
// Perform clustering analysis to generate the histogram of cluster sizes
final PcPalmAnalysis analysis = new PcPalmAnalysis();
final List<Molecule> molecules = analysis.cropToRoi(WindowManager.getCurrentImage(), moleculesResults);
if (molecules.size() < 2) {
error("No results within the crop region");
return null;
}
ImageJUtils.log("Using %d molecules (Density = %s um^-2) @ %s nm", molecules.size(), MathUtils.rounded(molecules.size() / analysis.croppedArea), MathUtils.rounded(settings.distance));
final long s1 = System.nanoTime();
final ClusteringEngine engine = new ClusteringEngine(1, clusteringAlgorithm, SimpleImageJTrackProgress.getInstance());
if (settings.multiThread) {
engine.setThreadCount(Prefs.getThreads());
}
engine.setTracker(SimpleImageJTrackProgress.getInstance());
IJ.showStatus("Clustering ...");
final List<Cluster> clusters = engine.findClusters(convertToPoint(molecules), settings.distance);
IJ.showStatus("");
if (clusters == null) {
ImageJUtils.log("Aborted");
return null;
}
numberOfMolecules = molecules.size();
ImageJUtils.log("Finished : %d total clusters (%s ms)", clusters.size(), MathUtils.rounded((System.nanoTime() - s1) / 1e6));
// Save cluster centroids to a results set in memory. Then they can be plotted.
final MemoryPeakResults results = new MemoryPeakResults(clusters.size());
results.setName(TITLE);
// Set an arbitrary calibration so that the lifetime of the results is stored in the exposure
// time
// The results will be handled as a single mega-frame containing all localisation.
results.setCalibration(CalibrationHelper.create(100, 1, moleculesResults.seconds * 1000));
int id = 0;
for (final Cluster c : clusters) {
results.add(new ExtendedPeakResult((float) c.getX(), (float) c.getY(), c.getSize(), ++id));
}
MemoryPeakResults.addResults(results);
// Get the data for fitting
final float[] values = new float[clusters.size()];
for (int i = 0; i < values.length; i++) {
values[i] = clusters.get(i).getSize();
}
final float yMax = (int) Math.ceil(MathUtils.max(values));
final int nBins = (int) (yMax + 1);
final float[][] hist = HistogramPlot.calcHistogram(values, 0, yMax, nBins);
final HistogramData histogramData = (settings.calibrateHistogram) ? new HistogramData(hist, settings.frames, settings.area, Settings.UNITS[settings.units]) : new HistogramData(hist);
saveHistogram(histogramData);
return histogramData;
}
use of uk.ac.sussex.gdsc.core.clustering.ClusteringEngine 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("");
}
use of uk.ac.sussex.gdsc.core.clustering.ClusteringEngine in project GDSC-SMLM by aherbert.
the class TraceMolecules method run.
@Override
public void run(String arg) {
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
if (MemoryPeakResults.isMemoryEmpty()) {
IJ.error(pluginTitle, "No localisations in memory");
return;
}
altKeyDown = ImageJUtils.isExtraOptions();
Trace[] traces = null;
int totalFiltered = 0;
if ("dynamic".equals(arg)) {
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Dynamic Mutliple Target Tracing
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
outputName = "Dynamic Trace";
if (!showDynamicTraceDialog()) {
return;
}
final DmttConfiguration config = createDmttConfiguration();
traces = new DynamicMultipleTargetTracing(results).traceMolecules(config).toArray(new Trace[0]);
} else if ("cluster".equals(arg)) {
// -=-=-=-=-=
// Clustering
// -=-=-=-=-=
outputName = "Cluster";
if (!showClusterDialog()) {
return;
}
final ClusteringEngine engine = new ClusteringEngine(Prefs.getThreads(), getClusteringAlgorithm(settings.getClusteringAlgorithm()), SimpleImageJTrackProgress.getInstance());
if (settings.getSplitPulses()) {
engine.setPulseInterval(settings.getPulseInterval());
limitTimeThreshold(settings.getPulseInterval());
}
final List<Cluster> clusters = engine.findClusters(convertToClusterPoints(), getDistance(settings.getDistanceThreshold(), results.getCalibration()), timeThresholdInFrames());
if (clusters == null) {
ImageJUtils.log("Aborted");
return;
}
traces = convertToTraces(clusters);
} else {
// -=-=-=-
// Tracing
// -=-=-=-
outputName = "Trace";
if (!showDialog()) {
return;
}
final TraceManager manager = new TraceManager(results);
manager.setTraceMode(getTraceMode(settings.getTraceMode()));
manager.setActivationFrameInterval(settings.getPulseInterval());
manager.setActivationFrameWindow(settings.getPulseWindow());
manager.setDistanceExclusion(getDistance(settings.getDistanceExclusion(), results.getCalibration()));
if (settings.getOptimise()) {
// Optimise before configuring for a pulse interval
runOptimiser(manager);
}
if (settings.getSplitPulses()) {
manager.setPulseInterval(settings.getPulseInterval());
limitTimeThreshold(settings.getPulseInterval());
}
manager.setTracker(SimpleImageJTrackProgress.getInstance());
manager.traceMolecules(getDistance(settings.getDistanceThreshold(), results.getCalibration()), timeThresholdInFrames());
traces = manager.getTraces();
totalFiltered = manager.getTotalFiltered();
}
// --=-=-=-=-=-
// Results processing
// --=-=-=-=-=-
outputName += (outputName.endsWith("e") ? "" : "e") + "d";
saveResults(results, traces, outputName);
// Save singles + single localisations in a trace
saveCentroidResults(results, getSingles(traces), outputName + " Singles");
final Trace[] multiTraces = getTraces(traces);
saveResults(results, multiTraces, outputName + " Multi");
// Save centroids
outputName += " Centroids";
final MemoryPeakResults tracedResults = saveCentroidResults(results, traces, outputName);
// Save traces separately
saveCentroidResults(results, multiTraces, outputName + " Multi");
// 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.
sortByTime(traces);
if (settings.getSaveTraces()) {
saveTraces(traces);
}
summarise(createSummaryTable(), traces, totalFiltered, settings.getDistanceThreshold(), timeThresholdInSeconds());
IJ.showStatus(String.format("%d localisations => %d traces (%d filtered)", results.size(), tracedResults.size(), totalFiltered));
}
use of uk.ac.sussex.gdsc.core.clustering.ClusteringEngine in project GDSC-SMLM by aherbert.
the class PcPalmMolecules method performDistanceAnalysis.
private void performDistanceAnalysis(double[][] intraHist, int p99) {
// We want to know the fraction of distances between molecules at the 99th percentile
// that are intra- rather than inter-molecule.
// Do single linkage clustering of closest pair at this distance and count the number of
// links that are inter and intra.
// Convert molecules for clustering
final ArrayList<ClusterPoint> points = new ArrayList<>(settings.molecules.size());
for (final Molecule m : settings.molecules) {
// Precision was used to store the molecule ID
points.add(ClusterPoint.newClusterPoint((int) m.precision, m.x, m.y, m.photons));
}
final ClusteringEngine engine = new ClusteringEngine(Prefs.getThreads(), ClusteringAlgorithm.PARTICLE_SINGLE_LINKAGE, SimpleImageJTrackProgress.getInstance());
IJ.showStatus("Clustering to check inter-molecule distances");
engine.setTrackJoins(true);
final List<Cluster> clusters = engine.findClusters(points, intraHist[0][p99]);
IJ.showStatus("");
if (clusters != null) {
final double[] intraIdDistances = engine.getIntraIdDistances();
final double[] interIdDistances = engine.getInterIdDistances();
final int all = interIdDistances.length + intraIdDistances.length;
log(" * Fraction of inter-molecule particle linkage @ %s nm = %s %%", MathUtils.rounded(intraHist[0][p99], 4), (all > 0) ? MathUtils.rounded(100.0 * interIdDistances.length / all, 4) : "0");
// Show a double cumulative histogram plot
final double[][] intraIdHist = MathUtils.cumulativeHistogram(intraIdDistances, false);
final double[][] interIdHist = MathUtils.cumulativeHistogram(interIdDistances, false);
// Plot
final String title = TITLE + " molecule linkage distance";
final Plot plot = new Plot(title, "Distance", "Frequency");
plot.addPoints(intraIdHist[0], intraIdHist[1], Plot.LINE);
double max = (intraIdHist[1].length > 0) ? intraIdHist[1][intraIdHist[1].length - 1] : 0;
if (interIdHist[1].length > 0) {
max = Math.max(max, interIdHist[1][interIdHist[1].length - 1]);
}
plot.setLimits(0, intraIdHist[0][intraIdHist[0].length - 1], 0, max);
plot.setColor(Color.blue);
plot.addPoints(interIdHist[0], interIdHist[1], Plot.LINE);
plot.setColor(Color.black);
plot.addLegend("Intra-molecule\nInter-molecule");
ImageJUtils.display(title, plot);
} else {
log("Aborted clustering to check inter-molecule distances");
}
}
Aggregations