use of uk.ac.sussex.gdsc.core.ij.BufferedTextWindow in project GDSC-SMLM by aherbert.
the class TrackPopulationAnalysis method createModelTable.
/**
* Creates a table to show the final model. This uses the assignments to create a mixture model
* from the original data.
*
* @param data the data
* @param weights the weights for each component
* @param component the component
*/
private static void createModelTable(double[][] data, double[] weights, int[] component) {
final MixtureMultivariateGaussianDistribution model = MultivariateGaussianMixtureExpectationMaximization.createMixed(data, component);
final MultivariateGaussianDistribution[] distributions = model.getDistributions();
// Get the fraction of each component
final int[] count = new int[MathUtils.max(component) + 1];
Arrays.stream(component).forEach(c -> count[c]++);
try (BufferedTextWindow tw = new BufferedTextWindow(ImageJUtils.refresh(modelTableRef, () -> new TextWindow("Track Population Model", createHeader(), "", 800, 300)))) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < weights.length; i++) {
sb.setLength(0);
sb.append(i).append('\t');
sb.append(MathUtils.rounded((double) count[i] / component.length)).append('\t');
sb.append(MathUtils.rounded(weights[i]));
final double[] means = distributions[i].getMeans();
final double[] sd = distributions[i].getStandardDeviations();
for (int j = 0; j < means.length; j++) {
sb.append('\t').append(MathUtils.rounded(means[j])).append('\t').append(MathUtils.rounded(sd[j]));
}
tw.append(sb.toString());
}
}
}
use of uk.ac.sussex.gdsc.core.ij.BufferedTextWindow in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method showPairs.
/**
* Show the match pairs in a results table.
*
* <p>Adds an ROI painter for the original image source of results set 1 (if it is visible) to the
* table.
*
* @param results1 the first set of results
* @param pairs the pairs
* @param resultsWindow the results window
*/
private void showPairs(MemoryPeakResults results1, final List<PointPair> pairs, final TextWindow resultsWindow) {
if (!settings.showPairs) {
return;
}
final TextWindow pairsWindow = createPairsWindow(resultsWindow, results1.getSource());
pairsWindow.getTextPanel().clear();
final Ticker ticker = ImageJUtils.createTicker(pairs.size(), 0, "Writing pairs table");
try (final BufferedTextWindow bw = new BufferedTextWindow(pairsWindow)) {
final StringBuilder sb = new StringBuilder();
for (final PointPair pair : pairs) {
bw.append(addPairResult(sb, pair));
ticker.tick();
}
}
ImageJUtils.finished();
}
use of uk.ac.sussex.gdsc.core.ij.BufferedTextWindow in project GDSC-SMLM by aherbert.
the class FailCountManager method analyseData.
private void analyseData() {
final LocalList<FailCountData> failCountData = failCountDataRef.get();
if (failCountData.isEmpty()) {
IJ.error(TITLE, "No fail count data in memory");
return;
}
if (!showAnalysisDialog()) {
return;
}
final int maxCons = getMaxConsecutiveFailCount(failCountData);
final int maxFail = getMaxFailCount(failCountData);
// Create a set of fail counters
final LocalList<FailCounter> counters = new LocalList<>();
final TByteArrayList type = new TByteArrayList();
for (int i = 0; i <= maxCons; i++) {
counters.add(ConsecutiveFailCounter.create(i));
}
fill(type, counters, 0);
// The other counters are user configured.
// Ideally this would be a search to optimise the best parameters
// for each counter as any enumeration may be way off the mark.
// Note that 0 failures in a window can be scored using the consecutive fail counter.
int max = Math.min(maxFail, settings.getRollingCounterMaxAllowedFailures());
for (int fail = MathUtils.clip(1, maxFail, settings.getRollingCounterMinAllowedFailures()); fail <= max; fail++) {
// Note that n-1 failures in window n can be scored using the consecutive fail counter.
for (int window = Math.max(fail + 2, settings.getRollingCounterMinWindow()); window <= settings.getRollingCounterMaxWindow(); window++) {
counters.add(RollingWindowFailCounter.create(fail, window));
}
switch(checkCounters(counters)) {
case ANALYSE:
break;
case CONTINUE:
break;
case RETURN:
return;
default:
throw new IllegalStateException();
}
}
fill(type, counters, 1);
max = Math.min(maxFail, settings.getWeightedCounterMaxAllowedFailures());
for (int fail = MathUtils.min(maxFail, settings.getWeightedCounterMinAllowedFailures()); fail <= max; fail++) {
for (int w = settings.getWeightedCounterMinPassDecrement(); w <= settings.getWeightedCounterMaxPassDecrement(); w++) {
counters.add(WeightedFailCounter.create(fail, 1, w));
}
switch(checkCounters(counters)) {
case ANALYSE:
break;
case CONTINUE:
break;
case RETURN:
return;
default:
throw new IllegalStateException();
}
}
fill(type, counters, 2);
max = Math.min(maxFail, settings.getResettingCounterMaxAllowedFailures());
for (int fail = MathUtils.min(maxFail, settings.getResettingCounterMinAllowedFailures()); fail <= max; fail++) {
for (double f = settings.getResettingCounterMinResetFraction(); f <= settings.getResettingCounterMaxResetFraction(); f += settings.getResettingCounterIncResetFraction()) {
counters.add(ResettingFailCounter.create(fail, f));
}
switch(checkCounters(counters)) {
case ANALYSE:
break;
case CONTINUE:
break;
case RETURN:
return;
default:
throw new IllegalStateException();
}
}
fill(type, counters, 3);
for (int count = settings.getPassRateCounterMinAllowedCounts(); count <= settings.getPassRateCounterMaxAllowedCounts(); count++) {
for (double f = settings.getPassRateCounterMinPassRate(); f <= settings.getPassRateCounterMaxPassRate(); f += settings.getPassRateCounterIncPassRate()) {
counters.add(PassRateFailCounter.create(count, f));
}
switch(checkCounters(counters)) {
case ANALYSE:
break;
case CONTINUE:
break;
case RETURN:
return;
default:
throw new IllegalStateException();
}
}
fill(type, counters, 4);
counters.trimToSize();
// Score each of a set of standard fail counters against each frame using how
// close they are to the target.
final double[] score = new double[counters.size()];
final double targetPassFraction = settings.getTargetPassFraction();
final int nThreads = Prefs.getThreads();
final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
final LocalList<Future<?>> futures = new LocalList<>(nThreads);
final Ticker ticker = ImageJUtils.createTicker(failCountData.size(), nThreads);
IJ.showStatus("Analysing " + TextUtils.pleural(counters.size(), "counter"));
for (int i = 0; i < failCountData.size(); i++) {
final FailCountData data = failCountData.unsafeGet(i);
futures.add(executor.submit(() -> {
if (IJ.escapePressed()) {
return;
}
// TODO - Ideally this plugin should be run on benchmark data with ground truth.
// The target could be to ensure all the correct results are fit
// and false positives are excluded from incrementing the pass counter.
// This could be done by saving the results from a benchmarking scoring
// plugin to memory as the current dataset.
data.initialiseAnalysis(targetPassFraction);
// Score in blocks and then do a synchronized write to the combined score
final Thread t = Thread.currentThread();
final double[] s = new double[8192];
int index = 0;
while (index < counters.size()) {
if (t.isInterrupted()) {
break;
}
final int block = Math.min(8192, counters.size() - index);
for (int j = 0; j < block; j++) {
final FailCounter counter = counters.unsafeGet(index + j).newCounter();
s[j] = data.score(counter);
}
// Write to the combined score
synchronized (score) {
for (int j = 0; j < block; j++) {
score[index + j] += s[j];
}
}
index += block;
}
ticker.tick();
}));
}
executor.shutdown();
ConcurrencyUtils.waitForCompletionUnchecked(futures);
IJ.showProgress(1);
if (IJ.escapePressed()) {
IJ.showStatus("");
IJ.error(TITLE, "Cancelled analysis");
return;
}
IJ.showStatus("Summarising results ...");
// TODO - check if the top filter is at the bounds of the range
final int minIndex = SimpleArrayUtils.findMinIndex(score);
ImageJUtils.log(TITLE + " Analysis : Best counter = %s (Score = %f)", counters.unsafeGet(minIndex).getDescription(), score[minIndex]);
// Show a table of results for the top N for each type
final int topN = Math.min(settings.getTableTopN(), score.length);
if (topN > 0) {
final byte[] types = type.toArray();
final byte maxType = types[types.length - 1];
final TextWindow resultsWindow = createTable();
for (byte b = 0; b <= maxType; b++) {
int[] indices;
// Use a heap to avoid a full sort
final IntDoubleMinHeap heap = new IntDoubleMinHeap(topN);
for (int i = 0; i < score.length; i++) {
if (types[i] == b) {
heap.offer(score[i], i);
}
}
if (heap.getSize() == 0) {
continue;
}
indices = heap.getItems();
// Ensure sorted
SortUtils.sortIndices(indices, score, false);
final StringBuilder sb = new StringBuilder();
try (final BufferedTextWindow tw = new BufferedTextWindow(resultsWindow)) {
for (int i = 0; i < topN; i++) {
sb.setLength(0);
final int j = indices[i];
sb.append(i + 1).append('\t');
sb.append(counters.unsafeGet(j).getDescription()).append('\t');
sb.append(score[j]);
tw.append(sb.toString());
}
}
}
}
// TODO - Save the best fail counter to the current fit configuration.
IJ.showStatus("");
}
use of uk.ac.sussex.gdsc.core.ij.BufferedTextWindow in project GDSC-SMLM by aherbert.
the class SummariseResults method showSummary.
private static void showSummary(Collection<MemoryPeakResults> results, int[] removeNullResults) {
final TextWindow summary = createSummaryTable();
final StringBuilder sb = new StringBuilder();
try (BufferedTextWindow tw = new BufferedTextWindow(summary)) {
for (final MemoryPeakResults result : results) {
tw.append(createSummary(sb, result, removeNullResults));
}
tw.append("");
}
summary.toFront();
}
use of uk.ac.sussex.gdsc.core.ij.BufferedTextWindow in project GDSC-SMLM by aherbert.
the class ClassificationMatchCalculator method runCompareClassifications.
private void runCompareClassifications(MemoryPeakResults results1, MemoryPeakResults results2) {
final List<PointPair> allMatches = new LinkedList<>();
// Optionally exclude results which do not have an id and/or category
Predicate<PeakResult> test = settings.useId == ClassAnalysis.IGNORE_ZERO ? r -> r.getId() != 0 : null;
if (settings.useCategory == ClassAnalysis.IGNORE_ZERO) {
final Predicate<PeakResult> test2 = r -> r.getCategory() != 0;
test = test == null ? test2 : test.and(test2);
} else if (test == null) {
test = r -> true;
}
// Divide the results into time points
final TIntObjectHashMap<List<PeakResultPoint>> coordinates1 = getCoordinates(results1, test);
final TIntObjectHashMap<List<PeakResultPoint>> coordinates2 = getCoordinates(results2, test);
// Process each time point
int n1 = 0;
int n2 = 0;
for (final int t : getTimepoints(coordinates1, coordinates2)) {
final Coordinate[] c1 = getCoordinates(coordinates1, t);
final Coordinate[] c2 = getCoordinates(coordinates2, t);
n1 += c1.length;
n2 += c2.length;
final List<PointPair> matches = new LinkedList<>();
MatchCalculator.analyseResults3D(c1, c2, settings.matchDistance, null, null, null, matches);
allMatches.addAll(matches);
}
if (allMatches.isEmpty()) {
IJ.error(TITLE, "No localisation matches between the two results sets");
return;
}
// Get the unique Ids and Categories in the matches.
final Mapper ids = getMapper(allMatches, PeakResult::getId, settings.useId);
final Mapper cats = getMapper(allMatches, PeakResult::getCategory, settings.useCategory);
// Map id/category to an index = stride * cat + id
final int stride = ids.size();
// Any integer is allowed as an index
if ((long) stride * cats.size() > 1L << 32) {
IJ.error(TITLE, "Too many combinations of id and category to assigne unique labels");
return;
}
// Extract indices
final int[] set1 = new int[allMatches.size()];
final int[] set2 = new int[allMatches.size()];
int i = 0;
for (final PointPair r : allMatches) {
set1[i] = toIndex(stride, ids, cats, ((PeakResultPoint) r.getPoint1()).getPeakResult());
set2[i] = toIndex(stride, ids, cats, ((PeakResultPoint) r.getPoint2()).getPeakResult());
i++;
}
final Resequencer re = new Resequencer();
re.setCacheMap(true);
re.renumber(set1);
re.renumber(set2);
// Compare
final RandIndex r = new RandIndex().compute(set1, set2);
final TextWindow resultsWindow = ImageJUtils.refresh(resultsWindowRef, () -> new TextWindow(TITLE + " Results", "Results1\tResults2\tID\tCategory\tn1\tc1\tn2\tc2\tMatched\tRand Index\tAdjusted RI", "", 900, 300));
try (BufferedTextWindow bw = new BufferedTextWindow(resultsWindow)) {
final StringBuilder sb = new StringBuilder(2048);
sb.append(results1.getName()).append('\t');
sb.append(results2.getName()).append('\t');
sb.append(ANALYSIS_OPTION[settings.useId.ordinal()]).append('\t');
sb.append(ANALYSIS_OPTION[settings.useCategory.ordinal()]).append('\t');
sb.append(n1).append('\t');
sb.append(MathUtils.max(set1) + 1).append('\t');
sb.append(n2).append('\t');
sb.append(MathUtils.max(set2) + 1).append('\t');
sb.append(set1.length).append('\t');
sb.append(MathUtils.rounded(r.getRandIndex())).append('\t');
sb.append(MathUtils.rounded(r.getAdjustedRandIndex())).append('\t');
bw.append(sb.toString());
}
}
Aggregations