Search in sources :

Example 76 with GenericDialog

use of ij.gui.GenericDialog in project GDSC-SMLM by aherbert.

the class PSFDrift method computeDrift.

private void computeDrift() {
    // Create a grid of XY offset positions between 0-1 for PSF insert
    final double[] grid = new double[gridSize];
    for (int i = 0; i < grid.length; i++) grid[i] = (double) i / gridSize;
    // Configure fitting region
    final int w = 2 * regionSize + 1;
    centrePixel = w / 2;
    // Check region size using the image PSF
    double newPsfWidth = (double) imp.getWidth() / scale;
    if (Math.ceil(newPsfWidth) > w)
        Utils.log(TITLE + ": Fitted region size (%d) is smaller than the scaled PSF (%.1f)", w, newPsfWidth);
    // Create robust PSF fitting settings
    final double a = psfSettings.nmPerPixel * scale;
    final double sa = PSFCalculator.squarePixelAdjustment(psfSettings.nmPerPixel * (psfSettings.fwhm / Gaussian2DFunction.SD_TO_FWHM_FACTOR), a);
    fitConfig.setInitialPeakStdDev(sa / a);
    fitConfig.setBackgroundFitting(backgroundFitting);
    fitConfig.setNotSignalFitting(false);
    fitConfig.setComputeDeviations(false);
    fitConfig.setDisableSimpleFilter(true);
    // Create the PSF over the desired z-depth
    int depth = (int) Math.round(zDepth / psfSettings.nmPerSlice);
    int startSlice = psfSettings.zCentre - depth;
    int endSlice = psfSettings.zCentre + depth;
    int nSlices = imp.getStackSize();
    startSlice = (startSlice < 1) ? 1 : (startSlice > nSlices) ? nSlices : startSlice;
    endSlice = (endSlice < 1) ? 1 : (endSlice > nSlices) ? nSlices : endSlice;
    ImagePSFModel psf = createImagePSF(startSlice, endSlice);
    int minz = startSlice - psfSettings.zCentre;
    int maxz = endSlice - psfSettings.zCentre;
    final int nZ = maxz - minz + 1;
    final int gridSize2 = grid.length * grid.length;
    total = nZ * gridSize2;
    // Store all the fitting results
    int nStartPoints = getNumberOfStartPoints();
    results = new double[total * nStartPoints][];
    // TODO - Add ability to iterate this, adjusting the current offset in the PSF
    // each iteration
    // Create a pool of workers
    int nThreads = Prefs.getThreads();
    BlockingQueue<Job> jobs = new ArrayBlockingQueue<Job>(nThreads * 2);
    List<Worker> workers = new LinkedList<Worker>();
    List<Thread> threads = new LinkedList<Thread>();
    for (int i = 0; i < nThreads; i++) {
        Worker worker = new Worker(jobs, psf, w, fitConfig);
        Thread t = new Thread(worker);
        workers.add(worker);
        threads.add(t);
        t.start();
    }
    // Fit 
    Utils.showStatus("Fitting ...");
    final int step = Utils.getProgressInterval(total);
    outer: for (int z = minz, i = 0; z <= maxz; z++) {
        for (int x = 0; x < grid.length; x++) for (int y = 0; y < grid.length; y++, i++) {
            if (IJ.escapePressed()) {
                break outer;
            }
            put(jobs, new Job(z, grid[x], grid[y], i));
            if (i % step == 0) {
                IJ.showProgress(i, total);
            }
        }
    }
    // If escaped pressed then do not need to stop the workers, just return
    if (Utils.isInterrupted()) {
        IJ.showProgress(1);
        return;
    }
    // Finish all the worker threads by passing in a null job
    for (int i = 0; i < threads.size(); i++) {
        put(jobs, new Job());
    }
    // Wait for all to finish
    for (int i = 0; i < threads.size(); i++) {
        try {
            threads.get(i).join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    threads.clear();
    IJ.showProgress(1);
    IJ.showStatus("");
    // Plot the average and SE for the drift curve
    // Plot the recall
    double[] zPosition = new double[nZ];
    double[] avX = new double[nZ];
    double[] seX = new double[nZ];
    double[] avY = new double[nZ];
    double[] seY = new double[nZ];
    double[] recall = new double[nZ];
    for (int z = minz, i = 0; z <= maxz; z++, i++) {
        Statistics statsX = new Statistics();
        Statistics statsY = new Statistics();
        for (int s = 0; s < nStartPoints; s++) {
            int resultPosition = i * gridSize2 + s * total;
            final int endResultPosition = resultPosition + gridSize2;
            while (resultPosition < endResultPosition) {
                if (results[resultPosition] != null) {
                    statsX.add(results[resultPosition][0]);
                    statsY.add(results[resultPosition][1]);
                }
                resultPosition++;
            }
        }
        zPosition[i] = z * psfSettings.nmPerSlice;
        avX[i] = statsX.getMean();
        seX[i] = statsX.getStandardError();
        avY[i] = statsY.getMean();
        seY[i] = statsY.getStandardError();
        recall[i] = (double) statsX.getN() / (nStartPoints * gridSize2);
    }
    // Find the range from the z-centre above the recall limit 
    int centre = 0;
    for (int slice = startSlice, i = 0; slice <= endSlice; slice++, i++) {
        if (slice == psfSettings.zCentre) {
            centre = i;
            break;
        }
    }
    if (recall[centre] < recallLimit)
        return;
    int start = centre, end = centre;
    for (int i = centre; i-- > 0; ) {
        if (recall[i] < recallLimit)
            break;
        start = i;
    }
    for (int i = centre; ++i < recall.length; ) {
        if (recall[i] < recallLimit)
            break;
        end = i;
    }
    int iterations = 1;
    LoessInterpolator loess = null;
    if (smoothing > 0)
        loess = new LoessInterpolator(smoothing, iterations);
    double[][] smoothx = displayPlot("Drift X", "X (nm)", zPosition, avX, seX, loess, start, end);
    double[][] smoothy = displayPlot("Drift Y", "Y (nm)", zPosition, avY, seY, loess, start, end);
    displayPlot("Recall", "Recall", zPosition, recall, null, null, start, end);
    WindowOrganiser wo = new WindowOrganiser();
    wo.tileWindows(idList);
    // Ask the user if they would like to store them in the image
    GenericDialog gd = new GenericDialog(TITLE);
    gd.enableYesNoCancel();
    gd.hideCancelButton();
    startSlice = psfSettings.zCentre - (centre - start);
    endSlice = psfSettings.zCentre + (end - centre);
    gd.addMessage(String.format("Save the drift to the PSF?\n \nSlices %d (%s nm) - %d (%s nm) above recall limit", startSlice, Utils.rounded(zPosition[start]), endSlice, Utils.rounded(zPosition[end])));
    gd.addMessage("Optionally average the end points to set drift outside the limits.\n(Select zero to ignore)");
    gd.addSlider("Number_of_points", 0, 10, positionsToAverage);
    gd.showDialog();
    if (gd.wasOKed()) {
        positionsToAverage = Math.abs((int) gd.getNextNumber());
        ArrayList<PSFOffset> offset = new ArrayList<PSFOffset>();
        final double pitch = psfSettings.nmPerPixel;
        int j = 0, jj = 0;
        for (int i = start, slice = startSlice; i <= end; slice++, i++) {
            j = findCentre(zPosition[i], smoothx, j);
            if (j == -1) {
                Utils.log("Failed to find the offset for depth %.2f", zPosition[i]);
                continue;
            }
            // The offset should store the difference to the centre in pixels so divide by the pixel pitch
            double cx = smoothx[1][j] / pitch;
            double cy = smoothy[1][j] / pitch;
            jj = findOffset(slice, jj);
            if (jj != -1) {
                cx += psfSettings.offset[jj].cx;
                cy += psfSettings.offset[jj].cy;
            }
            offset.add(new PSFOffset(slice, cx, cy));
        }
        addMissingOffsets(startSlice, endSlice, nSlices, offset);
        psfSettings.offset = offset.toArray(new PSFOffset[offset.size()]);
        psfSettings.addNote(TITLE, String.format("Solver=%s, Region=%d", PeakFit.getSolverName(fitConfig), regionSize));
        imp.setProperty("Info", XmlUtils.toXML(psfSettings));
    }
}
Also used : PSFOffset(gdsc.smlm.ij.settings.PSFOffset) ArrayList(java.util.ArrayList) WindowOrganiser(ij.plugin.WindowOrganiser) Statistics(gdsc.core.utils.Statistics) LinkedList(java.util.LinkedList) LoessInterpolator(org.apache.commons.math3.analysis.interpolation.LoessInterpolator) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) GenericDialog(ij.gui.GenericDialog) ImagePSFModel(gdsc.smlm.model.ImagePSFModel)

Example 77 with GenericDialog

use of ij.gui.GenericDialog in project GDSC-SMLM by aherbert.

the class PSFDrift method run.

/*
	 * (non-Javadoc)
	 * 
	 * @see ij.plugin.PlugIn#run(java.lang.String)
	 */
public void run(String arg) {
    SMLMUsageTracker.recordPlugin(this.getClass(), arg);
    // Build a list of suitable images
    List<String> titles = createImageList();
    if (titles.isEmpty()) {
        IJ.error(TITLE, "No suitable PSF images");
        return;
    }
    if ("hwhm".equals(arg)) {
        showHWHM(titles);
        return;
    }
    GenericDialog gd = new GenericDialog(TITLE);
    gd.addMessage("Select the input PSF image");
    gd.addChoice("PSF", titles.toArray(new String[titles.size()]), title);
    gd.addCheckbox("Use_offset", useOffset);
    gd.addNumericField("Scale", scale, 2);
    gd.addNumericField("z_depth", zDepth, 2, 6, "nm");
    gd.addNumericField("Grid_size", gridSize, 0);
    gd.addSlider("Recall_limit", 0.01, 1, recallLimit);
    gd.addSlider("Region_size", 2, 20, regionSize);
    gd.addCheckbox("Background_fitting", backgroundFitting);
    String[] solverNames = SettingsManager.getNames((Object[]) FitSolver.values());
    gd.addChoice("Fit_solver", solverNames, solverNames[fitConfig.getFitSolver().ordinal()]);
    String[] functionNames = SettingsManager.getNames((Object[]) FitFunction.values());
    gd.addChoice("Fit_function", functionNames, functionNames[fitConfig.getFitFunction().ordinal()]);
    // We need these to set bounds for any bounded fitters
    gd.addSlider("Min_width_factor", 0, 0.99, fitConfig.getMinWidthFactor());
    gd.addSlider("Width_factor", 1.01, 5, fitConfig.getWidthFactor());
    gd.addCheckbox("Offset_fit", offsetFitting);
    gd.addNumericField("Start_offset", startOffset, 3);
    gd.addCheckbox("Include_CoM_fit", comFitting);
    gd.addCheckbox("Use_sampling", useSampling);
    gd.addNumericField("Photons", photons, 0);
    gd.addSlider("Photon_limit", 0, 1, photonLimit);
    gd.addSlider("Smoothing", 0, 0.5, smoothing);
    gd.showDialog();
    if (gd.wasCanceled())
        return;
    title = gd.getNextChoice();
    useOffset = gd.getNextBoolean();
    scale = gd.getNextNumber();
    zDepth = gd.getNextNumber();
    gridSize = (int) gd.getNextNumber();
    recallLimit = gd.getNextNumber();
    regionSize = (int) Math.abs(gd.getNextNumber());
    backgroundFitting = gd.getNextBoolean();
    fitConfig.setFitSolver(gd.getNextChoiceIndex());
    fitConfig.setFitFunction(gd.getNextChoiceIndex());
    fitConfig.setMinWidthFactor(gd.getNextNumber());
    fitConfig.setWidthFactor(gd.getNextNumber());
    offsetFitting = gd.getNextBoolean();
    startOffset = Math.abs(gd.getNextNumber());
    comFitting = gd.getNextBoolean();
    useSampling = gd.getNextBoolean();
    photons = Math.abs(gd.getNextNumber());
    photonLimit = Math.abs(gd.getNextNumber());
    smoothing = Math.abs(gd.getNextNumber());
    if (!comFitting && !offsetFitting) {
        IJ.error(TITLE, "No initial fitting positions");
        return;
    }
    if (regionSize < 1)
        regionSize = 1;
    if (gd.invalidNumber())
        return;
    GlobalSettings settings = new GlobalSettings();
    settings.setFitEngineConfiguration(new FitEngineConfiguration(fitConfig));
    if (!PeakFit.configureFitSolver(settings, null, false, true))
        return;
    imp = WindowManager.getImage(title);
    if (imp == null) {
        IJ.error(TITLE, "No PSF image for image: " + title);
        return;
    }
    psfSettings = getPSFSettings(imp);
    if (psfSettings == null) {
        IJ.error(TITLE, "No PSF settings for image: " + title);
        return;
    }
    computeDrift();
}
Also used : FitEngineConfiguration(gdsc.smlm.engine.FitEngineConfiguration) GenericDialog(ij.gui.GenericDialog) GlobalSettings(gdsc.smlm.ij.settings.GlobalSettings)

Example 78 with GenericDialog

use of ij.gui.GenericDialog in project GDSC-SMLM by aherbert.

the class OverlayImage method addImage.

/**
	 * Adapted from ij.plugins.OverlayCommands#addImage(boolean) with the additional option for setting the zero pixels
	 * to transparent.
	 */
void addImage() {
    ImagePlus imp = IJ.getImage();
    int[] wList = WindowManager.getIDList();
    if (wList == null || wList.length < 2) {
        IJ.error("Add Image...", "The command requires at least two open images.");
        return;
    }
    String[] titles = new String[wList.length];
    int count = 0;
    for (int i = 0; i < wList.length; i++) {
        ImagePlus imp2 = WindowManager.getImage(wList[i]);
        if (imp2 != null && imp2 != imp && imp.getWidth() >= imp2.getWidth() && imp.getHeight() >= imp2.getHeight())
            titles[count++] = imp2.getTitle();
    }
    if (count < 1) {
        IJ.error("Add Image...", "The command requires at least one valid overlay image.");
        return;
    }
    titles = Arrays.copyOf(titles, count);
    int x = 0, y = 0;
    Roi roi = imp.getRoi();
    if (roi != null && roi.isArea()) {
        Rectangle r = roi.getBounds();
        x = r.x;
        y = r.y;
    }
    GenericDialog gd = new GenericDialog("Add Image...");
    gd.addChoice("Image to add:", titles, title);
    gd.addNumericField("X location:", x, 0);
    gd.addNumericField("Y location:", y, 0);
    gd.addNumericField("Opacity (0-100%):", opacity, 0);
    gd.addCheckbox("Transparent background", transparent);
    gd.addCheckbox("Replace overlay", replace);
    gd.showDialog();
    if (gd.wasCanceled())
        return;
    title = gd.getNextChoice();
    x = (int) gd.getNextNumber();
    y = (int) gd.getNextNumber();
    opacity = (int) gd.getNextNumber();
    transparent = gd.getNextBoolean();
    replace = gd.getNextBoolean();
    ImagePlus overlay = WindowManager.getImage(title);
    if (overlay == imp) {
        IJ.error("Add Image...", "Image to be added cannot be the same as\n\"" + imp.getTitle() + "\".");
        return;
    }
    if (overlay.getWidth() > imp.getWidth() && overlay.getHeight() > imp.getHeight()) {
        IJ.error("Add Image...", "Image to be added cannnot be larger than\n\"" + imp.getTitle() + "\".");
        return;
    }
    ImageRoi roi2 = new ImageRoi(x, y, overlay.getProcessor());
    roi2.setZeroTransparent(transparent);
    roi2.setName(overlay.getShortTitle());
    if (opacity != 100)
        roi2.setOpacity(opacity / 100.0);
    Overlay overlayList = imp.getOverlay();
    if (overlayList == null || replace)
        overlayList = new Overlay();
    overlayList.add(roi2);
    imp.setOverlay(overlayList);
    Undo.setup(Undo.OVERLAY_ADDITION, imp);
}
Also used : GenericDialog(ij.gui.GenericDialog) Rectangle(java.awt.Rectangle) ImageRoi(ij.gui.ImageRoi) Overlay(ij.gui.Overlay) ImagePlus(ij.ImagePlus) ImageRoi(ij.gui.ImageRoi) Roi(ij.gui.Roi)

Example 79 with GenericDialog

use of ij.gui.GenericDialog in project GDSC-SMLM by aherbert.

the class PSFCreator method subtractBackgroundAndWindow.

/**
	 * Subtract the background from the spot, compute the intensity within half the box region distance from the centre
	 * and smooth the intensity profile. In interactive mode the user must choose to accept the profile or reject.
	 * If accepted the smoothed profile is user to normalise the image and then the image is rolled off to zero
	 * using a Tukey window function.
	 * 
	 * @param spot
	 * @param background
	 *            The minimum level, all below this is background and set to zero
	 * @param spotWidth
	 * @param spotHeight
	 * @param n
	 *            The spot number
	 * @param loess
	 *            The smoothing interpolator
	 * @return True if accepted
	 */
private boolean subtractBackgroundAndWindow(float[][] spot, final float background, final int spotWidth, final int spotHeight, double[] centre, LoessInterpolator loess) {
    //ImageWindow imageWindow = new ImageWindow();
    for (int i = 0; i < spot.length; i++) {
        for (int j = 0; j < spot[i].length; j++) spot[i][j] = FastMath.max(spot[i][j] - background, 0);
    }
    // Create a distance map from the centre
    if (lastWidth != spotWidth || lastHeight != spotHeight) {
        final double cx = spotWidth * 0.5;
        final double cy = spotHeight * 0.5;
        minx = FastMath.max(0, (int) (cx - boxRadius * 0.5));
        maxx = FastMath.min(spotWidth, (int) Math.ceil(cx + boxRadius * 0.5));
        miny = FastMath.max(0, (int) (cy - boxRadius * 0.5));
        maxy = FastMath.min(spotHeight, (int) Math.ceil(cy + boxRadius * 0.5));
        // Precompute square distances
        double[] dx2 = new double[maxx - minx + 1];
        for (int x = minx, i = 0; x < maxx; x++, i++) {
            // Use pixel centres with 0.5 offset
            final double dx = x + 0.5 - cx;
            dx2[i] = dx * dx;
        }
        dmap = new boolean[dx2.length * (maxy - miny + 1)];
        final double d2 = boxRadius * boxRadius / 4;
        for (int y = miny, j = 0; y < maxy; y++) {
            final double dy = (y + 0.5 - cy);
            final double dy2 = dy * dy;
            final double limit = d2 - dy2;
            for (int x = minx, i = 0; x < maxx; x++, i++, j++) {
                dmap[j] = (dx2[i] < limit);
            }
        }
        lastWidth = spotWidth;
        lastHeight = spotHeight;
    }
    // Calculate the intensity profile within half the box radius from the centre
    double[] xValues = new double[spot.length];
    double[] yValues = new double[spot.length];
    for (int i = 0; i < spot.length; i++) {
        xValues[i] = i + 1;
        double sum = 0;
        for (int y = miny, j = 0; y < maxy; y++) {
            int index = y * spotWidth + minx;
            for (int x = minx; x < maxx; x++, index++, j++) if (dmap[j])
                sum += spot[i][index];
        }
        yValues[i] = sum;
    }
    double[] newY = loess.smooth(xValues, yValues);
    // falls towards zero at the ends)
    for (int i = 0; i < newY.length; i++) if (newY[i] < 0)
        newY[i] = yValues[i];
    if (interactiveMode) {
        Utils.hide(TITLE_AMPLITUDE);
        Utils.hide(TITLE_PSF_PARAMETERS);
        final int n = (int) centre[4];
        String title = TITLE_INTENSITY;
        Plot plot = new Plot(title, "Slice", "Sum", xValues, yValues);
        plot.setColor(Color.red);
        plot.addPoints(xValues, newY, Plot.LINE);
        plot.setColor(Color.green);
        double[] limits = Maths.limits(yValues);
        plot.drawLine(centre[2], limits[0], centre[2], limits[1]);
        plot.setColor(Color.black);
        plot.addLabel(0, 0, "Spot " + n);
        Utils.display(title, plot);
        GenericDialog gd = new GenericDialog(TITLE);
        gd.enableYesNoCancel();
        gd.hideCancelButton();
        gd.addMessage(String.format("Add spot %d to the PSF?\n(The intensity profile is the sum within half the box region)", n));
        if (yesNoPosition != null) {
            gd.centerDialog(false);
            gd.setLocation(yesNoPosition);
        }
        gd.showDialog();
        yesNoPosition = gd.getLocation();
        if (!gd.wasOKed())
            return false;
    }
    for (int i = 0; i < spot.length; i++) {
        // Normalise
        final float scale = (float) (newY[i] / yValues[i]);
        for (int j = 0; j < spot[i].length; j++) spot[i][j] *= scale;
        // Use a Tukey window to roll-off the image edges
        //spot[i] = imageWindow.applySeperable(spot[i], spotWidth, spotHeight, ImageWindow.WindowFunction.Tukey);
        spot[i] = ImageWindow.applyWindow(spot[i], spotWidth, spotHeight, ImageWindow.WindowFunction.TUKEY);
    }
    return true;
}
Also used : Plot(ij.gui.Plot) GenericDialog(ij.gui.GenericDialog) Point(java.awt.Point) BasePoint(gdsc.core.match.BasePoint)

Example 80 with GenericDialog

use of ij.gui.GenericDialog in project GDSC-SMLM by aherbert.

the class ImageBackground method showDialog.

private int showDialog() {
    GenericDialog gd = new GenericDialog(TITLE);
    gd.addHelp(About.HELP_URL);
    gd.addMessage("Creates a background and mask image from a sample input stack\nusing a median projection");
    gd.addNumericField("Bias", bias, 0);
    gd.addSlider("Blur", 0, 20, sigma);
    gd.showDialog();
    if (gd.wasCanceled())
        return DONE;
    bias = (float) gd.getNextNumber();
    sigma = gd.getNextNumber();
    // Check arguments
    try {
        Parameters.isPositive("Bias", bias);
    } catch (IllegalArgumentException e) {
        IJ.error(TITLE, e.getMessage());
        return DONE;
    }
    return flags;
}
Also used : GenericDialog(ij.gui.GenericDialog)

Aggregations

GenericDialog (ij.gui.GenericDialog)87 NonBlockingGenericDialog (ij.gui.NonBlockingGenericDialog)12 ExtendedGenericDialog (ij.gui.ExtendedGenericDialog)10 GlobalSettings (gdsc.smlm.ij.settings.GlobalSettings)9 Checkbox (java.awt.Checkbox)9 Color (java.awt.Color)8 Component (java.awt.Component)8 GridBagConstraints (java.awt.GridBagConstraints)8 GridBagLayout (java.awt.GridBagLayout)8 Rectangle (java.awt.Rectangle)7 BasePoint (gdsc.core.match.BasePoint)6 FitConfiguration (gdsc.smlm.fitting.FitConfiguration)6 PeakResultPoint (gdsc.smlm.ij.plugins.ResultsMatchCalculator.PeakResultPoint)6 Calibration (gdsc.smlm.results.Calibration)6 ArrayList (java.util.ArrayList)6 PeakResult (gdsc.smlm.results.PeakResult)5 TextField (java.awt.TextField)5 File (java.io.File)5 Vector (java.util.Vector)5 FitEngineConfiguration (gdsc.smlm.engine.FitEngineConfiguration)4