use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure in project GDSC-SMLM by aherbert.
the class DensityEstimator method run.
@Override
public void run(String arg) {
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
// Require some fit results and selected regions
if (MemoryPeakResults.countMemorySize() == 0) {
IJ.error(TITLE, "There are no fitting results in memory");
return;
}
if (!showDialog()) {
return;
}
// Currently this only supports pixel distance units
final MemoryPeakResults results = ResultsManager.loadInputResults(settings.inputOption, false, DistanceUnit.PIXEL, null);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
IJ.showStatus("");
return;
}
final long start = System.currentTimeMillis();
IJ.showStatus("Calculating density ...");
// Scale to um^2 from px^2
final double scale = Math.pow(results.getDistanceConverter(DistanceUnit.UM).convertBack(1), 2);
results.sort();
final FrameCounter counter = results.newFrameCounter();
final double localisationsPerFrame = (double) results.size() / (results.getLastFrame() - counter.currentFrame() + 1);
final Rectangle bounds = results.getBounds(true);
final double globalDensity = localisationsPerFrame / bounds.width / bounds.height;
final int border = settings.border;
final boolean includeSingles = settings.includeSingles;
final int size = 2 * border + 1;
final double minDensity = Math.pow(size, -2);
ImageJUtils.log("%s : %s : Global density %s. Minimum density in %dx%d px = %s um^-2", TITLE, results.getName(), MathUtils.rounded(globalDensity * scale), size, size, MathUtils.rounded(minDensity * scale));
final TIntArrayList x = new TIntArrayList();
final TIntArrayList y = new TIntArrayList();
final ExecutorService es = Executors.newFixedThreadPool(Prefs.getThreads());
final LocalList<FrameDensity> densities = new LocalList<>();
final LocalList<Future<?>> futures = new LocalList<>();
results.forEach((PeakResultProcedure) (peak) -> {
if (counter.advance(peak.getFrame())) {
final FrameDensity fd = new FrameDensity(peak.getFrame(), x.toArray(), y.toArray(), border, includeSingles);
densities.add(fd);
futures.add(es.submit(fd));
x.resetQuick();
y.resetQuick();
}
x.add((int) peak.getXPosition());
y.add((int) peak.getYPosition());
});
densities.add(new FrameDensity(counter.currentFrame(), x.toArray(), y.toArray(), border, includeSingles));
futures.add(es.submit(densities.get(densities.size() - 1)));
es.shutdown();
// Wait
ConcurrencyUtils.waitForCompletionUnchecked(futures);
densities.sort((o1, o2) -> Integer.compare(o1.frame, o2.frame));
final int total = densities.stream().mapToInt(fd -> fd.counts.length).sum();
// Plot density
final Statistics stats = new Statistics();
final float[] frame = new float[total];
final float[] density = new float[total];
densities.stream().forEach(fd -> {
for (int i = 0; i < fd.counts.length; i++) {
final double d = (fd.counts[i] / fd.values[i]) * scale;
frame[stats.getN()] = fd.frame;
density[stats.getN()] = (float) d;
stats.add(d);
}
});
final double mean = stats.getMean();
final double sd = stats.getStandardDeviation();
final String label = String.format("Density = %s +/- %s um^-2", MathUtils.rounded(mean), MathUtils.rounded(sd));
final Plot plot = new Plot("Frame vs Density", "Frame", "Density (um^-2)");
plot.addPoints(frame, density, Plot.CIRCLE);
plot.addLabel(0, 0, label);
final WindowOrganiser wo = new WindowOrganiser();
ImageJUtils.display(plot.getTitle(), plot, wo);
// Histogram density
new HistogramPlotBuilder("Local", StoredData.create(density), "Density (um^-2)").setPlotLabel(label).show(wo);
wo.tile();
// Log the number of singles
final int singles = densities.stream().mapToInt(fd -> fd.singles).sum();
ImageJUtils.log("Singles %d / %d (%s%%)", singles, results.size(), MathUtils.rounded(100.0 * singles / results.size()));
IJ.showStatus(TITLE + " complete : " + TextUtils.millisToString(System.currentTimeMillis() - start));
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure in project GDSC-SMLM by aherbert.
the class AstigmatismModelManager method plotData.
private boolean plotData() {
if (results.size() <= imp.getStackSize() / 2) {
IJ.error(TITLE, "Not enough fit results " + results.size());
return false;
}
final double umPerSlice = pluginSettings.getNmPerSlice() / 1000.0;
// final double nmPerPixel = results.getNmPerPixel();
z = new double[results.size()];
x = new double[z.length];
y = new double[z.length];
intensity = new double[z.length];
final Counter counter = new Counter();
// We have fit the results so they will be in the preferred units
results.forEach(new PeakResultProcedure() {
@Override
public void execute(PeakResult peak) {
final int i = counter.getAndIncrement();
z[i] = peak.getFrame() * umPerSlice;
x[i] = (peak.getXPosition() - cx);
y[i] = (peak.getYPosition() - cy);
intensity[i] = peak.getIntensity();
}
});
final WidthResultProcedure wp = new WidthResultProcedure(results, DistanceUnit.PIXEL);
wp.getWxWy();
sx = SimpleArrayUtils.toDouble(wp.wx);
sy = SimpleArrayUtils.toDouble(wp.wy);
final WindowOrganiser wo = new WindowOrganiser();
plot(wo, z, "Intensity (photon)", intensity, "Intensity", null, null);
xyPlot = plot(wo, z, "Position (px)", x, "X", y, "Y");
widthPlot = plot(wo, z, "Width (px)", sx, "Sx", sy, "Sy");
wo.tile();
return true;
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure in project GDSC-SMLM by aherbert.
the class FilterAnalysis method showDialog.
private boolean showDialog(List<MemoryPeakResults> resultsList, boolean fileInput) {
final GenericDialog gd = new GenericDialog(TITLE);
String helpKey = "filter-analysis";
if (fileInput) {
helpKey += "-file";
}
gd.addHelp(HelpUrls.getUrl(helpKey));
int total = 0;
final Counter tp = new Counter();
for (final MemoryPeakResults r : resultsList) {
total += r.size();
r.forEach((PeakResultProcedure) result -> {
if (result.getOrigValue() != 0) {
tp.increment();
}
});
}
ImageJUtils.addMessage(gd, "%d files, %d results, %d True-Positives", resultsList.size(), total, tp.getCount());
settings = Settings.load();
settings.save();
if (!fileInput) {
gd.addCheckbox("SNR_filter", settings.snrFilter);
gd.addNumericField("Min_SNR", settings.minSnr, 0);
gd.addNumericField("Max_SNR", settings.maxSnr, 0);
gd.addNumericField("Min_Width", settings.minWidth, 2);
gd.addNumericField("Max_Width", settings.maxWidth, 2);
gd.addNumericField("Increment_Width", settings.incWidth, 2);
gd.addCheckbox("Precision_filter", settings.precisionFilter);
gd.addNumericField("Min_Precision", settings.minPrecision, 0);
gd.addNumericField("Max_Precision", settings.maxPrecision, 0);
gd.addCheckbox("Trace_filter", settings.traceFilter);
gd.addNumericField("Min_distance", settings.minDistance, 2);
gd.addNumericField("Max_distance", settings.maxDistance, 2);
gd.addNumericField("Increment_distance", settings.incDistance, 2);
gd.addNumericField("Min_time", settings.minTime, 0);
gd.addNumericField("Max_time", settings.maxTime, 0);
gd.addNumericField("Increment_time", settings.incTime, 0);
gd.addCheckbox("Hysteresis_SNR_filter", settings.hysteresisSnrFilter);
gd.addNumericField("Min_SNR_gap", settings.minSnrGap, 0);
gd.addNumericField("Max_SNR_gap", settings.maxSnrGap, 0);
gd.addNumericField("Increment_SNR_gap", settings.incSnrGap, 0);
gd.addCheckbox("Hysteresis_Precision_filter", settings.hysteresisPrecisionFilter);
gd.addNumericField("Min_Precision_gap", settings.minPrecisionGap, 0);
gd.addNumericField("Max_Precision_gap", settings.maxPrecisionGap, 0);
gd.addNumericField("Increment_Precision_gap", settings.incPrecisionGap, 0);
gd.addCheckbox("Save_filters", settings.saveFilterSets);
}
gd.addCheckbox("Show_table", settings.showResultsTable);
gd.addSlider("Plot_top_n", 0, 20, settings.plotTopN);
gd.addCheckbox("Calculate_sensitivity", settings.calculateSensitivity);
gd.addSlider("Delta", 0.01, 1, settings.delta);
gd.showDialog();
return !gd.wasCanceled() && readDialog(gd, fileInput);
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure in project GDSC-SMLM by aherbert.
the class Filter method filterSubset.
/**
* Filter the results.
*
* <p>Input PeakResults must be allocated a score for true positive, false positive, true negative
* and false negative (accessed via the object property get methods). The filter is run and
* results that pass accumulate scores for true positive and false positive, otherwise the scores
* are accumulated for true negative and false negative. The simplest scoring scheme is to mark
* valid results as tp=fn=1 and fp=tn=0 and invalid results the opposite.
*
* <p>The number of failures before each peak is stored in the origX property of the PeakResult.
*
* @param results the results
* @param score If not null will be populated with the fraction score [ tp, fp, tn, fn, p, n ]
* @return the filtered results
*/
public MemoryPeakResults filterSubset(MemoryPeakResults results, double[] score) {
final MemoryPeakResults newResults = new MemoryPeakResults();
final FrameCounter counter = new FrameCounter();
newResults.copySettings(results);
setup(results);
final double[] s = new double[4];
final Counter p = new Counter();
results.forEach((PeakResultProcedure) peak -> {
counter.advanceAndReset(peak.getFrame());
final boolean isPositive = accept(peak);
if (isPositive) {
peak.setOrigX(counter.getCount());
counter.reset();
newResults.add(peak);
} else {
counter.increment();
}
if (isPositive) {
p.increment();
s[TP] += peak.getTruePositiveScore();
s[FP] += peak.getFalsePositiveScore();
} else {
s[FN] += peak.getFalseNegativeScore();
s[TN] += peak.getTrueNegativeScore();
}
});
end();
if (score != null && score.length > 5) {
score[0] = s[TP];
score[1] = s[FP];
score[2] = s[TN];
score[3] = s[FN];
score[4] = p.getCount();
score[5] = (double) results.size() - p.getCount();
}
return newResults;
}
use of uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure in project GDSC-SMLM by aherbert.
the class Filter method filterSubset.
/**
* Filter the results.
*
* <p>Input PeakResults must be allocated a score for true positive, false positive, true negative
* and false negative (accessed via the object property get methods). The filter is run and
* results that pass accumulate scores for true positive and false positive, otherwise the scores
* are accumulated for true negative and false negative. The simplest scoring scheme is to mark
* valid results as tp=fn=1 and fp=tn=0 and invalid results the opposite.
*
* <p>The number of consecutive rejections are counted per frame. When the configured number of
* failures is reached all remaining results for the frame are rejected. This assumes the results
* are ordered by the frame.
*
* <p>The number of failures before each peak is stored in the origX property of the PeakResult.
*
* @param results the results
* @param failures the number of failures to allow per frame before all peaks are rejected
* @param score If not null will be populated with the fraction score [ tp, fp, tn, fn, p, n ]
* @return the filtered results
*/
public MemoryPeakResults filterSubset(MemoryPeakResults results, final int failures, double[] score) {
final MemoryPeakResults newResults = new MemoryPeakResults();
final FrameCounter counter = new FrameCounter();
newResults.copySettings(results);
setup(results);
final double[] s = new double[4];
results.forEach((PeakResultProcedure) peak -> {
counter.advanceAndReset(peak.getFrame());
final boolean isPositive;
if (counter.getCount() > failures) {
isPositive = false;
} else {
isPositive = accept(peak);
}
if (isPositive) {
peak.setOrigX(counter.getCount());
counter.reset();
newResults.add(peak);
} else {
counter.increment();
}
if (isPositive) {
s[TP] += peak.getTruePositiveScore();
s[FP] += peak.getFalsePositiveScore();
} else {
s[FN] += peak.getFalseNegativeScore();
s[TN] += peak.getTrueNegativeScore();
}
});
end();
if (score != null && score.length > 5) {
score[0] = s[TP];
score[1] = s[FP];
score[2] = s[TN];
score[3] = s[FN];
score[4] = newResults.size();
score[5] = (double) results.size() - newResults.size();
}
return newResults;
}
Aggregations