use of ij.text.TextWindow in project GDSC-SMLM by aherbert.
the class BenchmarkSmartSpotRanking method summariseResults.
private void summariseResults(TIntObjectHashMap<RankResults> rankResults, CandidateData candidateData) {
// Summarise the ranking results.
final StringBuilder sb = new StringBuilder(filterResult.resultPrefix);
// countPositive and countNegative is the fractional score of the spot candidates
addCount(sb, (double) candidateData.countPositive + candidateData.countNegative);
addCount(sb, candidateData.countPositive);
addCount(sb, candidateData.countNegative);
addCount(sb, candidateData.fractionPositive);
addCount(sb, candidateData.fractionNegative);
final double[] counter1 = new double[2];
final int[] counter2 = new int[2];
candidateData.filterCandidates.forEachValue(result -> {
counter1[0] += result.np;
counter1[1] += result.nn;
counter2[0] += result.pos;
counter2[1] += result.neg;
return true;
});
final int countTp = counter2[0];
final int countFp = counter2[1];
// The fraction of positive and negative candidates that were included
add(sb, (100.0 * countTp) / candidateData.countPositive);
add(sb, (100.0 * countFp) / candidateData.countNegative);
// Add counts of the the candidates
add(sb, countTp + countFp);
add(sb, countTp);
add(sb, countFp);
// Add fractional counts of the the candidates
double tp = counter1[0];
double fp = counter1[1];
add(sb, tp + fp);
add(sb, tp);
add(sb, fp);
// Materialise rankResults
final int[] frames = new int[rankResults.size()];
final RankResults[] rankResultsArray = new RankResults[rankResults.size()];
final int[] counter = new int[1];
rankResults.forEachEntry((frame, result) -> {
frames[counter[0]] = frame;
rankResultsArray[counter[0]] = result;
counter[0]++;
return true;
});
// Summarise actual and candidate spots per frame
final Statistics actual = new Statistics();
final Statistics candidates = new Statistics();
for (final RankResults rr : rankResultsArray) {
actual.add(rr.zPosition.length);
candidates.add(rr.spots.length);
}
add(sb, actual.getMean());
add(sb, actual.getStandardDeviation());
add(sb, candidates.getMean());
add(sb, candidates.getStandardDeviation());
final String resultPrefix = sb.toString();
// ---
// TODO: Further explore pre-filtering of spot candidates.
// Add good label to spot candidates and have the benchmark spot filter respect this before
// applying the fail count limit.
// Correlation between intensity and SNR ...
// SNR is very good at low density
// SNR fails at high density. The SNR estimate is probably wrong for high intensity spots.
// Triangle is very good when there are a large number of good spots in a region of the image
// (e.g. a mask is used).
// Triangle is poor when there are few good spots in an image.
// Perhaps we can estimate the density of the spots and choose the correct thresholding method?
// ---
// Do a full benchmark through different Spot SNR, image sizes, densities and mask structures
// and see if there are patterns for a good threshold method.
// ---
// Allow using the fitted results from benchmark spot fit. Will it make a difference if we fit
// the candidates (some will fail if weak).
// Can this be done by allowing the user to select the input (spot candidates or fitted
// positions)?
// Perhaps I need to produce a precision estimate for all simulated spots and then only use
// those that achieve a certain precision, i.e. are reasonably in focus. Can this be done?
// Does the image PSF have a width estimate for the entire stack?
// Perhaps I should filter, fit and then filter all spots using no fail count. These then become
// the spots to work with for creating a smart fail count filter.
// ---
// Pre-compute the results and have optional sort
final ArrayList<ScoredResult> list = new ArrayList<>(methodNames.length);
for (int i = 0; i < methodNames.length; i++) {
tp = 0;
fp = 0;
double tn = 0;
int itp = 0;
int ifp = 0;
int itn = 0;
final Statistics s = new Statistics();
long time = 0;
for (final RankResults rr : rankResultsArray) {
final RankResult r = rr.results.get(i);
// Some results will not have a threshold
if (!Float.isInfinite(r.threshold)) {
s.add(r.threshold);
}
time += r.time;
tp += r.fresult.getTruePositives();
fp += r.fresult.getFalsePositives();
tn += r.fresult.getTrueNegatives();
itp += r.cresult.getTruePositives();
ifp += r.cresult.getFalsePositives();
itn += r.cresult.getTrueNegatives();
}
sb.setLength(0);
sb.append(resultPrefix);
add(sb, methodNames[i]);
if (methodNames[i].startsWith("SNR")) {
sb.append('\t');
} else {
add(sb, settings.compactBins);
}
add(sb, s.getMean());
add(sb, s.getStandardDeviation());
add(sb, TextUtils.nanosToString(time));
// TP are all accepted candidates that can be matched to a spot
// FP are all accepted candidates that cannot be matched to a spot
// TN are all accepted candidates that cannot be matched to a spot
// FN = The number of missed spots
// Raw counts of match or no-match
final FractionClassificationResult f1 = new FractionClassificationResult(itp, ifp, itn, simulationParameters.molecules - itp);
final double s1 = addScores(sb, f1);
// Fractional scoring
final FractionClassificationResult f2 = new FractionClassificationResult(tp, fp, tn, simulationParameters.molecules - tp);
final double s2 = addScores(sb, f2);
// Store for sorting
list.add(new ScoredResult(i, (settings.useFractionScores) ? s2 : s1, sb.toString()));
}
if (list.isEmpty()) {
return;
}
Collections.sort(list, ScoredResult::compare);
final TextWindow summaryTable = createTable();
if (summaryTable.getTextPanel().getLineCount() > 0) {
summaryTable.append("");
}
try (BufferedTextWindow tw = new BufferedTextWindow(summaryTable)) {
tw.setIncrement(0);
for (final ScoredResult r : list) {
tw.append(r.result);
}
}
if (settings.showOverlay) {
final int bestMethod = list.get(0).index;
final Overlay o = new Overlay();
for (int j = 0; j < rankResultsArray.length; j++) {
final int frame = frames[j];
final RankResults rr = rankResultsArray[j];
final RankResult r = rr.results.get(bestMethod);
final int[] x1 = new int[r.good.length];
final int[] y1 = new int[r.good.length];
int c1 = 0;
final int[] x2 = new int[r.good.length];
final int[] y2 = new int[r.good.length];
int c2 = 0;
final int[] x3 = new int[r.good.length];
final int[] y3 = new int[r.good.length];
int c3 = 0;
final int[] x4 = new int[r.good.length];
final int[] y4 = new int[r.good.length];
int c4 = 0;
for (int i = 0; i < x1.length; i++) {
if (r.good[i] == TP) {
x1[c1] = rr.spots[i].spot.x;
y1[c1] = rr.spots[i].spot.y;
c1++;
} else if (r.good[i] == FP) {
x2[c2] = rr.spots[i].spot.x;
y2[c2] = rr.spots[i].spot.y;
c2++;
} else if (r.good[i] == TN) {
x3[c3] = rr.spots[i].spot.x;
y3[c3] = rr.spots[i].spot.y;
c3++;
} else if (r.good[i] == FN) {
x4[c4] = rr.spots[i].spot.x;
y4[c4] = rr.spots[i].spot.y;
c4++;
}
}
addToOverlay(o, frame, x1, y1, c1, Color.green);
addToOverlay(o, frame, x2, y2, c2, Color.red);
if (IJ.debugMode) {
// light green
addToOverlay(o, frame, x3, y3, c3, new Color(153, 255, 153));
}
// light red
addToOverlay(o, frame, x4, y4, c4, new Color(255, 153, 153));
}
imp.setOverlay(o);
}
}
use of ij.text.TextWindow in project GDSC-SMLM by aherbert.
the class BenchmarkSpotFilter method getTable.
private static TextWindow getTable(boolean batchSummary) {
AtomicReference<TextWindow> tableRef;
String title;
if (batchSummary) {
tableRef = batchSummaryTable;
title = TITLE + " Batch";
} else {
tableRef = summaryTable;
title = TITLE;
}
return ImageJUtils.refresh(tableRef, () -> new TextWindow(title, createHeader(), "", 1000, 300));
}
use of ij.text.TextWindow in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method createGaWindow.
private void createGaWindow() {
if (isHeadless) {
String header = createResultsHeader(false);
header += "\tIteration";
IJ.log(header);
gaWindow = IJ::log;
} else {
final TextWindow window = ImageJUtils.refresh(gaWindowRef, () -> {
String header = createResultsHeader(false);
header += "\tIteration";
return new TextWindow(TITLE + " Evolution", header, "", 900, 300);
});
if (settings.clearTables) {
window.getTextPanel().clear();
}
gaWindow = window::append;
}
}
use of ij.text.TextWindow in project GDSC-SMLM by aherbert.
the class PsfEstimator method estimatePsf.
private int estimatePsf() {
log("Estimating PSF ... Press escape to abort");
final PeakFit fitter = createFitter();
// Use the fit configuration to generate a Gaussian function to test what is being evaluated
final Gaussian2DFunction gf = config.getFitConfiguration().createGaussianFunction(1, 1, 1);
ignore[ANGLE] = !gf.evaluatesAngle();
ignore[X] = !gf.evaluatesSD0();
ignore[Y] = !gf.evaluatesSD1();
final double[] params = new double[] { gf.evaluatesAngle() ? initialPeakAngle : 0, gf.evaluatesSD0() ? initialPeakStdDev0 : 0, gf.evaluatesSD1() ? initialPeakStdDev1 : 0, 0, 0 };
final double[] paramsDev = new double[3];
final boolean[] identical = new boolean[4];
final double[] p = new double[] { Double.NaN, Double.NaN, Double.NaN, Double.NaN };
final TextWindow resultsWindow = createResultsWindow();
addToResultTable(resultsWindow, 0, 0, params, paramsDev, p);
if (!calculateStatistics(fitter, params, paramsDev)) {
return (ImageJUtils.isInterrupted()) ? ABORTED : INSUFFICIENT_PEAKS;
}
if (!addToResultTable(resultsWindow, 1, size(), params, paramsDev, p)) {
return BAD_ESTIMATE;
}
boolean tryAgain = false;
int iteration = 2;
for (; ; ) {
if (!calculateStatistics(fitter, params, paramsDev)) {
return (ImageJUtils.isInterrupted()) ? ABORTED : INSUFFICIENT_PEAKS;
}
try {
for (int i = 0; i < 3; i++) {
getP(i, p, identical);
}
if (!ignore[Y]) {
getPairedP(sampleNew[X], sampleNew[Y], XY, p, identical);
}
if (!addToResultTable(resultsWindow, iteration++, size(), params, paramsDev, p)) {
return BAD_ESTIMATE;
}
if ((ignore[ANGLE] || identical[ANGLE] || identical[XY]) && (ignore[X] || identical[X]) && (ignore[Y] || identical[Y])) {
tryAgain = checkAngleSignificance() || checkXySignificance(identical);
// Update recommended values. Only use if significant
params[X] = sampleNew[X].getMean();
params[Y] = (!ignore[Y] && !identical[XY]) ? sampleNew[Y].getMean() : params[X];
params[ANGLE] = (!ignore[ANGLE]) ? sampleNew[ANGLE].getMean() : 0;
// update starting configuration
initialPeakAngle = (float) params[ANGLE];
initialPeakStdDev0 = (float) params[X];
initialPeakStdDev1 = (float) params[Y];
if (settings.getUpdatePreferences()) {
config.getFitConfiguration().setInitialPeakStdDev0((float) params[X]);
try {
config.getFitConfiguration().setInitialPeakStdDev1((float) params[Y]);
config.getFitConfiguration().setInitialAngle((float) params[ANGLE]);
} catch (final IllegalStateException | ConfigurationException ex) {
// Ignore this as the current PSF is not a 2 axis and theta Gaussian PSF
}
}
break;
}
if (IJ.escapePressed()) {
IJ.beep();
IJ.showStatus("Aborted");
return ABORTED;
}
} catch (final Exception ex) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Error while estimating the PSF", ex);
return EXCEPTION;
}
}
return (tryAgain) ? TRY_AGAIN : COMPLETE;
}
use of ij.text.TextWindow in project GDSC-SMLM by aherbert.
the class Noise method showResults.
private void showResults() {
// Sort on slice number
Collections.sort(results, (o1, o2) -> Double.compare(o1[0], o2[0]));
// Slow when there are lots of results ... Could change the output options in the future
final TextWindow tw = new TextWindow(imp.getTitle() + " Noise", createHeader(), "", 800, 400);
for (final double[] result : results) {
tw.append(createResult(result));
}
}
Aggregations