use of uk.ac.sussex.gdsc.core.annotation.Nullable in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method score.
@Nullable
@Override
public SearchResult<FilterScore>[] score(double[][] points) {
gaIteration++;
SimpleFilterScore max = filterScoreOptimum;
final FilterScoreResult[] scoreResults = scoreFilters(setStrength(new FilterSet(searchSpaceToFilters(points))), false);
if (scoreResults == null) {
return null;
}
@SuppressWarnings("unchecked") final SearchResult<FilterScore>[] scores = new SearchResult[scoreResults.length];
for (int index = 0; index < scoreResults.length; index++) {
final FilterScoreResult scoreResult = scoreResults[index];
final SimpleFilterScore result = new SimpleFilterScore(scoreResult, true, scoreResult.criteria >= minCriteria);
if (result.compareTo(max) < 0) {
max = result;
}
scores[index] = new SearchResult<>(result.result.filter.getParameters(), result);
}
filterScoreOptimum = max;
// Add the best filter to the table
// This filter may not have been part of the scored subset so use the entire results set for
// reporting
final DirectFilter filter = max.result.filter;
final FractionClassificationResult r = scoreFilter(filter, defaultMinimalFilter, gaResultsList, coordinateStore);
final StringBuilder text = createResult(filter, r);
add(text, gaIteration);
gaWindow.accept(text.toString());
return scores;
}
use of uk.ac.sussex.gdsc.core.annotation.Nullable in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method readFilterSets.
@Nullable
@SuppressWarnings("unchecked")
private List<FilterSet> readFilterSets() {
if (extraOptions) {
final MultiPathFilter multiFilter = BenchmarkSpotFit.getMultiFilter();
if (multiFilter != null) {
final IDirectFilter f = multiFilter.getFilter();
if (f instanceof DirectFilter) {
final GenericDialog gd = new GenericDialog(TITLE);
gd.addMessage("Use an identical filter to " + BenchmarkSpotFit.TITLE);
gd.enableYesNoCancel();
gd.hideCancelButton();
gd.showDialog();
if (gd.wasOKed()) {
final List<FilterSet> filterSets = new ArrayList<>(1);
final List<Filter> filters = new ArrayList<>(1);
filters.add((DirectFilter) f);
final FilterSet filterSet = new FilterSet(filters);
filterSets.add(filterSet);
resetParametersFromFitting();
createResultsPrefix2();
return filterSets;
}
}
}
}
GUIFilterSettings filterSettings = SettingsManager.readGuiFilterSettings(0);
final String filename = ImageJUtils.getFilename("Filter_File", filterSettings.getFilterSetFilename());
if (filename != null) {
IJ.showStatus("Reading filters ...");
filterSettings = filterSettings.toBuilder().setFilterSetFilename(filename).build();
// Allow the filters to be cached
final Triple<String, Long, List<FilterSet>> filterCache = lastFilterList.get();
if (isSameFile(filename, filterCache)) {
final GenericDialog gd = new GenericDialog(TITLE);
gd.hideCancelButton();
gd.addMessage("The same filter file was selected.");
gd.addCheckbox("Re-use_filters", settings.reUseFilters);
gd.showDialog();
if (!gd.wasCanceled()) {
settings.reUseFilters = gd.getNextBoolean();
if (settings.reUseFilters) {
SettingsManager.writeSettings(filterSettings);
return filterCache.getRight();
}
}
}
final File file = new File(filename);
try (BufferedReader input = new BufferedReader(new UnicodeReader(new FileInputStream(file), null))) {
// Use the instance so we can catch the exception
final Object o = FilterXStreamUtils.getXStreamInstance().fromXML(input);
if (!(o instanceof List<?>)) {
IJ.log("No filter sets defined in the specified file: " + filename);
return null;
}
SettingsManager.writeSettings(filterSettings);
List<FilterSet> filterSets = (List<FilterSet>) o;
if (containsStandardFilters(filterSets)) {
IJ.log("Filter sets must contain 'Direct' filters");
return null;
}
// Check they are not empty lists
final List<FilterSet> filterSets2 = new LinkedList<>();
for (final FilterSet filterSet : filterSets) {
if (filterSet.size() != 0) {
filterSets2.add(filterSet);
} else {
IJ.log("Filter set empty: " + filterSet.getName());
}
}
if (filterSets2.isEmpty()) {
IJ.log("All Filter sets are empty");
return null;
}
// Maintain the same list type
filterSets.clear();
filterSets.addAll(filterSets2);
// Option to enumerate filters
filterSets = expandFilters(filterSets);
// Save for re-use
lastFilterList.set(Triple.of(filename, getLastModified(file), filterSets));
return filterSets;
} catch (final Exception ex) {
IJ.log("Unable to load the filter sets from file: " + ex.getMessage());
} finally {
IJ.showStatus("");
}
}
return null;
}
use of uk.ac.sussex.gdsc.core.annotation.Nullable in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method scoreFilters.
/**
* Score filters.
*
* @param points the points (must be sorted by duplicate distance)
* @param createTextResult set to true to create the text result
* @return the score results
*/
@Nullable
private ParameterScoreResult[] scoreFilters(double[][] points, boolean createTextResult) {
if (points == null || points.length == 0) {
return null;
}
gaResultsListToScore = gaResultsList;
gaSubset = false;
ParameterScoreResult[] scoreResults = new ParameterScoreResult[points.length];
if (scoreResults.length == 1) {
// No need to multi-thread this
final int failCount = (int) Math.round(points[0][0]);
final double residualsThreshold = points[0][1];
final double duplicateDistance = points[0][2];
scoreResults[0] = scoreFilter(searchScoreFilter, defaultMinimalFilter, failCount, residualsThreshold, duplicateDistance, createCoordinateStore(duplicateDistance), createTextResult);
} else {
// Multi-thread score all the result
final int nThreads = getThreads(scoreResults.length);
final BlockingQueue<ParameterScoreJob> 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 ParameterScoreWorker worker = new ParameterScoreWorker(jobs, scoreResults, createTextResult, ticker);
final Thread t = new Thread(worker);
threads.add(t);
t.start();
}
ticker.start();
for (int i = 0; i < points.length; i++) {
if (IJ.escapePressed()) {
break;
}
put(jobs, new ParameterScoreJob(points[i], i));
}
// Finish all the worker threads by passing in a null job
for (int i = 0; i < threads.size(); i++) {
put(jobs, new ParameterScoreJob(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.core.annotation.Nullable in project GDSC-SMLM by aherbert.
the class BenchmarkFilterAnalysis method showOverlay.
/**
* Show overlay.
*
* <ul>
*
* <li>Green = TP
*
* <li>Red = FP
*
* <li>Magenta = FP (Ignored from analysis)
*
* <li>Yellow = FN
*
* <li>Orange = FN (Outside border)
*
* </ul>
*
* @param allAssignments The assignments generated from running the filter (or null)
* @param filter the filter
* @return The results from running the filter (or null)
*/
@Nullable
@SuppressWarnings("null")
private PreprocessedPeakResult[] showOverlay(ArrayList<FractionalAssignment[]> allAssignments, DirectFilter filter) {
final ImagePlus imp = CreateData.getImage();
if (imp == null) {
return null;
}
// Run the filter manually to get the results that pass.
if (allAssignments == null) {
allAssignments = getAssignments(filter);
}
final Overlay o = new Overlay();
// Do TP
final TIntHashSet actual = new TIntHashSet();
final TIntHashSet predicted = new TIntHashSet();
for (final FractionalAssignment[] assignments : allAssignments) {
if (assignments == null || assignments.length == 0) {
continue;
}
float[] tx = null;
float[] ty = null;
int count = 0;
if (settings.showTP) {
tx = new float[assignments.length];
ty = new float[assignments.length];
}
int frame = 0;
for (int i = 0; i < assignments.length; i++) {
final CustomFractionalAssignment c = (CustomFractionalAssignment) assignments[i];
final UniqueIdPeakResult peak = (UniqueIdPeakResult) c.peak;
final BasePreprocessedPeakResult spot = (BasePreprocessedPeakResult) c.peakResult;
actual.add(peak.uniqueId);
predicted.add(spot.getUniqueId());
frame = spot.getFrame();
if (settings.showTP) {
tx[count] = spot.getX();
ty[count++] = spot.getY();
}
}
if (settings.showTP) {
SpotFinderPreview.addRoi(frame, o, tx, ty, count, Color.green);
}
}
float[] x = new float[10];
float[] y = new float[x.length];
float[] x2 = new float[10];
float[] y2 = new float[x2.length];
// Do FP (all remaining results that are not a TP)
PreprocessedPeakResult[] filterResults = null;
if (settings.showFP) {
final MultiPathFilter multiPathFilter = createMpf(filter, defaultMinimalFilter);
filterResults = filterResults(multiPathFilter);
int frame = 0;
int c1 = 0;
int c2 = 0;
for (int i = 0; i < filterResults.length; i++) {
if (frame != filterResults[i].getFrame()) {
if (c1 != 0) {
SpotFinderPreview.addRoi(frame, o, x, y, c1, Color.red);
}
if (c2 != 0) {
SpotFinderPreview.addRoi(frame, o, x2, y2, c2, Color.magenta);
}
c1 = c2 = 0;
}
frame = filterResults[i].getFrame();
if (predicted.contains(filterResults[i].getUniqueId())) {
continue;
}
if (filterResults[i].ignore()) {
if (x2.length == c2) {
x2 = Arrays.copyOf(x2, c2 * 2);
y2 = Arrays.copyOf(y2, c2 * 2);
}
x2[c2] = filterResults[i].getX();
y2[c2++] = filterResults[i].getY();
} else {
if (x.length == c1) {
x = Arrays.copyOf(x, c1 * 2);
y = Arrays.copyOf(y, c1 * 2);
}
x[c1] = filterResults[i].getX();
y[c1++] = filterResults[i].getY();
}
}
if (c1 != 0) {
SpotFinderPreview.addRoi(frame, o, x, y, c1, Color.red);
}
if (c2 != 0) {
SpotFinderPreview.addRoi(frame, o, x2, y2, c2, Color.magenta);
}
}
// Do FN (all remaining peaks that have not been matched)
if (settings.showFN) {
final boolean checkBorder = (filterResult.analysisBorder != null && filterResult.analysisBorder.x != 0);
final float border;
final float xlimit;
final float ylimit;
if (checkBorder) {
final Rectangle lastAnalysisBorder = filterResult.analysisBorder;
border = lastAnalysisBorder.x;
xlimit = lastAnalysisBorder.x + lastAnalysisBorder.width;
ylimit = lastAnalysisBorder.y + lastAnalysisBorder.height;
} else {
border = xlimit = ylimit = 0;
}
// Add the results to the lists
actualCoordinates.forEachEntry(new CustomTIntObjectProcedure(x, y, x2, y2) {
@Override
public boolean execute(int frame, UniqueIdPeakResult[] results) {
int c1 = 0;
int c2 = 0;
if (x.length <= results.length) {
x = new float[results.length];
y = new float[results.length];
}
if (x2.length <= results.length) {
x2 = new float[results.length];
y2 = new float[results.length];
}
for (int i = 0; i < results.length; i++) {
// Ignore those that were matched by TP
if (actual.contains(results[i].uniqueId)) {
continue;
}
if (checkBorder && outsideBorder(results[i], border, xlimit, ylimit)) {
x2[c2] = results[i].getXPosition();
y2[c2++] = results[i].getYPosition();
} else {
x[c1] = results[i].getXPosition();
y[c1++] = results[i].getYPosition();
}
}
if (c1 != 0) {
SpotFinderPreview.addRoi(frame, o, x, y, c1, Color.yellow);
}
if (c2 != 0) {
SpotFinderPreview.addRoi(frame, o, x2, y2, c2, Color.orange);
}
return true;
}
});
}
imp.setOverlay(o);
return filterResults;
}
use of uk.ac.sussex.gdsc.core.annotation.Nullable in project GDSC-SMLM by aherbert.
the class DriftCalculator method calculateUsingImageStack.
/**
* Calculates drift using images from a reference stack aligned to the overall z-projection.
*
* @param stack the stack
* @param limits the limits
* @return the drift { dx[], dy[] }
*/
@Nullable
private double[][] calculateUsingImageStack(ImageStack stack, int[] limits) {
// Update the limits using the stack size
final int upperT = settings.startFrame + settings.frameSpacing * (stack.getSize() - 1);
limits[1] = Math.max(limits[1], upperT);
// TODO - Truncate the stack if there are far too many frames for the localisation limits
tracker.status("Constructing images");
executor = Executors.newFixedThreadPool(Prefs.getThreads());
// Built an image and FHT image for each slice
final ImageProcessor[] images = new ImageProcessor[stack.getSize()];
final Fht[] fhtImages = new Fht[stack.getSize()];
final List<Future<?>> futures = new LinkedList<>();
final Ticker ticker = Ticker.createStarted(tracker, images.length, true);
final int imagesPerThread = getImagesPerThread(images);
final AlignImagesFft aligner = new AlignImagesFft();
final FloatProcessor referenceIp = stack.getProcessor(1).toFloat(0, null);
// We do not care about the window method because this processor will not
// actually be used for alignment, it is a reference for the FHT size
aligner.initialiseReference(referenceIp, WindowMethod.NONE, false);
for (int i = 0; i < images.length; i += imagesPerThread) {
futures.add(executor.submit(new ImageFhtInitialiser(stack, images, aligner, fhtImages, i, i + imagesPerThread, ticker)));
}
ConcurrencyUtils.waitForCompletionUnchecked(futures);
tracker.progress(1);
if (tracker.isEnded()) {
return null;
}
final double[] dx = new double[limits[1] + 1];
final double[] dy = new double[dx.length];
final double[] originalDriftTimePoints = new double[dx.length];
final int[] blockT = new int[stack.getSize()];
for (int i = 0, t = settings.startFrame; i < stack.getSize(); i++, t += settings.frameSpacing) {
originalDriftTimePoints[t] = 1;
blockT[i] = t;
}
final double smoothing = updateSmoothingParameter(originalDriftTimePoints);
lastdx = null;
// For the first iteration calculate drift to the first image in the stack
// (since the average projection may have a large drift blurring the image)
double change = calculateDriftUsingImageStack(referenceIp, images, fhtImages, blockT, dx, dy, originalDriftTimePoints, smoothing, settings.iterations);
if (Double.isNaN(change) || tracker.isEnded()) {
return null;
}
plotDrift(limits, dx, dy);
ImageJUtils.log("Drift Calculator : Initial drift " + MathUtils.rounded(change));
for (int i = 1; i <= settings.maxIterations; i++) {
change = calculateDriftUsingImageStack(null, images, fhtImages, blockT, dx, dy, originalDriftTimePoints, smoothing, settings.iterations);
if (Double.isNaN(change)) {
return null;
}
plotDrift(limits, dx, dy);
if (converged(i, change, getTotalDrift(dx, dy, originalDriftTimePoints))) {
break;
}
}
if (tracker.isEnded()) {
return null;
}
plotDrift(limits, dx, dy);
return new double[][] { dx, dy };
}
Aggregations