use of uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method componentAnalysis.
private void componentAnalysis(ComplexFilterScore bestFilterScore) {
if (settings.componentAnalysis == 0) {
return;
}
final Consumer<String> output = createComponentAnalysisWindow();
final DirectFilter localBestFilter = bestFilterScore.getFilter();
final String[] names = getNames(localBestFilter);
// Skip disabled parameters
int paramCount = localBestFilter.getNumberOfParameters();
final boolean[] enable = new boolean[paramCount];
final int[] map = new int[paramCount];
for (int n = 0, i = 0; n < map.length; n++) {
if (localBestFilter.getParameterValue(n) == localBestFilter.getDisabledParameterValue(n)) {
// Mark to ignore
enable[n] = true;
paramCount--;
} else {
map[i++] = n;
}
}
// Score the best filter just so we have the unique Ids of the results
scoreComponents(localBestFilter, -1, paramCount, null, null, null, 0);
final int[] uniqueIds1 = uniqueIds;
final int uniqueIdCount1 = uniqueIdCount;
// Limit to 12 params == 4095 combinations (this is the max for two multi filters combined)
if (settings.componentAnalysis >= 3 && paramCount <= 12) {
// Enumeration of combinations
final long count = countComponentCombinations(paramCount);
// Enumerate all combinations
final ComplexFilterScore[] localScores = new ComplexFilterScore[(int) count];
int index = 0;
for (int k = 1; k <= paramCount; k++) {
final Iterator<int[]> it = CombinatoricsUtils.combinationsIterator(paramCount, k);
while (it.hasNext()) {
final int[] combinations = it.next();
final boolean[] enable2 = enable.clone();
for (int i = 0; i < k; i++) {
combinations[i] = map[combinations[i]];
enable2[combinations[i]] = true;
}
final DirectFilter f = (DirectFilter) localBestFilter.create(enable2);
localScores[index++] = scoreComponents(f, 0, k, combinations, enable2, uniqueIds1, uniqueIdCount1);
}
}
// Report
Arrays.sort(localScores, FilterScoreCompararor.INSTANCE);
int lastSize = 0;
for (int i = 0; i < localScores.length; i++) {
if (settings.componentAnalysis == 3) {
if (lastSize == localScores[i].size) {
// Only add the best result for each size
continue;
}
lastSize = localScores[i].size;
}
// Find the last component that was added
if (localScores[i].size == 1) {
localScores[i].index = localScores[i].combinations[0];
} else {
// For each size k, find the best result with k-1 components and set the add index
// appropriately
int add = -1;
int target = -1;
for (int l = 0; l < enable.length; l++) {
if (localScores[i].enable[l]) {
target++;
}
}
final int size1 = localScores[i].size - 1;
for (int ii = 0; ii < i; ii++) {
if (localScores[ii].size < size1) {
continue;
}
if (localScores[ii].size > size1) {
// Broken
break;
}
// Count matches. It must be 1 less than the current result
int matches = 0;
for (int l = 0; l < enable.length; l++) {
if (localScores[i].enable[l] && localScores[ii].enable[l]) {
matches++;
}
}
if (matches == target) {
// Find the additional parameter added
for (int l = 0; l < enable.length; l++) {
if (localScores[i].enable[l]) {
if (!localScores[ii].enable[l]) {
add = l;
break;
}
}
}
break;
}
}
localScores[i].index = add;
}
addToComponentAnalysisWindow(output, localScores[i], bestFilterScore, names);
}
return;
}
// Preserve the option to output the best or all results if we fell through from above
final int myComponentAnalysis = (settings.componentAnalysis >= 3) ? settings.componentAnalysis - 2 : settings.componentAnalysis;
// Progressively add components until all are the same as the input bestFilter
int enabled = 0;
int[] previousCombinations = new int[0];
for (int ii = 0; ii < paramCount; ii++) {
// Create a set of filters by enabling each component that is not currently enabled.
final ComplexFilterScore[] localScores = new ComplexFilterScore[paramCount - enabled];
final int k = enabled + 1;
for (int i = 0, j = 0; i < paramCount; i++) {
final int n = map[i];
if (enable[n]) {
continue;
}
enable[n] = true;
final DirectFilter f = (DirectFilter) localBestFilter.create(enable);
enable[n] = false;
final int[] combinations = new int[k];
System.arraycopy(previousCombinations, 0, combinations, 0, previousCombinations.length);
combinations[k - 1] = n;
Arrays.sort(combinations);
localScores[j++] = scoreComponents(f, n, k, combinations, null, uniqueIds1, uniqueIdCount1);
}
// Rank them
Arrays.sort(localScores);
for (int i = 0; i < localScores.length; i++) {
addToComponentAnalysisWindow(output, localScores[i], bestFilterScore, names);
if (myComponentAnalysis == 1) {
// Only add the best result
break;
}
}
// Flag the best component added
enable[localScores[0].index] = true;
enabled++;
previousCombinations = localScores[0].combinations;
}
}
use of uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method runAnalysis.
private void runAnalysis(List<FilterSet> filterSets, ComplexFilterScore optimum, double rangeReduction) {
filterAnalysisResult.plots.clear();
filterAnalysisResult.bestFilter.clear();
getCoordinateStore();
filterAnalysisStopWatch = StopWatch.createStarted();
IJ.showStatus("Analysing filters ...");
int setNumber = 0;
final DirectFilter currentOptimum = (optimum != null) ? optimum.result.filter : null;
for (final FilterSet filterSet : filterSets) {
setNumber++;
if (filterAnalysis(filterSet, setNumber, currentOptimum, rangeReduction) < 0) {
break;
}
}
filterAnalysisStopWatch.stop();
ImageJUtils.finished();
final String timeString = filterAnalysisStopWatch.toString();
IJ.log("Filter analysis time : " + timeString);
}
use of uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method scoreFilters.
@Nullable
private FilterScoreResult[] scoreFilters(FilterSet filterSet, boolean createTextResult) {
if (filterSet.size() == 0) {
return null;
}
initialiseScoring(filterSet);
FilterScoreResult[] scoreResults = new FilterScoreResult[filterSet.size()];
if (scoreResults.length == 1) {
// No need to multi-thread this
scoreResults[0] = scoreFilter((DirectFilter) filterSet.getFilters().get(0), defaultMinimalFilter, createTextResult, coordinateStore);
} else {
// Multi-thread score all the result
final int nThreads = getThreads(scoreResults.length);
final BlockingQueue<ScoreJob> jobs = new ArrayBlockingQueue<>(nThreads * 2);
final List<Thread> threads = new LinkedList<>();
final Ticker ticker = ImageJUtils.createTicker(scoreResults.length, nThreads, "Scoring Filters");
for (int i = 0; i < nThreads; i++) {
final ScoreWorker worker = new ScoreWorker(jobs, scoreResults, createTextResult, (coordinateStore == null) ? null : coordinateStore.newInstance(), ticker);
final Thread t = new Thread(worker);
threads.add(t);
t.start();
}
int index = 0;
for (final Filter filter : filterSet.getFilters()) {
if (IJ.escapePressed()) {
break;
}
put(jobs, new ScoreJob((DirectFilter) filter, index++));
}
// Finish all the worker threads by passing in a null job
for (int i = 0; i < threads.size(); i++) {
put(jobs, new ScoreJob(null, -1));
}
// Wait for all to finish
for (int i = 0; i < threads.size(); i++) {
try {
threads.get(i).join();
} catch (final InterruptedException ex) {
Logger.getLogger(BenchmarkFilterAnalysis.class.getName()).log(Level.WARNING, "Interrupted!", ex);
Thread.currentThread().interrupt();
throw new ConcurrentRuntimeException("Unexpected interruption", ex);
}
}
threads.clear();
ImageJUtils.finished();
// In case the threads were interrupted
if (ImageJUtils.isInterrupted()) {
scoreResults = null;
}
}
finishScoring();
return scoreResults;
}
use of uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method reportResults.
private ComplexFilterScore reportResults(boolean newResults, List<ComplexFilterScore> filters) {
if (filters.isEmpty()) {
IJ.log("Warning: No filters pass the criteria");
return null;
}
getCoordinateStore();
Collections.sort(filters);
FractionClassificationResult topFilterClassificationResult = null;
ArrayList<FractionalAssignment[]> topFilterResults = null;
String topFilterSummary = null;
if (settings.showSummaryTable || settings.saveTemplate) {
final Consumer<String> summaryWindow = createSummaryWindow();
int count = 0;
final double range = (settings.summaryDepth / simulationParameters.pixelPitch) * 0.5;
final int[] np = { 0 };
fitResultData.depthStats.forEach(depth -> {
if (Math.abs(depth) < range) {
np[0]++;
}
});
for (final ComplexFilterScore fs : filters) {
final ArrayList<FractionalAssignment[]> list = new ArrayList<>(fitResultData.resultsList.length);
final FractionClassificationResult r = scoreFilter(fs.getFilter(), defaultMinimalFilter, fitResultData.resultsList, list, coordinateStore);
final StringBuilder sb = createResult(fs.getFilter(), r);
if (topFilterResults == null) {
topFilterResults = list;
topFilterClassificationResult = r;
}
// Show the recall at the specified depth. Sum the distance and signal factor of all scored
// spots.
int scored = 0;
double tp = 0;
double distance = 0;
double sf = 0;
double rmsd = 0;
final SimpleRegression regression = new SimpleRegression(false);
for (final FractionalAssignment[] assignments : list) {
if (assignments == null) {
continue;
}
for (int i = 0; i < assignments.length; i++) {
final CustomFractionalAssignment c = (CustomFractionalAssignment) assignments[i];
if (Math.abs(c.peak.getZPosition()) <= range) {
tp += c.getScore();
}
distance += c.distToTarget;
sf += c.getSignalFactor();
rmsd += c.distToTarget * c.distToTarget;
regression.addData(c.peakResult.getSignal(), c.peak.getIntensity());
}
scored += assignments.length;
}
final double slope = regression.getSlope();
sb.append('\t');
sb.append(MathUtils.rounded(tp / np[0])).append('\t');
sb.append(MathUtils.rounded(distance / scored)).append('\t');
sb.append(MathUtils.rounded(sf / scored)).append('\t');
// RMSD to be the root mean square deviation in a single dimension so divide by 2.
// (This assumes 2D Euclidean distances.)
sb.append(MathUtils.rounded(Math.sqrt(MathUtils.div0(rmsd / 2, scored)))).append('\t');
sb.append(MathUtils.rounded(slope)).append('\t');
if (fs.atLimit() != null) {
sb.append(fs.atLimit());
}
String text = sb.toString();
if (topFilterSummary == null) {
topFilterSummary = text;
if (!settings.showSummaryTable) {
break;
}
}
if (fs.time != 0) {
sb.append('\t');
sb.append(fs.algorithm);
sb.append('\t');
sb.append(org.apache.commons.lang3.time.DurationFormatUtils.formatDurationHMS(fs.time));
} else {
sb.append("\t\t");
}
if (fs.paramTime != 0) {
sb.append('\t');
sb.append(fs.getParamAlgorithm());
sb.append('\t');
sb.append(org.apache.commons.lang3.time.DurationFormatUtils.formatDurationHMS(fs.paramTime));
} else {
sb.append("\t\t");
}
text = sb.toString();
summaryWindow.accept(text);
count++;
if (settings.summaryTopN > 0 && count >= settings.summaryTopN) {
break;
}
}
// Add a spacer to the summary table if we have multiple results
if (count > 1 && settings.showSummaryTable) {
summaryWindow.accept("");
}
}
final DirectFilter localBestFilter = filters.get(0).getFilter();
if (settings.saveBestFilter) {
saveFilter(localBestFilter);
}
if (topFilterClassificationResult == null) {
topFilterResults = new ArrayList<>(fitResultData.resultsList.length);
scoreFilter(localBestFilter, defaultMinimalFilter, fitResultData.resultsList, topFilterResults, coordinateStore);
}
if (newResults || filterAnalysisResult.scores.isEmpty()) {
filterAnalysisResult.scores.add(new FilterResult(settings.failCount, residualsThreshold, settings.duplicateDistance, settings.duplicateDistanceAbsolute, filters.get(0)));
}
if (settings.saveTemplate) {
saveTemplate(topFilterSummary);
}
showPlots();
calculateSensitivity();
topFilterResults = depthAnalysis(topFilterResults, localBestFilter);
topFilterResults = scoreAnalysis(topFilterResults, localBestFilter);
componentAnalysis(filters.get(0));
PreprocessedPeakResult[] filterResults = null;
if (isShowOverlay()) {
filterResults = showOverlay(topFilterResults, localBestFilter);
}
saveResults(filterResults, localBestFilter);
wo.tile();
return filters.get(0);
}
use of uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method shutdown.
@Override
public void shutdown() {
// Report the score for the best filter
final List<? extends Chromosome<FilterScore>> individuals = gaPopulation.getIndividuals();
FilterScore max = null;
for (final Chromosome<FilterScore> c : individuals) {
final FilterScore f = c.getFitness();
if (f != null && f.compareTo(max) < 0) {
max = f;
}
}
if (max == null) {
return;
}
final DirectFilter filter = (DirectFilter) ((SimpleFilterScore) max).filter;
// This filter may not have been part of the scored subset so use the entire results set for
// reporting
final FractionClassificationResult r = scoreFilter(filter, defaultMinimalFilter, gaResultsList, coordinateStore);
final StringBuilder text = createResult(filter, r);
add(text, gaIteration);
gaWindow.accept(text.toString());
}
Aggregations