use of uk.ac.sussex.gdsc.smlm.results.PeakResultPoint in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method savePairs.
private void savePairs(MemoryPeakResults results1, MemoryPeakResults results2, List<PointPair> allMatches) {
if (!settings.savePairs) {
return;
}
// Get the directory
final String directory = ImageJUtils.getDirectory("Pairs_directory", settings.pairsDirectory);
if (directory == null) {
return;
}
settings.pairsDirectory = directory;
final double[] distanceThresholds = getDistances(settings.distanceThreshold, settings.increments, settings.delta);
// Create output files for each distance band
final PeakResults[] output1 = new PeakResults[distanceThresholds.length];
final PeakResults[] output2 = new PeakResults[distanceThresholds.length];
double high = 0;
for (int i = 0; i < distanceThresholds.length; i++) {
final double low = high;
high = distanceThresholds[i];
output1[i] = createFilePeakResults(directory, 1, results1, low, high);
output2[i] = createFilePeakResults(directory, 2, results2, low, high);
}
// Square the thresholds
SimpleArrayUtils.apply(distanceThresholds, v -> v * v);
final double[] pairDistances = getPairDistances(allMatches);
int index = 0;
for (final PointPair pair : allMatches) {
final int insert = search(distanceThresholds, pairDistances[index++]);
if (insert != -1) {
final PeakResult r1 = ((PeakResultPoint) pair.getPoint1()).getPeakResult();
final PeakResult r2 = ((PeakResultPoint) pair.getPoint2()).getPeakResult();
output1[insert].add(r1);
output2[insert].add(r2);
}
}
for (int i = 0; i < output1.length; i++) {
output1[i].end();
output2[i].end();
}
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResultPoint in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method showResults.
@SuppressWarnings("null")
private void showResults(MemoryPeakResults results1, MemoryPeakResults results2, final List<PointPair> allMatches, int n1, int n2, final boolean doIdAnalysis1, final boolean doIdAnalysis2, TextWindow resultsWindow) {
if (!settings.showTable) {
return;
}
// Output the results
Consumer<String> output;
if (resultsWindow != null) {
output = resultsWindow::append;
} else {
// Headless mode
output = IJ::log;
if (writeHeader.get()) {
writeHeader.set(false);
IJ.log(createResultsHeader(settings.idAnalysis));
}
}
// We have the results for the largest distance.
// Now reduce the distance threshold and recalculate the results
final double[] distanceThresholds = getDistances(settings.distanceThreshold, settings.increments, settings.delta);
final double[] pairDistances = getPairDistances(allMatches);
// Re-use storage for the ID analysis
TIntHashSet id1 = null;
TIntHashSet id2 = null;
TIntHashSet matchId1 = null;
TIntHashSet matchId2 = null;
final boolean doIdAnalysis = doIdAnalysis1 || doIdAnalysis2;
if (doIdAnalysis) {
if (doIdAnalysis1) {
id1 = getIds(results1);
matchId1 = new TIntHashSet(id1.size());
}
if (doIdAnalysis2) {
id2 = getIds(results2);
matchId2 = new TIntHashSet(id2.size());
}
}
final StringBuilder sb = new StringBuilder();
for (final double distanceThreshold : distanceThresholds) {
double rms = 0;
int tp2 = 0;
final double d2 = distanceThreshold * distanceThreshold;
for (final double d : pairDistances) {
if (d <= d2) {
rms += d;
tp2++;
}
}
// All non-true positives must be added to the false totals.
final int fp2 = n2 - tp2;
final int fn2 = n1 - tp2;
// RMSD to be the root mean square deviation in a single dimension so divide by 2.
// (This assumes 2D Euclidean distances.)
final MatchResult result = new MatchResult(tp2, fp2, fn2, Math.sqrt(MathUtils.div0(rms / 2, tp2)));
MatchResult idResult1 = null;
MatchResult idResult2 = null;
if (doIdAnalysis) {
if (doIdAnalysis1) {
matchId1.clear();
}
if (doIdAnalysis2) {
matchId2.clear();
}
int index = 0;
for (final PointPair pair : allMatches) {
if (pairDistances[index++] <= d2) {
if (doIdAnalysis1) {
matchId1.add(((PeakResultPoint) pair.getPoint1()).getPeakResult().getId());
}
if (doIdAnalysis2) {
matchId2.add(((PeakResultPoint) pair.getPoint2()).getPeakResult().getId());
}
}
}
// => Only the recall will be valid: tp / (tp + fn)
if (doIdAnalysis1) {
idResult1 = new MatchResult(matchId1.size(), 0, id1.size() - matchId1.size(), 0);
}
if (doIdAnalysis2) {
idResult2 = new MatchResult(matchId2.size(), 0, id2.size() - matchId2.size(), 0);
}
}
addResult(sb, settings.inputOption1, settings.inputOption2, distanceThreshold, result, idResult1, idResult2);
output.accept(sb.toString());
}
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResultPoint in project GDSC-SMLM by aherbert.
the class ClassificationMatchCalculator method getTimepoints.
/**
* Merge the time points from each map into a single sorted list of unique time points.
*
* @param actualCoordinates the actual coordinates
* @param predictedCoordinates the predicted coordinates
* @return a list of time points
*/
private static int[] getTimepoints(TIntObjectHashMap<List<PeakResultPoint>> actualCoordinates, TIntObjectHashMap<List<PeakResultPoint>> predictedCoordinates) {
// Do inline to avoid materialising the keys arrays
final TIntHashSet hashset = new TIntHashSet(Math.max(actualCoordinates.size(), predictedCoordinates.size()));
final TIntProcedure p = value -> {
hashset.add(value);
return true;
};
actualCoordinates.forEachKey(p);
predictedCoordinates.forEachKey(p);
final int[] set = hashset.toArray();
Arrays.sort(set);
return set;
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResultPoint in project GDSC-SMLM by aherbert.
the class ClassificationMatchCalculator method getCoordinates.
/**
* Build a map between the peak id (time point) and a list of coordinates that pass the filter.
*
* @param results the results
* @param test the test
* @return the coordinates
*/
public static TIntObjectHashMap<List<PeakResultPoint>> getCoordinates(MemoryPeakResults results, Predicate<PeakResult> test) {
final TIntObjectHashMap<List<PeakResultPoint>> coords = new TIntObjectHashMap<>();
if (results.size() > 0) {
// Do not use HashMap directly to build the coords object since there
// will be many calls to getEntry(). Instead sort the results and use
// a new list for each time point
results.sort();
// Create list
final LocalList<PeakResultPoint> tmpCoords = new LocalList<>();
// Add the results for each frame
final FrameCounter counter = results.newFrameCounter();
results.forEach(DistanceUnit.PIXEL, (XyzrResultProcedure) (x, y, z, r) -> {
if (counter.advance(r.getFrame()) && !tmpCoords.isEmpty()) {
coords.put(counter.previousFrame(), tmpCoords.copy());
tmpCoords.clear();
}
if (test.test(r)) {
tmpCoords.add(new PeakResultPoint(r.getFrame(), x, y, z, r));
}
});
if (!tmpCoords.isEmpty()) {
coords.put(counter.currentFrame(), tmpCoords.copy());
}
}
return coords;
}
use of uk.ac.sussex.gdsc.smlm.results.PeakResultPoint in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method runCompareCoordinates.
@SuppressWarnings("null")
private void runCompareCoordinates(MemoryPeakResults results1, MemoryPeakResults results2) {
final boolean requirePairs = settings.showPairs || settings.isSaveClassifications();
final boolean saveMatched = settings.isSaveMatched();
final boolean saveUnmatched = settings.isSaveUnmatched();
final TextFilePeakResults fileResults = createFilePeakResults(results2);
final List<PointPair> allMatches = new LinkedList<>();
final List<PointPair> pairs = (requirePairs) ? new LinkedList<>() : null;
final double maxDistance = settings.distanceThreshold + settings.increments * settings.delta;
// Divide the results into time points
final TIntObjectHashMap<List<Coordinate>> actualCoordinates = getCoordinates(results1, settings.coordinateMethod1);
final TIntObjectHashMap<List<Coordinate>> predictedCoordinates = getCoordinates(results2, settings.coordinateMethod2);
int n1 = 0;
int n2 = 0;
// Process each time point
for (final int t : getTimepoints(actualCoordinates, predictedCoordinates)) {
final Coordinate[] actual = getCoordinates(actualCoordinates, t);
final Coordinate[] predicted = getCoordinates(predictedCoordinates, t);
final List<Coordinate> tp = null;
List<Coordinate> fp = null;
List<Coordinate> fn = null;
final List<PointPair> matches = new LinkedList<>();
if (requirePairs) {
fp = new LinkedList<>();
fn = new LinkedList<>();
}
MatchCalculator.analyseResults2D(actual, predicted, maxDistance, tp, fp, fn, matches);
// Aggregate
n1 += actual.length;
n2 += predicted.length;
allMatches.addAll(matches);
if (settings.showPairs) {
pairs.addAll(matches);
for (final Coordinate c : fn) {
pairs.add(new PointPair(c, null));
}
for (final Coordinate c : fp) {
pairs.add(new PointPair(null, c));
}
}
if (fileResults != null) {
// Matches are marked in the original value with 1 for true, 0 for false
if (saveMatched) {
for (final PointPair pair : matches) {
PeakResult result = ((PeakResultPoint) pair.getPoint2()).getPeakResult();
result = result.copy();
result.setOrigValue(1);
fileResults.add(result);
}
}
if (saveUnmatched) {
for (final Coordinate c : fp) {
PeakResult result = ((PeakResultPoint) c).getPeakResult();
result = result.copy();
result.setOrigValue(0);
fileResults.add(result);
}
}
}
}
if (fileResults != null) {
fileResults.end();
}
final boolean doIdAnalysis1 = settings.idAnalysis && haveIds(results1);
final boolean doIdAnalysis2 = settings.idAnalysis && haveIds(results2);
// Create output.
// This supports headless mode with just the results table
// or graphical mode with a results table and pairs window.
final boolean headless = java.awt.GraphicsEnvironment.isHeadless();
TextWindow resultsWindow = null;
if (!headless) {
resultsWindow = (settings.showTable) ? createResultsWindow(doIdAnalysis1 || doIdAnalysis2) : null;
showPairs(results1, pairs, resultsWindow);
}
showResults(results1, results2, allMatches, n1, n2, doIdAnalysis1, doIdAnalysis2, resultsWindow);
savePairs(results1, results2, allMatches);
}
Aggregations