use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class PulseActivationAnalysis method createActivations.
/**
* Creates the activations. This splits the input traces into continuous chains of localisations.
* Each chain is an activation. A new activation is created if there are more than the configured
* number of dark frames since the last localisation. The start frame for the activation defines
* the channel the activation is assigned to (this may be channel 0 if the start frame is not in a
* pulse start frame).
*/
@SuppressWarnings("null")
private void createActivations() {
final LocalList<Activation> activations = new LocalList<>(traces.length);
// Activations are only counted if there are at least
// n frames between localisations.
final int n = settings.darkFramesForNewActivation + 1;
for (final Trace trace : traces) {
// Time-order
trace.sort();
final PeakResultStoreList points = trace.getPoints();
// Define the frame for a new activation
int nextActivationStartFrame = Integer.MIN_VALUE;
Trace current = null;
int channel = 0;
for (int j = 0; j < points.size(); j++) {
final PeakResult p = points.get(j);
// Check if this is an activation
if (p.getFrame() >= nextActivationStartFrame) {
if (current != null) {
// Store the last
activations.add(new Activation(current, channel));
}
// Create a new activation
current = new Trace(p);
channel = getChannel(p);
} else {
// This is the same chain of localisations
current.add(p);
}
nextActivationStartFrame = p.getEndFrame() + n;
}
if (current != null) {
activations.add(new Activation(current, channel));
}
}
save(activations);
}
use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class SpotFinderPreview method run.
private void run(ImageProcessor ip, MaximaSpotFilter filter) {
if (refreshing) {
return;
}
currentSlice = imp.getCurrentSlice();
final Rectangle bounds = ip.getRoi();
// Crop to the ROI
FloatProcessor fp = ip.crop().toFloat(0, null);
float[] data = (float[]) fp.getPixels();
final int width = fp.getWidth();
final int height = fp.getHeight();
// Store the mean bias and gain of the region data.
// This is used to correctly overlay the filtered data on the original image.
double bias = 0;
double gain = 1;
boolean adjust = false;
// Set weights
final CameraModel cameraModel = fitConfig.getCameraModel();
if (!(cameraModel instanceof FakePerPixelCameraModel)) {
// This should be done on the normalised data
final float[] w = cameraModel.getNormalisedWeights(bounds);
filter.setWeights(w, width, height);
data = data.clone();
if (data.length < ip.getPixelCount()) {
adjust = true;
bias = MathUtils.sum(cameraModel.getBias(bounds)) / data.length;
gain = MathUtils.sum(cameraModel.getGain(bounds)) / data.length;
}
cameraModel.removeBiasAndGain(bounds, data);
}
final Spot[] spots = filter.rank(data, width, height);
data = filter.getPreprocessedData();
final int size = spots.length;
if (topNScrollBar != null) {
topNScrollBar.setMaximum(size);
selectScrollBar.setMaximum(size);
}
fp = new FloatProcessor(width, height, data);
final FloatProcessor out = new FloatProcessor(ip.getWidth(), ip.getHeight());
out.copyBits(ip, 0, 0, Blitter.COPY);
if (adjust) {
fp.multiply(gain);
fp.add(bias);
}
out.insert(fp, bounds.x, bounds.y);
final double min = fp.getMin();
final double max = fp.getMax();
out.setMinAndMax(min, max);
final Overlay o = new Overlay();
o.add(new ImageRoi(0, 0, out));
if (label != null) {
// Get results for frame
final Coordinate[] actual = ResultsMatchCalculator.getCoordinates(actualCoordinates, imp.getCurrentSlice());
final Coordinate[] predicted = new Coordinate[size];
for (int i = 0; i < size; i++) {
predicted[i] = new BasePoint(spots[i].x + bounds.x, spots[i].y + bounds.y);
}
// Compute assignments
final LocalList<FractionalAssignment> fractionalAssignments = new LocalList<>(3 * predicted.length);
final double matchDistance = settings.distance * fitConfig.getInitialPeakStdDev();
final RampedScore score = RampedScore.of(matchDistance, matchDistance * settings.lowerDistance / 100, false);
final double dmin = matchDistance * matchDistance;
final int nActual = actual.length;
final int nPredicted = predicted.length;
for (int j = 0; j < nPredicted; j++) {
// Centre in the middle of the pixel
final float x = predicted[j].getX() + 0.5f;
final float y = predicted[j].getY() + 0.5f;
// Any spots that match
for (int i = 0; i < nActual; i++) {
final double dx = (x - actual[i].getX());
final double dy = (y - actual[i].getY());
final double d2 = dx * dx + dy * dy;
if (d2 <= dmin) {
final double d = Math.sqrt(d2);
final double s = score.score(d);
if (s == 0) {
continue;
}
double distance = 1 - s;
if (distance == 0) {
// In the case of a match below the distance thresholds
// the distance will be 0. To distinguish between candidates all below
// the thresholds just take the closest.
// We know d2 is below dmin so we subtract the delta.
distance -= (dmin - d2);
}
// Store the match
fractionalAssignments.add(new ImmutableFractionalAssignment(i, j, distance, s));
}
}
}
final FractionalAssignment[] assignments = fractionalAssignments.toArray(new FractionalAssignment[0]);
// Compute matches
final RankedScoreCalculator calc = RankedScoreCalculator.create(assignments, nActual - 1, nPredicted - 1);
final boolean save = settings.showTP || settings.showFP;
final double[] calcScore = calc.score(nPredicted, settings.multipleMatches, save);
final ClassificationResult result = RankedScoreCalculator.toClassificationResult(calcScore, nActual);
// Compute AUC and max jaccard (and plot)
final double[][] curve = RankedScoreCalculator.getPrecisionRecallCurve(assignments, nActual, nPredicted);
final double[] precision = curve[0];
final double[] recall = curve[1];
final double[] jaccard = curve[2];
final double auc = AucCalculator.auc(precision, recall);
// Show scores
final String scoreLabel = String.format("Slice=%d, AUC=%s, R=%s, Max J=%s", imp.getCurrentSlice(), MathUtils.rounded(auc), MathUtils.rounded(result.getRecall()), MathUtils.rounded(MathUtils.maxDefault(0, jaccard)));
setLabel(scoreLabel);
// Plot
String title = TITLE + " Performance";
Plot plot = new Plot(title, "Spot Rank", "");
final double[] rank = SimpleArrayUtils.newArray(precision.length, 0, 1.0);
plot.setLimits(0, nPredicted, 0, 1.05);
plot.setColor(Color.blue);
plot.addPoints(rank, precision, Plot.LINE);
plot.setColor(Color.red);
plot.addPoints(rank, recall, Plot.LINE);
plot.setColor(Color.black);
plot.addPoints(rank, jaccard, Plot.LINE);
plot.setColor(Color.black);
plot.addLabel(0, 0, scoreLabel);
final WindowOrganiser windowOrganiser = new WindowOrganiser();
ImageJUtils.display(title, plot, 0, windowOrganiser);
title = TITLE + " Precision-Recall";
plot = new Plot(title, "Recall", "Precision");
plot.setLimits(0, 1, 0, 1.05);
plot.setColor(Color.red);
plot.addPoints(recall, precision, Plot.LINE);
plot.drawLine(recall[recall.length - 1], precision[recall.length - 1], recall[recall.length - 1], 0);
plot.setColor(Color.black);
plot.addLabel(0, 0, scoreLabel);
ImageJUtils.display(title, plot, 0, windowOrganiser);
windowOrganiser.tile();
// Create Rois for TP and FP
if (save) {
final double[] matchScore = RankedScoreCalculator.getMatchScore(calc.getScoredAssignments(), nPredicted);
int matches = 0;
for (int i = 0; i < matchScore.length; i++) {
if (matchScore[i] != 0) {
matches++;
}
}
if (settings.showTP) {
final float[] x = new float[matches];
final float[] y = new float[x.length];
int count = 0;
for (int i = 0; i < matchScore.length; i++) {
if (matchScore[i] != 0) {
final BasePoint p = (BasePoint) predicted[i];
x[count] = p.getX() + 0.5f;
y[count] = p.getY() + 0.5f;
count++;
}
}
addRoi(0, o, x, y, count, Color.green);
}
if (settings.showFP) {
final float[] x = new float[nPredicted - matches];
final float[] y = new float[x.length];
int count = 0;
for (int i = 0; i < matchScore.length; i++) {
if (matchScore[i] == 0) {
final BasePoint p = (BasePoint) predicted[i];
x[count] = p.getX() + 0.5f;
y[count] = p.getY() + 0.5f;
count++;
}
}
addRoi(0, o, x, y, count, Color.red);
}
}
} else {
final WindowOrganiser wo = new WindowOrganiser();
// Option to show the number of neighbours within a set pixel box radius
final int[] count = spotFilterHelper.countNeighbours(spots, width, height, settings.neighbourRadius);
// Show as histogram the totals...
new HistogramPlotBuilder(TITLE, StoredData.create(count), "Neighbours").setIntegerBins(true).setPlotLabel("Radius = " + settings.neighbourRadius).show(wo);
// TODO - Draw n=0, n=1 on the image overlay
final LUT lut = LutHelper.createLut(LutColour.FIRE_LIGHT);
// These are copied by the ROI
final float[] x = new float[1];
final float[] y = new float[1];
// Plot the intensity
final double[] intensity = new double[size];
final double[] rank = SimpleArrayUtils.newArray(size, 1, 1.0);
final int top = (settings.topN > 0) ? settings.topN : size;
final int size_1 = size - 1;
for (int i = 0; i < size; i++) {
intensity[i] = spots[i].intensity;
if (i < top) {
x[0] = spots[i].x + bounds.x + 0.5f;
y[0] = spots[i].y + bounds.y + 0.5f;
final Color c = LutHelper.getColour(lut, size_1 - i, size);
addRoi(0, o, x, y, 1, c, 2, 1);
}
}
final String title = TITLE + " Intensity";
final Plot plot = new Plot(title, "Rank", "Intensity");
plot.setColor(Color.blue);
plot.addPoints(rank, intensity, Plot.LINE);
if (settings.topN > 0 && settings.topN < size) {
plot.setColor(Color.magenta);
plot.drawLine(settings.topN, 0, settings.topN, intensity[settings.topN - 1]);
}
if (settings.select > 0 && settings.select < size) {
plot.setColor(Color.yellow);
final int index = settings.select - 1;
final double in = intensity[index];
plot.drawLine(settings.select, 0, settings.select, in);
x[0] = spots[index].x + bounds.x + 0.5f;
y[0] = spots[index].y + bounds.y + 0.5f;
final Color c = LutHelper.getColour(lut, size_1 - settings.select, size);
addRoi(0, o, x, y, 1, c, 3, 3);
plot.setColor(Color.black);
plot.addLabel(0, 0, "Selected spot intensity = " + MathUtils.rounded(in));
}
ImageJUtils.display(title, plot, 0, wo);
wo.tile();
}
imp.setOverlay(o);
}
use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method getPoints.
/**
* Gets the points.
*
* @param results the results
* @param settings the settings
* @return the points
*/
static LocalList<Point3f> getPoints(MemoryPeakResults results, ImageJ3DResultsViewerSettingsOrBuilder settings) {
final LocalList<Point3f> points = new LocalList<>(results.size());
if (results.is3D()) {
results.forEach(DistanceUnit.NM, (XyzResultProcedure) (x, y, z) -> {
points.push(new Point3f(x, y, z));
});
} else {
results.forEach(DistanceUnit.NM, (XyResultProcedure) (x, y) -> {
points.push(new Point3f(x, y, 0));
});
final double range = settings.getDepthRange();
if (range > 0 && results.size() > 1) {
final DepthMode mode = DepthMode.forNumber(settings.getDepthMode());
final double min = -settings.getDepthRange() / 2;
switch(mode) {
case DITHER:
final SplitMix r = SplitMix.new64(settings.getDitherSeed());
for (int i = points.size(); i-- > 0; ) {
points.unsafeGet(i).z += (min + r.nextDouble() * range);
}
break;
case INTENSITY:
// Rank by intensity, highest first
final StandardResultProcedure p = new StandardResultProcedure(results);
p.getI();
final int[] indices = SimpleArrayUtils.natural(results.size());
SortUtils.sortIndices(indices, p.intensity, true);
final double inc = range / indices.length;
for (int i = 0; i < indices.length; i++) {
// The standard rendering has +z going away so put the highest rank at min
points.unsafeGet(indices[i]).z += (min + i * inc);
}
break;
case NONE:
break;
default:
throw new IllegalStateException("Unknown depth mode: " + mode);
}
}
}
return points;
}
use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class FailCountManager method createData.
/**
* Creates the fail count data by running fitting on the current image.
*/
private void createData() {
final ImagePlus imp = WindowManager.getCurrentImage();
if (imp == null) {
IJ.error(TITLE, "No image for fitting");
return;
}
if (!showCreateDataDialog(imp)) {
return;
}
// Get the current fit configuration
final Configuration c = new Configuration();
if (!c.showDialog(false)) {
return;
}
final FitEngineConfiguration fitConfig = c.getFitEngineConfiguration();
// Update stopping criteria.
fitConfig.resetFailCounter();
fitConfig.setFailuresLimit(settings.getFailCountLimit());
final ImageSource source = new IJImageSource(imp);
final PeakFit peakFit = new PeakFit(fitConfig, ResultsSettings.getDefaultInstance());
peakFit.setResultsSuffix("(FailCountAnalysis)");
if (!peakFit.initialise(source, null, false)) {
IJ.error(TITLE, "Failed to initialise the fit engine");
return;
}
final FitEngine engine = peakFit.createFitEngine();
final Rectangle bounds = new Rectangle(source.getWidth(), source.getHeight());
// Run
final int totalFrames = Math.min(source.getFrames(), settings.getMaxFrames());
final int step = ImageJUtils.getProgressInterval(totalFrames);
IJ.showProgress(0);
boolean shutdown = false;
int slice = 0;
final LocalList<ParameterisedFitJob> jobs = new LocalList<>(totalFrames);
while (!shutdown && slice < totalFrames) {
final float[] data = source.next();
if (data == null) {
break;
}
if (slice++ % step == 0) {
final int frames = slice;
if (ImageJUtils.showStatus(() -> "Fitting slice: " + frames + " / " + totalFrames)) {
IJ.showProgress(slice, totalFrames);
}
}
final ParameterisedFitJob job = createJob(source.getStartFrameNumber(), data, bounds);
jobs.push(job);
engine.run(job);
shutdown = escapePressed();
}
ImageJUtils.showStatus("Extracting fail count data");
engine.end(shutdown);
IJ.showProgress(1);
source.close();
// Extract the fail count data
final LocalList<FailCountData> failCountData = new LocalList<>(jobs.size());
for (int i = 0; i < jobs.size(); i++) {
final ParameterisedFitJob job = jobs.unsafeGet(i);
if (job.getStatus() == Status.FINISHED) {
final FitParameters fitParams = job.getFitParameters();
// Find the last success
boolean[] results = fitParams.pass;
int end = results.length - 1;
while (end > 0 && !results[end]) {
end--;
}
// Add on the configured fail count limit
end = Math.min(end + 1 + settings.getFailCountLimit(), results.length);
results = Arrays.copyOf(results, end);
failCountData.add(new FailCountData(job.getSlice(), results));
}
}
failCountDataRef.set(failCountData);
ImageJUtils.showStatus("");
// Save for the future
if (settings.getSaveAfterFitting()) {
saveData();
}
}
use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.
the class BinaryFilePeakResults method sort.
@Override
protected void sort() throws IOException {
final LocalList<Result> results = new LocalList<>(size);
String header;
try (DataInputStream input = new DataInputStream(new FileInputStream(filename))) {
header = readHeader(input);
int flags = 0;
if (isShowEndFrame()) {
flags += FLAG_END_FRAME;
}
if (isShowId()) {
flags += FLAG_ID;
}
if (isShowCategory()) {
flags += FLAG_CATEGORY;
}
if (isShowPrecision()) {
flags += FLAG_PRECISION;
}
final byte[] line = new byte[getDataSize(isShowDeviations(), flags, fieldCount)];
final int offset = (isShowId() ? 4 : 0) + (isShowCategory() ? 4 : 0);
while (input.read(line) == line.length) {
results.add(new Result(line, offset));
}
}
// Sort by slice number
Collections.sort(results, (r1, r2) -> Integer.compare(r1.slice, r2.slice));
// Must write using the same method as the main code so use a FileOutputStream again
try (FileOutputStream fos = new FileOutputStream(filename);
BufferedOutputStream output = new BufferedOutputStream(fos)) {
output.write(header.getBytes(StandardCharsets.UTF_8));
for (final Result result : results) {
output.write(result.line);
}
}
}
Aggregations