use of gdsc.core.match.ClassificationResult in project GDSC-SMLM by aherbert.
the class Filter method score.
/**
* Filter the results and return the performance score. Allows benchmarking the filter by marking the results as
* true or false.
* <p>
* Any input PeakResult with an original value that is not zero will be treated as a true result, all other results
* are false. The filter is run and the results are marked as true positive, false negative and false positive.
*
* @param resultsList
* a list of results to analyse
* @param tn
* The initial true negatives (used when the results have been pre-filtered)
* @param fn
* The initial false negatives (used when the results have been pre-filtered)
* @return
*/
public ClassificationResult score(List<MemoryPeakResults> resultsList, int tn, int fn) {
int tp = 0, fp = 0;
for (MemoryPeakResults peakResults : resultsList) {
setup(peakResults);
for (PeakResult peak : peakResults.getResults()) {
final boolean isTrue = peak.origValue != 0;
boolean isPositive = accept(peak);
if (isTrue) {
if (isPositive)
// true positive
tp++;
else
// false negative
fn++;
} else {
if (isPositive)
// false positive
fp++;
else
// true negative
tn++;
}
}
end();
}
return new ClassificationResult(tp, fp, tn, fn);
}
use of gdsc.core.match.ClassificationResult in project GDSC-SMLM by aherbert.
the class FilterAnalysis method calculateSensitivity.
private void calculateSensitivity(List<MemoryPeakResults> resultsList) {
if (!calculateSensitivity)
return;
if (!bestFilter.isEmpty()) {
IJ.showStatus("Calculating sensitivity ...");
createSensitivityWindow();
int currentIndex = 0;
for (String type : bestFilterOrder) {
IJ.showProgress(currentIndex++, bestFilter.size());
Filter filter = bestFilter.get(type).filter;
ClassificationResult s = filter.score(resultsList);
String message = type + "\t\t\t" + Utils.rounded(s.getJaccard(), 4) + "\t\t" + Utils.rounded(s.getPrecision(), 4) + "\t\t" + Utils.rounded(s.getRecall(), 4);
if (isHeadless) {
IJ.log(message);
} else {
sensitivityWindow.append(message);
}
// List all the parameters that can be adjusted.
final int parameters = filter.getNumberOfParameters();
for (int index = 0; index < parameters; index++) {
// For each parameter compute as upward + downward delta and get the average gradient
Filter higher = filter.adjustParameter(index, delta);
Filter lower = filter.adjustParameter(index, -delta);
ClassificationResult sHigher = higher.score(resultsList);
ClassificationResult sLower = lower.score(resultsList);
StringBuilder sb = new StringBuilder();
sb.append("\t").append(filter.getParameterName(index)).append("\t");
sb.append(Utils.rounded(filter.getParameterValue(index), 4)).append("\t");
double dx1 = higher.getParameterValue(index) - filter.getParameterValue(index);
double dx2 = filter.getParameterValue(index) - lower.getParameterValue(index);
addSensitivityScore(sb, s.getJaccard(), sHigher.getJaccard(), sLower.getJaccard(), dx1, dx2);
addSensitivityScore(sb, s.getPrecision(), sHigher.getPrecision(), sLower.getPrecision(), dx1, dx2);
addSensitivityScore(sb, s.getRecall(), sHigher.getRecall(), sLower.getRecall(), dx1, dx2);
if (isHeadless) {
IJ.log(sb.toString());
} else {
sensitivityWindow.append(sb.toString());
}
}
}
String message = "-=-=-=-";
if (isHeadless) {
IJ.log(message);
} else {
sensitivityWindow.append(message);
}
IJ.showProgress(1);
IJ.showStatus("");
}
}
use of gdsc.core.match.ClassificationResult in project GDSC-SMLM by aherbert.
the class FilterAnalysis method run.
private int run(FilterSet filterSet, List<MemoryPeakResults> resultsList, int count, final int total) {
double[] xValues = (isHeadless) ? null : new double[filterSet.size()];
double[] yValues = (isHeadless) ? null : new double[filterSet.size()];
int i = 0;
filterSet.sort();
// Track if all the filters are the same type. If so then we can calculate the sensitivity of each parameter.
String type = null;
boolean allSameType = true;
Filter maxFilter = null;
double maxScore = -1;
for (Filter filter : filterSet.getFilters()) {
if (count++ % 16 == 0)
IJ.showProgress(count, total);
ClassificationResult s = run(filter, resultsList);
if (type == null)
type = filter.getType();
else if (!type.equals(filter.getType()))
allSameType = false;
final double jaccard = s.getJaccard();
if (filter == null || maxScore < jaccard) {
maxScore = jaccard;
maxFilter = filter;
}
if (!isHeadless) {
xValues[i] = filter.getNumericalValue();
yValues[i++] = jaccard;
}
}
if (allSameType && calculateSensitivity) {
FilterScore filterScore = bestFilter.get(type);
if (filterScore != null) {
if (filterScore.score < maxScore)
filterScore.update(maxFilter, maxScore);
} else {
bestFilter.put(type, new FilterScore(maxFilter, maxScore));
bestFilterOrder.add(type);
}
}
// Add spacer at end of each result set
if (isHeadless) {
if (showResultsTable)
IJ.log("");
} else {
if (showResultsTable)
resultsWindow.append("");
if (plotTopN > 0) {
// Check the xValues are unique. Since the filters have been sorted by their
// numeric value we only need to compare adjacent entries.
boolean unique = true;
for (int ii = 0; ii < xValues.length - 1; ii++) {
if (xValues[ii] == xValues[ii + 1]) {
unique = false;
break;
}
}
String xAxisName = filterSet.getValueName();
// Check the values all refer to the same property
for (Filter filter : filterSet.getFilters()) {
if (!xAxisName.equals(filter.getNumericalValueName())) {
unique = false;
break;
}
}
if (!unique) {
// If not unique then renumber them and use an arbitrary label
xAxisName = "Filter";
for (int ii = 0; ii < xValues.length; ii++) xValues[ii] = ii + 1;
}
String title = filterSet.getName();
// Check if a previous filter set had the same name, update if necessary
NamedPlot p = getNamedPlot(title);
if (p == null)
plots.add(new NamedPlot(title, xAxisName, xValues, yValues));
else
p.updateValues(xAxisName, xValues, yValues);
if (plots.size() > plotTopN) {
Collections.sort(plots);
p = plots.remove(plots.size() - 1);
}
}
}
return count;
}
Aggregations