use of uk.ac.sussex.gdsc.core.ij.BufferedTextWindow in project GDSC-SMLM by aherbert.
the class DiffusionRateTest method msdAnalysis.
/**
* Tabulate the observed MSD for different jump distances.
*
* @param points the points
*/
private void msdAnalysis(ArrayList<Point> points) {
if (myMsdAnalysisSteps == 0) {
return;
}
IJ.showStatus("MSD analysis ...");
IJ.showProgress(1, myMsdAnalysisSteps);
// This will only be fast if the list is an array
final Point[] list = points.toArray(new Point[0]);
// Compute the base MSD
final Point origin = new Point(0, 0, 0);
double sum = origin.distance2(list[0]);
int count = 1;
for (int i = 1; i < list.length; i++) {
final Point last = list[i - 1];
final Point current = list[i];
if (last.id == current.id) {
sum += last.distance2(current);
} else {
sum += origin.distance2(current);
}
count++;
}
// Create a new set of points that have coordinates that
// are the rolling average over the number of aggregate steps
final DoubleRollingArray x = new DoubleRollingArray(pluginSettings.aggregateSteps);
final DoubleRollingArray y = new DoubleRollingArray(pluginSettings.aggregateSteps);
int id = 0;
int length = 0;
for (final Point p : points) {
if (p.id != id) {
x.clear();
y.clear();
}
id = p.id;
x.add(p.x);
y.add(p.y);
// Only create a point if the full aggregation size is reached
if (x.isFull()) {
list[length++] = new Point(id, x.getAverage(), y.getAverage());
}
}
// Q - is this useful?
final double p = myPrecision / settings.getPixelPitch();
final UniformRandomProvider rng = UniformRandomProviders.create();
final NormalizedGaussianSampler gauss = SamplerUtils.createNormalizedGaussianSampler(rng);
final int totalSteps = (int) Math.ceil(settings.getSeconds() * settings.getStepsPerSecond() - pluginSettings.aggregateSteps);
final int limit = Math.min(totalSteps, myMsdAnalysisSteps);
final Ticker ticker = ImageJUtils.createTicker(limit, 1);
final TextWindow msdTable = createMsdTable((sum / count) * settings.getStepsPerSecond() / conversionFactor);
try (BufferedTextWindow bw = new BufferedTextWindow(msdTable)) {
bw.setIncrement(0);
for (int step = 1; step <= myMsdAnalysisSteps; step++) {
sum = 0;
count = 0;
for (int i = step; i < length; i++) {
final Point last = list[i - step];
final Point current = list[i];
if (last.id == current.id) {
if (p == 0) {
sum += last.distance2(current);
count++;
} else {
// is the same if enough samples are present
for (int ii = 1; ii-- > 0; ) {
sum += last.distance2(current, p, gauss);
count++;
}
}
}
}
if (count == 0) {
break;
}
bw.append(addResult(step, sum, count));
ticker.tick();
}
}
IJ.showProgress(1);
}
use of uk.ac.sussex.gdsc.core.ij.BufferedTextWindow 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 uk.ac.sussex.gdsc.core.ij.BufferedTextWindow in project GDSC-SMLM by aherbert.
the class DoubletAnalysis method showResults.
/**
* Show results.
*
* @param results the results
*/
private static void showResults(ArrayList<DoubletResult> results, boolean show) {
if (!show) {
return;
}
try (BufferedTextWindow tw = new BufferedTextWindow(createResultsTable())) {
tw.setIncrement(0);
final StringBuilder sb = new StringBuilder();
for (final DoubletResult result : results) {
sb.setLength(0);
sb.append(result.frame).append('\t');
sb.append(result.spot.x).append('\t');
sb.append(result.spot.y).append('\t');
sb.append(IJ.d2s(result.spot.intensity, 1)).append('\t');
sb.append(result.matchCount).append('\t');
sb.append(result.neighbours).append('\t');
sb.append(result.almostNeighbours).append('\t');
sb.append(MathUtils.rounded(result.score1)).append('\t');
sb.append(MathUtils.rounded(result.score2)).append('\t');
add(sb, result.fitResult1);
add(sb, result.fitResult2);
sb.append(IJ.d2s(result.sumOfSquares1, 1)).append('\t');
sb.append(IJ.d2s(result.sumOfSquares2, 1)).append('\t');
sb.append(IJ.d2s(result.ll1, 1)).append('\t');
sb.append(IJ.d2s(result.ll2, 1)).append('\t');
sb.append(IJ.d2s(result.value1, 1)).append('\t');
sb.append(IJ.d2s(result.value2, 1)).append('\t');
sb.append(MathUtils.rounded(result.r1)).append('\t');
sb.append(MathUtils.rounded(result.r2)).append('\t');
sb.append(MathUtils.rounded(result.aic1)).append('\t');
sb.append(MathUtils.rounded(result.aic2)).append('\t');
sb.append(MathUtils.rounded(result.bic1)).append('\t');
sb.append(MathUtils.rounded(result.bic2)).append('\t');
sb.append(MathUtils.rounded(result.maic1)).append('\t');
sb.append(MathUtils.rounded(result.maic2)).append('\t');
sb.append(MathUtils.rounded(result.mbic1)).append('\t');
sb.append(MathUtils.rounded(result.mbic2)).append('\t');
sb.append(MathUtils.rounded(result.angle[0])).append('\t');
sb.append(MathUtils.rounded(result.angle[1])).append('\t');
sb.append(MathUtils.rounded(result.gap)).append('\t');
sb.append(MathUtils.rounded(result.xshift[0])).append('\t');
sb.append(MathUtils.rounded(result.yshift[0])).append('\t');
sb.append(MathUtils.rounded(result.xshift[1])).append('\t');
sb.append(MathUtils.rounded(result.yshift[1])).append('\t');
sb.append(result.iter1).append('\t');
sb.append(result.iter2).append('\t');
sb.append(result.eval1).append('\t');
sb.append(result.eval2).append('\t');
addParams(sb, result.fitResult1);
addParams(sb, result.fitResult2);
tw.append(sb.toString());
}
}
}
Aggregations