use of uk.ac.sussex.gdsc.core.annotation.Nullable in project gdsc-smlm by aherbert.
the class DriftCalculator method calculateUsingFrames.
/**
* Calculates drift using images from N consecutive frames aligned to the overall image.
*
* @param results the results
* @param limits the limits
* @param reconstructionSize the reconstruction size
* @return the drift { dx[], dy[] }
*/
@Nullable
private double[][] calculateUsingFrames(MemoryPeakResults results, int[] limits, int reconstructionSize) {
// Extract the localisations into blocks of N consecutive frames
final BlockPeakResultProcedure p = new BlockPeakResultProcedure(settings);
results.sort();
results.forEach(p);
final List<List<Localisation>> blocks = p.blocks;
if (blocks.size() <= 1) {
tracker.log("ERROR : Require at least 2 images for drift calculation");
return null;
}
// Check the final block has enough localisations
final List<Localisation> nextBlock = p.nextBlock;
if (nextBlock.size() < settings.minimimLocalisations) {
blocks.remove(blocks.size() - 1);
if (blocks.size() <= 1) {
tracker.log("ERROR : Require at least 2 images for drift calculation");
return null;
}
final List<Localisation> combinedBlock = blocks.get(blocks.size() - 1);
combinedBlock.addAll(nextBlock);
}
// Find the average time point for each block
final int[] blockT = new int[blocks.size()];
int time = 0;
for (final List<Localisation> block : blocks) {
long sum = 0;
for (final Localisation r : block) {
sum += r.time;
}
blockT[time++] = (int) (sum / block.size());
}
// Calculate a scale to use when constructing the images for alignment
final Rectangle bounds = results.getBounds(true);
final ResultsImageSettings.Builder builder = ResultsImageSettings.newBuilder().setImageSizeMode(ResultsImageSizeMode.IMAGE_SIZE).setImageSize(reconstructionSize);
final float scale = ImagePeakResultsFactory.getScale(builder, bounds, 1);
executor = Executors.newFixedThreadPool(Prefs.getThreads());
final double[] dx = new double[limits[1] + 1];
final double[] dy = new double[dx.length];
final double[] originalDriftTimePoints = getOriginalDriftTimePoints(dx, blockT);
lastdx = null;
final double smoothing = updateSmoothingParameter(originalDriftTimePoints);
double change = calculateDriftUsingFrames(blocks, blockT, bounds, scale, 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 = calculateDriftUsingFrames(blocks, blockT, bounds, scale, 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 };
}
use of uk.ac.sussex.gdsc.core.annotation.Nullable in project gdsc-smlm by aherbert.
the class DriftCalculator method calculateUsingMarkers.
/**
* Calculates drift using the feducial markers within ROI.
*
* <p>Adapted from the drift calculation method in QuickPALM.
*
* @param results the results
* @param limits the limits
* @param rois the rois
* @return the drift { dx[], dy[] }
*/
@Nullable
private double[][] calculateUsingMarkers(MemoryPeakResults results, int[] limits, Roi[] rois) {
final Spot[][] roiSpots = findSpots(results, rois, limits);
// Check we have enough data
if (roiSpots.length == 0) {
IJ.error("No peak fit results in the selected ROIs");
return null;
}
final double[] dx = new double[limits[1] + 1];
final double[] dy = new double[dx.length];
final double[] sum = new double[roiSpots.length];
final double[] weights = calculateWeights(roiSpots, dx.length, sum);
final double smoothing = updateSmoothingParameter(weights);
lastdx = null;
double change = calculateDriftUsingMarkers(roiSpots, weights, sum, dx, dy, smoothing, settings.iterations);
if (Double.isNaN(change) || tracker.isEnded()) {
return null;
}
ImageJUtils.log("Drift Calculator : Initial drift " + MathUtils.rounded(change));
for (int i = 1; i <= settings.maxIterations; i++) {
change = calculateDriftUsingMarkers(roiSpots, weights, sum, dx, dy, smoothing, settings.iterations);
if (Double.isNaN(change)) {
return null;
}
if (converged(i, change, getTotalDrift(dx, dy, weights))) {
break;
}
}
if (tracker.isEnded()) {
return null;
}
interpolate(dx, dy, weights);
plotDrift(limits, dx, dy);
saveDrift(weights, dx, dy);
return new double[][] { dx, dy };
}
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 };
}
use of uk.ac.sussex.gdsc.core.annotation.Nullable in project gdsc-smlm by aherbert.
the class MultiPathFilter method acceptAnyDoublet.
/**
* Check any new and all existing results within the multi-doublet fit results are valid. Returns
* the new results. Coordinate shift filter is disabled for the doublet results.
*
* <p>New results and validated candidates that fail the primary filter can be filtered using the
* minimal filter and sent to the store. The store can be used to determine if a fit for a
* different candidate has been performed already.
*
* @param multiPathResult the multi path result
* @param validateCandidates Set to true to validate the candidates
* @param store the store
* @param candidateId the candidate id
* @return The new results that pass the filter
*/
@Nullable
private PreprocessedPeakResult[] acceptAnyDoublet(final MultiPathFitResult multiPathResult, boolean validateCandidates, SelectedResultStore store, final int candidateId) {
final FitResult multiDoubletFitResult = multiPathResult.getMultiDoubletFitResult();
if (multiDoubletFitResult == null || multiDoubletFitResult.getResults() == null) {
return null;
}
// Doublets may drift further than single spot candidates.
// We must validate the doublet spot without shift filtering.
// Note: Only disable shift for the doublet results.
// doublets = len(multi-doublet) - len(multi) + 1
final PreprocessedPeakResult[] results = multiDoubletFitResult.getResults();
final int nDoublets = results.length - multiPathResult.getMultiFitResult().getResults().length + 1;
setupFilter(FilterValidationOption.NO_SHIFT);
validationResults = new int[results.length];
for (int i = 0; i < nDoublets; i++) {
validationResults[i] = filter.validate(results[i]);
}
restoreFilterState();
for (int i = nDoublets; i < results.length; i++) {
validationResults[i] = filter.validate(results[i]);
}
return acceptAnyInternal(candidateId, multiDoubletFitResult, validateCandidates, store);
}
use of uk.ac.sussex.gdsc.core.annotation.Nullable in project gdsc-smlm by aherbert.
the class TraceMatchCalculator method extractPulses.
@Nullable
private static Pulse[] extractPulses(MemoryPeakResults results) {
if (results == null) {
return null;
}
final Pulse[] pulses = new Pulse[results.size()];
final Counter i = new Counter();
results.forEach(DistanceUnit.PIXEL, (XyrResultProcedure) (x, y, result) -> pulses[i.getAndIncrement()] = new Pulse(x, y, result.getFrame(), result.getEndFrame()));
return pulses;
}
Aggregations