use of gdsc.core.match.Coordinate in project GDSC-SMLM by aherbert.
the class SpotFinderPreview method run.
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#run(ij.process.ImageProcessor)
*/
public void run(ImageProcessor ip) {
Rectangle bounds = ip.getRoi();
MaximaSpotFilter filter = config.createSpotFilter(true);
// Crop to the ROI
FloatProcessor fp = ip.crop().toFloat(0, null);
float[] data = (float[]) fp.getPixels();
int width = fp.getWidth();
int height = fp.getHeight();
Spot[] spots = filter.rank(data, width, height);
data = filter.getPreprocessedData();
fp = new FloatProcessor(width, height, data);
ip = ip.duplicate();
ip.insert(fp, bounds.x, bounds.y);
//ip.resetMinAndMax();
ip.setMinAndMax(fp.getMin(), fp.getMax());
Overlay o = new Overlay();
o.add(new ImageRoi(0, 0, ip));
if (label != null) {
// Get results for frame
Coordinate[] actual = ResultsMatchCalculator.getCoordinates(actualCoordinates, imp.getCurrentSlice());
Coordinate[] predicted = new Coordinate[spots.length];
for (int i = 0; i < spots.length; i++) {
predicted[i] = new BasePoint(spots[i].x + bounds.x, spots[i].y + bounds.y);
}
// Q. Should this use partial scoring with multi-matches allowed.
// If so then this needs to be refactored out of the BenchmarkSpotFilter class.
// TODO - compute AUC and max jaccard and plot
// Compute matches
List<PointPair> matches = new ArrayList<PointPair>(Math.min(actual.length, predicted.length));
List<Coordinate> FP = new ArrayList<Coordinate>(predicted.length);
MatchResult result = MatchCalculator.analyseResults2D(actual, predicted, distance * fitConfig.getInitialPeakStdDev0(), null, FP, null, matches);
// Show scores
setLabel(String.format("P=%s, R=%s, J=%s", Utils.rounded(result.getPrecision()), Utils.rounded(result.getRecall()), Utils.rounded(result.getJaccard())));
// Create Rois for TP and FP
if (showTP) {
float[] x = new float[matches.size()];
float[] y = new float[x.length];
int n = 0;
for (PointPair pair : matches) {
BasePoint p = (BasePoint) pair.getPoint2();
x[n] = p.getX() + 0.5f;
y[n] = p.getY() + 0.5f;
n++;
}
addRoi(0, o, x, y, n, Color.green);
}
if (showFP) {
float[] x = new float[predicted.length - matches.size()];
float[] y = new float[x.length];
int n = 0;
for (Coordinate c : FP) {
BasePoint p = (BasePoint) c;
x[n] = p.getX() + 0.5f;
y[n] = p.getY() + 0.5f;
n++;
}
addRoi(0, o, x, y, n, Color.red);
}
} else {
float[] x = new float[spots.length];
float[] y = new float[x.length];
for (int i = 0; i < spots.length; i++) {
x[i] = spots[i].x + bounds.x + 0.5f;
y[i] = spots[i].y + bounds.y + 0.5f;
}
PointRoi roi = new PointRoi(x, y);
// Add options to configure colour and labels
o.add(roi);
}
imp.setOverlay(o);
}
use of gdsc.core.match.Coordinate in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method compareCoordinates.
private void compareCoordinates(MemoryPeakResults results1, MemoryPeakResults results2, double dThreshold, int increments, double delta) {
boolean requirePairs = showPairs || saveClassifications;
FilePeakResults fileResults = createFilePeakResults(results2);
List<PointPair> allMatches = new LinkedList<PointPair>();
List<PointPair> pairs = (requirePairs) ? new LinkedList<PointPair>() : null;
List<PeakResult> actualPoints = results1.getResults();
List<PeakResult> predictedPoints = results2.getResults();
double maxDistance = dThreshold + increments * delta;
// Old implementation
//// Process each time point
//for (Integer t : getTimepoints(actualPoints, predictedPoints))
//{
// Coordinate[] actual = getCoordinates(actualPoints, t);
// Coordinate[] predicted = getCoordinates(predictedPoints, t);
// Divide the results into time points
TIntObjectHashMap<ArrayList<Coordinate>> actualCoordinates = getCoordinates(actualPoints);
TIntObjectHashMap<ArrayList<Coordinate>> predictedCoordinates = getCoordinates(predictedPoints);
int n1 = 0;
int n2 = 0;
// Process each time point
for (Integer t : getTimepoints(actualCoordinates, predictedCoordinates)) {
Coordinate[] actual = getCoordinates(actualCoordinates, t);
Coordinate[] predicted = getCoordinates(predictedCoordinates, t);
List<Coordinate> TP = null;
List<Coordinate> FP = null;
List<Coordinate> FN = null;
List<PointPair> matches = new LinkedList<PointPair>();
if (requirePairs) {
FP = new LinkedList<Coordinate>();
FN = new LinkedList<Coordinate>();
}
MatchCalculator.analyseResults2D(actual, predicted, maxDistance, TP, FP, FN, matches);
// Aggregate
n1 += actual.length;
n2 += predicted.length;
allMatches.addAll(matches);
if (showPairs) {
pairs.addAll(matches);
for (Coordinate c : FN) pairs.add(new PointPair(c, null));
for (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
for (PointPair pair : matches) {
PeakResult p = ((PeakResultPoint) pair.getPoint2()).peakResult;
fileResults.add(p.getFrame(), p.origX, p.origY, 1, p.error, p.noise, p.params, null);
}
for (Coordinate c : FP) {
PeakResult p = ((PeakResultPoint) c).peakResult;
fileResults.add(p.getFrame(), p.origX, p.origY, 0, p.error, p.noise, p.params, null);
}
}
}
if (fileResults != null)
fileResults.end();
// XXX : DEBUGGING : Output for signal correlation and fitting analysis
/*
* try
* {
* OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("/tmp/ResultsMatchCalculator.txt"));
* FilePeakResults r1 = new FilePeakResults("/tmp/" + results1.getName() + ".txt", false);
* FilePeakResults r2 = new FilePeakResults("/tmp/" + results2.getName() + ".txt", false);
* r1.begin();
* r2.begin();
* //OutputStreamWriter o2 = new OutputStreamWriter(new FileOutputStream("/tmp/"+results1.getName()+".txt"));
* //OutputStreamWriter o3 = new OutputStreamWriter(new FileOutputStream("/tmp/"+results2.getName()+".txt"));
* for (PointPair pair : allMatches)
* {
* PeakResult p1 = ((PeakResultPoint) pair.getPoint1()).peakResult;
* PeakResult p2 = ((PeakResultPoint) pair.getPoint2()).peakResult;
* r1.add(p1);
* r2.add(p2);
* o.write(Float.toString(p1.getSignal()));
* o.write('\t');
* o.write(Float.toString(p2.getSignal()));
* o.write('\n');
* }
* o.close();
* r1.end();
* r2.end();
* }
* catch (Exception e)
* {
* e.printStackTrace();
* }
*/
boolean doIdAnalysis1 = (idAnalysis) ? haveIds(results1) : false;
boolean doIdAnalysis2 = (idAnalysis) ? haveIds(results2) : false;
boolean doIdAnalysis = doIdAnalysis1 || doIdAnalysis2;
// Create output
if (!java.awt.GraphicsEnvironment.isHeadless()) {
String header = createResultsHeader(doIdAnalysis);
Utils.refreshHeadings(resultsWindow, header, true);
if (showTable && (resultsWindow == null || !resultsWindow.isShowing())) {
resultsWindow = new TextWindow(TITLE + " Results", header, "", 900, 300);
}
if (showPairs) {
if (pairsWindow == null || !pairsWindow.isShowing()) {
pairsWindow = new TextWindow(TITLE + " Pairs", createPairsHeader(pairs), "", 900, 300);
if (resultsWindow != null) {
Point p = resultsWindow.getLocation();
p.y += resultsWindow.getHeight();
pairsWindow.setLocation(p);
}
pairPainter = new ImageROIPainter(pairsWindow.getTextPanel(), "", this);
}
pairsWindow.getTextPanel().clear();
String title = "Results 1";
if (results1.getSource() != null && results1.getSource().getOriginal().getName().length() > 0)
title = results1.getSource().getOriginal().getName();
pairPainter.setTitle(title);
IJ.showStatus("Writing pairs table");
IJ.showProgress(0);
int c = 0;
final int total = pairs.size();
final int step = Utils.getProgressInterval(total);
final ArrayList<String> list = new ArrayList<String>(total);
boolean flush = true;
for (PointPair pair : pairs) {
if (++c % step == 0)
IJ.showProgress(c, total);
list.add(addPairResult(pair));
if (flush && c == 9) {
pairsWindow.getTextPanel().append(list);
list.clear();
flush = false;
}
}
pairsWindow.getTextPanel().append(list);
IJ.showProgress(1);
}
} else {
if (writeHeader && showTable) {
writeHeader = false;
IJ.log(createResultsHeader(idAnalysis));
}
}
if (!showTable)
return;
// We have the results for the largest distance.
// Now reduce the distance threshold and recalculate the results
double[] distanceThresholds = getDistances(dThreshold, increments, delta);
double[] pairDistances = getPairDistances(allMatches);
// Re-use storage for the ID analysis
TIntHashSet id1 = null, id2 = null, matchId1 = null, matchId2 = null;
if (doIdAnalysis) {
if (doIdAnalysis1) {
id1 = getIds(results1);
matchId1 = new TIntHashSet(id1.size());
}
if (doIdAnalysis2) {
id2 = getIds(results2);
matchId2 = new TIntHashSet(id2.size());
}
}
for (double distanceThreshold : distanceThresholds) {
double rms = 0;
int tp2 = 0;
final double d2 = distanceThreshold * distanceThreshold;
for (double d : pairDistances) {
if (d <= d2) {
rms += d;
tp2++;
}
}
// All non-true positives must be added to the false totals.
int fp2 = n2 - tp2;
int fn2 = n1 - tp2;
MatchResult result = new MatchResult(tp2, fp2, fn2, (tp2 > 0) ? Math.sqrt(rms / tp2) : 0);
MatchResult idResult1 = null, idResult2 = null;
if (doIdAnalysis) {
if (doIdAnalysis1)
matchId1.clear();
if (doIdAnalysis2)
matchId2.clear();
int i = 0;
for (PointPair pair : allMatches) {
if (pairDistances[i++] <= d2) {
if (doIdAnalysis1)
matchId1.add(((PeakResultPoint) pair.getPoint1()).peakResult.getId());
if (doIdAnalysis2)
matchId2.add(((PeakResultPoint) pair.getPoint2()).peakResult.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(inputOption1, inputOption2, distanceThreshold, result, idResult1, idResult2);
}
}
use of gdsc.core.match.Coordinate in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method getCoordinates.
/**
* Build a map between the peak id (time point) and a list of coordinates
*
* @param results
* @param integerCoordinates
* True if the values should be rounded down to integers
* @return
*/
public static TIntObjectHashMap<ArrayList<Coordinate>> getCoordinates(List<PeakResult> results, boolean integerCoordinates) {
TIntObjectHashMap<ArrayList<Coordinate>> coords = new TIntObjectHashMap<ArrayList<Coordinate>>();
if (results.size() > 0) {
ResultsMatchCalculator instance = new ResultsMatchCalculator();
// 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
Collections.sort(results);
int minT = results.get(0).getFrame();
int maxT = results.get(results.size() - 1).getEndFrame();
// Create lists
ArrayList<ArrayList<Coordinate>> tmpCoords = new ArrayList<ArrayList<Coordinate>>(maxT - minT + 1);
for (int t = minT; t <= maxT; t++) {
tmpCoords.add(new ArrayList<Coordinate>());
}
// Add the results to the lists
for (PeakResult p : results) {
final float x, y;
if (integerCoordinates) {
x = (int) p.getXPosition();
y = (int) p.getYPosition();
} else {
x = p.getXPosition();
y = p.getYPosition();
}
for (int t = p.getFrame() - minT, i = p.getEndFrame() - p.getFrame() + 1; i-- > 0; t++) tmpCoords.get(t).add(instance.new PeakResultPoint(t + minT, x, y, p));
}
// Put in the map
for (int t = minT, i = 0; t <= maxT; t++, i++) {
coords.put(t, tmpCoords.get(i));
}
}
return coords;
}
use of gdsc.core.match.Coordinate in project GDSC-SMLM by aherbert.
the class TraceMatchCalculator method compareCoordinates.
private void compareCoordinates(MemoryPeakResults results1, MemoryPeakResults results2, MemoryPeakResults results3, double dThreshold) {
Pulse[] p1 = extractPulses(results1);
Pulse[] p2 = extractPulses(results2);
Pulse[] p3 = extractPulses(results3);
List<Pulse> TP = null;
List<Pulse> FP = null;
List<Pulse> FN = null;
List<PointPair> pairs = null;
List<Pulse> TP2 = null;
List<Pulse> FP2 = null;
List<Pulse> FN2 = null;
List<PointPair> pairs2 = null;
if (showPairs) {
pairs = new LinkedList<PointPair>();
FP = new LinkedList<Pulse>();
FN = new LinkedList<Pulse>();
pairs2 = new LinkedList<PointPair>();
FP2 = new LinkedList<Pulse>();
FN2 = new LinkedList<Pulse>();
}
MatchResult result = MatchCalculator.analyseResults2D(p1, p2, dThreshold, TP, FP, FN, pairs);
MatchResult result2 = MatchCalculator.analyseResults2D(p1, p3, dThreshold, TP2, FP2, FN2, pairs2);
// Create output
if (!java.awt.GraphicsEnvironment.isHeadless()) {
if (resultsWindow == null || !resultsWindow.isShowing()) {
resultsWindow = new TextWindow(TITLE + " Results", createResultsHeader(), "", 900, 300);
}
if (showPairs) {
if (p3 == null) {
// Produce a pairs output
if (pairsWindow == null || !pairsWindow.isShowing()) {
pairsWindow = new TextWindow(TITLE + " Pairs", createPairsHeader(), "", 900, 300);
Point p = resultsWindow.getLocation();
p.y += resultsWindow.getHeight();
pairsWindow.setLocation(p);
pairPainter = new ImageROIPainter(pairsWindow.getTextPanel(), results1.getSource().getOriginal().getName(), this);
}
pairsWindow.getTextPanel().clear();
pairPainter.setTitle(results1.getSource().getOriginal().getName());
// Add the unmatched points
for (Coordinate c : FN) pairs.add(new PointPair(c, null));
for (Coordinate c : FP) pairs.add(new PointPair(null, c));
List<? extends PointPair> sortedPairs = sort(pairs);
for (PointPair pair : sortedPairs) addPairResult(pair);
} else {
// Produce a triple output
if (triplesWindow == null || !triplesWindow.isShowing()) {
triplesWindow = new TextWindow(TITLE + " Triples", createTriplesHeader(), "", 900, 300);
Point p = resultsWindow.getLocation();
p.y += resultsWindow.getHeight();
triplesWindow.setLocation(p);
triplePainter = new ImageROIPainter(triplesWindow.getTextPanel(), results1.getSource().getName(), this);
}
triplesWindow.getTextPanel().clear();
triplePainter.setTitle(results1.getSource().getOriginal().getName());
HashMap<Pulse, Triple> map = new HashMap<Pulse, Triple>();
ArrayList<Triple> triples = new ArrayList<Triple>(pairs.size());
for (PointPair pair : pairs) {
Pulse p = (Pulse) pair.getPoint1();
Triple t = new Triple(p, (Pulse) pair.getPoint2(), null);
triples.add(t);
map.put(p, t);
}
// Complete the reference set of points
for (Coordinate c : FN) {
Pulse p = (Pulse) c;
Triple t = new Triple(p, null, null);
triples.add(t);
map.put(p, t);
}
// Add the unmatched points
for (Coordinate c : FP) triples.add(new Triple(null, (Pulse) c, null));
for (Coordinate c : FP2) triples.add(new Triple(null, null, (Pulse) c));
// Add the results from the second match
for (PointPair pair : pairs2) {
Pulse p = (Pulse) pair.getPoint1();
Pulse pp = (Pulse) pair.getPoint2();
Triple t = map.get(p);
if (t != null) {
t.p3 = pp;
} else {
triples.add(new Triple(null, null, pp));
}
}
List<? extends Triple> sortedTriples = sort(triples);
for (Triple t : sortedTriples) addTripleResult(t);
}
}
} else {
if (writeHeader) {
writeHeader = false;
IJ.log(createResultsHeader());
}
}
addResult(inputOption1, inputOption2, dThreshold, result);
if (p3 != null)
addResult(inputOption1, inputOption3, dThreshold, result2);
}
use of gdsc.core.match.Coordinate in project GDSC-SMLM by aherbert.
the class ResultsMatchCalculator method compareCoordinates.
/**
* Compare the coordinates on a frame-by-frame basis.
*
* @param actualCoordinates
* the actual coordinates
* @param predictedCoordinates
* the predicted coordinates
* @param distance
* the distance
* @return the match result
*/
public static MatchResult compareCoordinates(TIntObjectHashMap<ArrayList<Coordinate>> actualCoordinates, TIntObjectHashMap<ArrayList<Coordinate>> predictedCoordinates, double distance) {
int tp = 0;
int fp = 0;
int fn = 0;
// Process each time point
for (Integer t : getTimepoints(actualCoordinates, predictedCoordinates)) {
Coordinate[] actual = getCoordinates(actualCoordinates, t);
Coordinate[] predicted = getCoordinates(predictedCoordinates, t);
MatchResult r = MatchCalculator.analyseResults2D(actual, predicted, distance);
// Aggregate
tp += r.getTruePositives();
fp += r.getFalsePositives();
fn += r.getFalseNegatives();
}
return new MatchResult(tp, fp, fn, 0);
}
Aggregations