use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.
the class TcPalmAnalysis method runPlot.
/**
* Create the activations and total activations plots.
*
* @param settings the settings
*/
private void runPlot(TcPalmAnalysisSettings settings) {
final WindowOrganiser wo = new WindowOrganiser();
String timeLabel = "Time";
UnaryOperator<float[]> timeConverter;
double timeScale;
if (settings.getTimeInSeconds()) {
timeLabel += " (s)";
timeScale = 1.0 / results.getCalibration().getTimeCalibration().getExposureTime();
timeConverter = frames -> {
SimpleArrayUtils.apply(frames, f -> f *= timeScale);
return frames;
};
} else {
timeLabel += " (frame)";
timeConverter = UnaryOperator.identity();
timeScale = 1;
}
final CumulativeCountData data = this.countData;
String title = TITLE + " Activations vs Time";
final Plot plot1 = new Plot(title, timeLabel, "Count");
plot1.addLabel(0, 0, TextUtils.pleural(clusters.size(), "cluster"));
for (int i = 0; i < data.frames.length; i++) {
final int t = data.frames[i];
final int c = data.counts[i];
plot1.addPoints(timeConverter.apply(new float[] { t, t }), new float[] { 0, c }, Plot.LINE);
}
plot1.draw();
plot1.setLimitsToFit(true);
if (settings.getFixedTimeAxis()) {
final double[] limits = plot1.getLimits();
limits[0] = timeScale * (minT - 1);
limits[1] = timeScale * (maxT + 1);
plot1.setLimits(limits);
plot1.updateImage();
}
final PlotWindow pw1 = ImageJUtils.display(title, plot1, ImageJUtils.NO_TO_FRONT, wo);
title = TITLE + " Total Activations vs Time";
final Plot plot2 = new Plot(title, timeLabel, "Cumulative count");
final int localisations = data.counts.length == 0 ? 0 : data.plotCounts[data.plotCounts.length - 1];
final int clashes = localisations - data.counts.length;
plot2.addLabel(0, 0, TextUtils.pleural(localisations, "localisation") + " : " + clashes + TextUtils.pleuralise(clashes, " clash", " clashes"));
plot2.addPoints(timeConverter.apply(SimpleArrayUtils.toFloat(data.plotFrames)), SimpleArrayUtils.toFloat(data.plotCounts), Plot.LINE);
if (settings.getFixedTimeAxis()) {
plot2.setLimits(timeScale * (minT - 1), timeScale * (maxT + 1), Double.NaN, Double.NaN);
}
final PlotWindow pw2 = ImageJUtils.display(title, plot2, ImageJUtils.NO_TO_FRONT, wo);
activationsPlotData = new ActivationsPlotData(plot2, timeConverter, data);
// Simple tile one window above the other only if both are new.
if (wo.size() == 2) {
final Point p = pw1.getLocation();
p.y += pw1.getHeight();
pw2.setLocation(p);
}
}
use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.
the class DriftCalculator method plotDrift.
private static PlotWindow plotDrift(PlotWindow parent, double[][] interpolated, double[][] original, String name, int index) {
// Create plot
final double[] xlimits = MathUtils.limits(interpolated[0]);
double[] ylimits = MathUtils.limits(original[index]);
ylimits = MathUtils.limits(ylimits, interpolated[index]);
final Plot plot = new Plot(name, "Frame", "Drift (px)");
plot.setLimits(xlimits[0], xlimits[1], ylimits[0], ylimits[1]);
// De-saturated blue
plot.setColor(new Color(0, 0, 155));
plot.addPoints(original[0], original[index], Plot.CROSS);
plot.setColor(java.awt.Color.RED);
plot.addPoints(interpolated[0], interpolated[index], Plot.LINE);
final WindowOrganiser wo = new WindowOrganiser();
final PlotWindow window = ImageJUtils.display(name, plot, wo);
if (wo.isNotEmpty() && parent != null) {
final Point location = parent.getLocation();
location.y += parent.getHeight();
window.setLocation(location);
}
return window;
}
use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.
the class DriftCalculator method plotDrift.
private void plotDrift(int[] limits, double[] dx, double[] dy) {
if (!settings.plotDrift) {
return;
}
// Build an array of timepoints from the min to the max
final double[] completeT = new double[limits[1] + 1];
for (int i = limits[0]; i < completeT.length; i++) {
completeT[i] = i;
}
// Drift should be centred around zero for the calculated points to produce a fair plot
normalise(lastdx, calculatedTimepoints);
normalise(lastdy, calculatedTimepoints);
// Extract the interpolated points and the original drift
final double[][] interpolated = extractValues(dx, limits[0], limits[1], dx, dy);
final double[][] original = extractValues(calculatedTimepoints, limits[0], limits[1], lastdx, lastdy);
final PlotWindow window = plotDrift(null, interpolated, original, "Drift X", 1);
ploty.set(plotDrift(window, interpolated, original, "Drift Y", 2));
plotx.set(window);
}
use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.
the class PsfDrift method showHwhm.
private void showHwhm() {
// Build a list of suitable images
final List<String> titles = createImageList(false);
if (titles.isEmpty()) {
IJ.error(TITLE, "No suitable PSF images");
return;
}
final GenericDialog gd = new GenericDialog(TITLE);
gd.addMessage("Approximate the volume of the PSF as a Gaussian and\n" + "compute the equivalent Gaussian width.");
settings = Settings.load();
gd.addChoice("PSF", titles.toArray(new String[0]), settings.title);
gd.addCheckbox("Use_offset", settings.useOffset);
gd.addSlider("Smoothing", 0, 0.5, settings.smoothing);
gd.addHelp(HelpUrls.getUrl("psf-hwhm"));
gd.showDialog();
if (gd.wasCanceled()) {
return;
}
settings.title = gd.getNextChoice();
settings.useOffset = gd.getNextBoolean();
settings.smoothing = gd.getNextNumber();
settings.save();
imp = WindowManager.getImage(settings.title);
if (imp == null) {
IJ.error(TITLE, "No PSF image for image: " + settings.title);
return;
}
psfSettings = getPsfSettings(imp);
if (psfSettings == null) {
IJ.error(TITLE, "No PSF settings for image: " + settings.title);
return;
}
final int size = imp.getStackSize();
final ImagePsfModel psf = createImagePsf(1, size, 1);
final double[] w0 = psf.getAllHwhm0();
final double[] w1 = psf.getAllHwhm1();
// Get current centre
final int centre = psfSettings.getCentreImage();
// Extract valid values (some can be NaN)
double[] sw0 = new double[w0.length];
double[] sw1 = new double[w1.length];
final TDoubleArrayList s0 = new TDoubleArrayList(w0.length);
final TDoubleArrayList s1 = new TDoubleArrayList(w0.length);
int c0 = 0;
int c1 = 0;
for (int i = 0; i < w0.length; i++) {
if (Double.isFinite(w0[i])) {
s0.add(i + 1);
sw0[c0++] = w0[i];
}
if (Double.isFinite(w1[i])) {
s1.add(i + 1);
sw1[c1++] = w1[i];
}
}
if (c0 == 0 && c1 == 0) {
IJ.error(TITLE, "No computed HWHM for image: " + settings.title);
return;
}
double[] slice0 = s0.toArray();
sw0 = Arrays.copyOf(sw0, c0);
double[] slice1 = s1.toArray();
sw1 = Arrays.copyOf(sw1, c1);
// Smooth
if (settings.smoothing > 0) {
final LoessInterpolator loess = new LoessInterpolator(settings.smoothing, 1);
sw0 = loess.smooth(slice0, sw0);
sw1 = loess.smooth(slice1, sw1);
}
final TDoubleArrayList minWx = new TDoubleArrayList();
final TDoubleArrayList minWy = new TDoubleArrayList();
for (int i = 0; i < w0.length; i++) {
double weight = 0;
if (Double.isFinite(w0[i])) {
if (Double.isFinite(w1[i])) {
weight = w0[i] * w1[i];
} else {
weight = w0[i] * w0[i];
}
} else if (Double.isFinite(w1[i])) {
weight = w1[i] * w1[i];
}
if (weight != 0) {
minWx.add(i + 1);
minWy.add(Math.sqrt(weight));
}
}
// Smooth the combined line
final double[] cx = minWx.toArray();
double[] cy = minWy.toArray();
if (settings.smoothing > 0) {
final LoessInterpolator loess = new LoessInterpolator(settings.smoothing, 1);
cy = loess.smooth(cx, cy);
}
final int newCentre = SimpleArrayUtils.findMinIndex(cy);
// Convert to FWHM
final double fwhm = psfSettings.getFwhm();
// Widths are in pixels
final String title = TITLE + " HWHM";
final Plot plot = new Plot(title, "Slice", "HWHM (px)");
double[] limits = MathUtils.limits(sw0);
limits = MathUtils.limits(limits, sw1);
final double maxY = limits[1] * 1.05;
plot.setLimits(1, size, 0, maxY);
plot.setColor(Color.red);
plot.addPoints(slice0, sw0, Plot.LINE);
plot.setColor(Color.blue);
plot.addPoints(slice1, sw1, Plot.LINE);
plot.setColor(Color.magenta);
plot.addPoints(cx, cy, Plot.LINE);
plot.setColor(Color.black);
plot.addLabel(0, 0, "X=red; Y=blue, Combined=Magenta");
final PlotWindow pw = ImageJUtils.display(title, plot);
// Show a non-blocking dialog to allow the centre to be updated ...
// Add a label and dynamically update when the centre is moved.
final NonBlockingExtendedGenericDialog gd2 = new NonBlockingExtendedGenericDialog(TITLE);
final double scale = psfSettings.getPixelSize();
// @formatter:off
ImageJUtils.addMessage(gd2, "Update the PSF information?\n \n" + "Current z-centre = %d, FHWM = %s px (%s nm)\n", centre, MathUtils.rounded(fwhm), MathUtils.rounded(fwhm * scale));
// @formatter:on
gd2.addSlider("z-centre", cx[0], cx[cx.length - 1], newCentre);
final TextField tf = gd2.getLastTextField();
gd2.addMessage("");
gd2.addAndGetButton("Reset", event -> tf.setText(Integer.toString(newCentre)));
final Label label = gd2.getLastLabel();
gd2.addCheckbox("Update_centre", settings.updateCentre);
gd2.addCheckbox("Update_HWHM", settings.updateHwhm);
gd2.enableYesNoCancel();
gd2.hideCancelButton();
final UpdateDialogListener dl = new UpdateDialogListener(cx, cy, maxY, newCentre, scale, pw, label);
gd2.addDialogListener(dl);
gd.addHelp(HelpUrls.getUrl("psf-hwhm"));
gd2.showDialog();
if (gd2.wasOKed() && (settings.updateCentre || settings.updateHwhm)) {
final ImagePSF.Builder b = psfSettings.toBuilder();
if (settings.updateCentre) {
b.setCentreImage(dl.centre);
}
if (settings.updateHwhm) {
b.setFwhm(dl.getFwhm());
}
imp.setProperty("Info", ImagePsfHelper.toString(b));
}
}
use of ij.gui.PlotWindow in project GDSC-SMLM by aherbert.
the class PsfCreator method plotSignalAtSpecifiedSd.
/**
* Show a plot of the amount of signal within N x SD for each z position. This indicates how much
* the PSF has spread from the original Gaussian shape.
*
* @param psf The PSF
* @param fittedSd The width of the PSF (in pixels)
* @param factor The factor to use
* @param slice The slice used to create the label
*/
private void plotSignalAtSpecifiedSd(ImageStack psf, double fittedSd, double factor, int slice) {
if (signalZ == null) {
// Get the bounds
final int radius = (int) Math.round(fittedSd * factor);
final int min = Math.max(0, psf.getWidth() / 2 - radius);
final int max = Math.min(psf.getWidth() - 1, psf.getWidth() / 2 + radius);
// Create a circle mask of the PSF projection
final ByteProcessor circle = new ByteProcessor(max - min + 1, max - min + 1);
circle.setColor(255);
circle.fillOval(0, 0, circle.getWidth(), circle.getHeight());
final byte[] mask = (byte[]) circle.getPixels();
// Sum the pixels within the mask for each slice
signalZ = new double[psf.getSize()];
signal = new double[psf.getSize()];
for (int i = 0; i < psf.getSize(); i++) {
double sum = 0;
final float[] data = (float[]) psf.getProcessor(i + 1).getPixels();
for (int y = min, ii = 0; y <= max; y++) {
int index = y * psf.getWidth() + min;
for (int x = min; x <= max; x++, ii++, index++) {
if (mask[ii] != 0 && data[index] > 0) {
sum += data[index];
}
}
}
double total = 0;
for (final float f : data) {
if (f > 0) {
total += f;
}
}
signalZ[i] = i + 1;
signal[i] = 100 * sum / total;
}
signalTitle = String.format("%% PSF signal at %s x SD", MathUtils.rounded(factor, 3));
signalLimits = MathUtils.limits(signal);
}
// Plot the sum
final boolean alignWindows = (WindowManager.getFrame(signalTitle) == null);
final double total = signal[slice - 1];
final Plot plot = new Plot(signalTitle, "z", "Signal");
plot.addPoints(signalZ, signal, Plot.LINE);
plot.addLabel(0, 0, String.format("Total = %s. z = %s nm", MathUtils.rounded(total), MathUtils.rounded((slice - zCentre) * settings.getNmPerSlice())));
plot.setColor(Color.green);
plot.drawLine(slice, signalLimits[0], slice, signalLimits[1]);
plot.setColor(Color.blue);
final PlotWindow plotWindow = ImageJUtils.display(signalTitle, plot);
if (alignWindows && plotWindow != null) {
final PlotWindow otherWindow = getPlot(TITLE_AMPLITUDE);
if (otherWindow != null) {
// Put the two plots tiled together so both are visible
final Point l = plotWindow.getLocation();
l.x = otherWindow.getLocation().x + otherWindow.getWidth();
l.y = otherWindow.getLocation().y;
plotWindow.setLocation(l);
}
}
}
Aggregations