Search in sources :

Example 61 with LocalList

use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.

the class PeakResultConversionHelper method getNames.

/**
 * Gets the names for the peak results parameters. This includes the standard parameters and any
 * additional parameters defined in the PSF. If a parameter name is undefined then unknown is
 * returned.
 *
 * @return the converters
 */
public String[] getNames() {
    final LocalList<String> list = new LocalList<>(5);
    list.add("Background");
    list.add("Intensity");
    list.add("X");
    list.add("Y");
    list.add("Z");
    if (psf != null) {
        try {
            for (final PSFParameter p : PsfHelper.getParameters(psf)) {
                final String name = p.getName();
                list.add(TextUtils.isNullOrEmpty(name) ? "unknown" : name);
            }
        } catch (final ConfigurationException ex) {
        // Ignore
        }
    }
    return list.toArray(new String[0]);
}
Also used : LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) ConfigurationException(uk.ac.sussex.gdsc.smlm.data.config.ConfigurationException) PSFParameter(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFParameter)

Example 62 with LocalList

use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.

the class PeakResultConversionHelper method getConverters.

/**
 * Gets the converters for the peak results parameters. This includes the standard parameters and
 * any additional parameters defined in the PSF. If a parameter unit type is undefined then an
 * identity converter is created.
 *
 * @return the converters
 */
public Converter[] getConverters() {
    final LocalList<Converter> list = new LocalList<>(5);
    getIntensityConverter();
    getDistanceConverter();
    list.add(intensityConverter);
    list.add(intensityConverter);
    list.add(distanceConverter);
    list.add(distanceConverter);
    list.add(distanceConverter);
    if (psf != null) {
        try {
            for (final PSFParameter p : PsfHelper.getParameters(psf)) {
                switch(p.getUnit()) {
                    case DISTANCE:
                        list.add(distanceConverter);
                        break;
                    case INTENSITY:
                        list.add(intensityConverter);
                        break;
                    case ANGLE:
                        list.add(getAngleConverter());
                        break;
                    default:
                        list.add(new IdentityTypeConverter<>(p.getUnit()));
                }
            }
        } catch (final ConfigurationException ex) {
        // Ignore
        }
    }
    return list.toArray(new Converter[0]);
}
Also used : LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) ConfigurationException(uk.ac.sussex.gdsc.smlm.data.config.ConfigurationException) IdentityTypeConverter(uk.ac.sussex.gdsc.core.data.utils.IdentityTypeConverter) Converter(uk.ac.sussex.gdsc.core.data.utils.Converter) TypeConverter(uk.ac.sussex.gdsc.core.data.utils.TypeConverter) PSFParameter(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFParameter)

Example 63 with LocalList

use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.

the class PeakResultConversionHelper method getUnitNames.

/**
 * Gets the unit names for the peak results parameters. This includes the standard parameters and
 * any additional parameters defined in the PSF. If a parameter unit is undefined then an empty
 * string is returned.
 *
 * @return the converters
 */
public String[] getUnitNames() {
    final LocalList<String> list = new LocalList<>(5);
    getIntensityConverter();
    getDistanceConverter();
    final String safeIntensityUnit = (intensityConverter.to() != null) ? UnitHelper.getShortName(intensityConverter.to()) : "";
    final String safeDistanceUnit = (distanceConverter.to() != null) ? UnitHelper.getShortName(distanceConverter.to()) : "";
    String safeAngleUnit = null;
    list.add(safeIntensityUnit);
    list.add(safeIntensityUnit);
    list.add(safeDistanceUnit);
    list.add(safeDistanceUnit);
    list.add(safeDistanceUnit);
    if (psf != null) {
        try {
            for (final PSFParameter p : PsfHelper.getParameters(psf)) {
                switch(p.getUnit()) {
                    case DISTANCE:
                        list.add(safeDistanceUnit);
                        break;
                    case INTENSITY:
                        list.add(safeIntensityUnit);
                        break;
                    case ANGLE:
                        safeAngleUnit = getOrCreateAngleUnit(safeAngleUnit);
                        list.add(safeAngleUnit);
                        break;
                    default:
                        list.add("");
                }
            }
        } catch (final ConfigurationException ex) {
        // Ignore
        }
    }
    return list.toArray(new String[0]);
}
Also used : LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) ConfigurationException(uk.ac.sussex.gdsc.smlm.data.config.ConfigurationException) PSFParameter(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFParameter)

Example 64 with LocalList

use of uk.ac.sussex.gdsc.core.utils.LocalList 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[settings.gridSize];
    for (int i = 0; i < grid.length; i++) {
        grid[i] = (double) i / settings.gridSize;
    }
    // Configure fitting region
    final int w = 2 * settings.regionSize + 1;
    centrePixel = w / 2;
    // Check region size using the image PSF
    final double newPsfWidth = imp.getWidth() / settings.scale;
    if (Math.ceil(newPsfWidth) > w) {
        ImageJUtils.log(TITLE + ": Fitted region size (%d) is smaller than the scaled PSF (%.1f)", w, newPsfWidth);
    }
    // Create robust PSF fitting settings
    final double a = psfSettings.getPixelSize() * settings.scale;
    final double sa = PsfCalculator.squarePixelAdjustment(psfSettings.getPixelSize() * (psfSettings.getFwhm() / Gaussian2DFunction.SD_TO_FWHM_FACTOR), a);
    fitConfig.setInitialPeakStdDev(sa / a);
    fitConfig.setBackgroundFitting(settings.backgroundFitting);
    fitConfig.setNotSignalFitting(false);
    fitConfig.setComputeDeviations(false);
    fitConfig.setDisableSimpleFilter(true);
    // Create the PSF over the desired z-depth
    final int depth = (int) Math.round(settings.zDepth / psfSettings.getPixelDepth());
    int startSlice = psfSettings.getCentreImage() - depth;
    int endSlice = psfSettings.getCentreImage() + depth;
    final int nSlices = imp.getStackSize();
    startSlice = MathUtils.clip(1, nSlices, startSlice);
    endSlice = MathUtils.clip(1, nSlices, endSlice);
    final ImagePsfModel psf = createImagePsf(startSlice, endSlice, settings.scale);
    final int minz = startSlice - psfSettings.getCentreImage();
    final int maxz = endSlice - psfSettings.getCentreImage();
    final int nZ = maxz - minz + 1;
    final int gridSize2 = grid.length * grid.length;
    total = nZ * gridSize2;
    // Store all the fitting results
    final 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
    final int threadCount = Prefs.getThreads();
    final Ticker ticker = ImageJUtils.createTicker(total, threadCount, "Fitting...");
    final BlockingQueue<Job> jobs = new ArrayBlockingQueue<>(threadCount * 2);
    final List<Thread> threads = new LinkedList<>();
    for (int i = 0; i < threadCount; i++) {
        final Worker worker = new Worker(jobs, psf, w, fitConfig, ticker);
        final Thread t = new Thread(worker);
        threads.add(t);
        t.start();
    }
    // Fit
    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 escaped pressed then do not need to stop the workers, just return
    if (ImageJUtils.isInterrupted()) {
        ImageJUtils.finished();
        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 (final InterruptedException ex) {
            Thread.currentThread().interrupt();
            throw new ConcurrentRuntimeException("Unexpected interrupt", ex);
        }
    }
    threads.clear();
    ImageJUtils.finished();
    // Plot the average and SE for the drift curve
    // Plot the recall
    final double[] zPosition = new double[nZ];
    final double[] avX = new double[nZ];
    final double[] seX = new double[nZ];
    final double[] avY = new double[nZ];
    final double[] seY = new double[nZ];
    final double[] recall = new double[nZ];
    for (int z = minz, i = 0; z <= maxz; z++, i++) {
        final Statistics statsX = new Statistics();
        final 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.getPixelDepth();
        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.getCentreImage()) {
            centre = i;
            break;
        }
    }
    if (recall[centre] < settings.recallLimit) {
        return;
    }
    int start = centre;
    int end = centre;
    for (int i = centre; i-- > 0; ) {
        if (recall[i] < settings.recallLimit) {
            break;
        }
        start = i;
    }
    for (int i = centre; ++i < recall.length; ) {
        if (recall[i] < settings.recallLimit) {
            break;
        }
        end = i;
    }
    final int iterations = 1;
    LoessInterpolator loess = null;
    if (settings.smoothing > 0) {
        loess = new LoessInterpolator(settings.smoothing, iterations);
    }
    final double[][] smoothx = displayPlot("Drift X", "X (nm)", zPosition, avX, seX, loess, start, end);
    final double[][] smoothy = displayPlot("Drift Y", "Y (nm)", zPosition, avY, seY, loess, start, end);
    displayPlot("Recall", "Recall", zPosition, recall, null, null, start, end);
    windowOrganiser.tile();
    // Ask the user if they would like to store them in the image
    final GenericDialog gd = new GenericDialog(TITLE);
    gd.enableYesNoCancel();
    gd.hideCancelButton();
    startSlice = psfSettings.getCentreImage() - (centre - start);
    endSlice = psfSettings.getCentreImage() + (end - centre);
    ImageJUtils.addMessage(gd, "Save the drift to the PSF?\n \nSlices %d (%s nm) - %d (%s nm) above recall limit", startSlice, MathUtils.rounded(zPosition[start]), endSlice, MathUtils.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, settings.positionsToAverage);
    gd.showDialog();
    if (gd.wasOKed()) {
        settings.positionsToAverage = Math.abs((int) gd.getNextNumber());
        final Map<Integer, Offset> oldOffset = psfSettings.getOffsetsMap();
        final boolean useOldOffset = settings.useOffset && !oldOffset.isEmpty();
        final LocalList<double[]> offset = new LocalList<>();
        final double pitch = psfSettings.getPixelSize();
        int index = 0;
        for (int i = start, slice = startSlice; i <= end; slice++, i++) {
            index = findCentre(zPosition[i], smoothx, index);
            if (index == -1) {
                ImageJUtils.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][index] / pitch;
            double cy = smoothy[1][index] / pitch;
            if (useOldOffset) {
                final Offset o = oldOffset.get(slice);
                if (o != null) {
                    cx += o.getCx();
                    cy += o.getCy();
                }
            }
            offset.add(new double[] { slice, cx, cy });
        }
        addMissingOffsets(startSlice, endSlice, nSlices, offset);
        final Offset.Builder offsetBuilder = Offset.newBuilder();
        final ImagePSF.Builder imagePsfBuilder = psfSettings.toBuilder();
        for (final double[] o : offset) {
            final int slice = (int) o[0];
            offsetBuilder.setCx(o[1]);
            offsetBuilder.setCy(o[2]);
            imagePsfBuilder.putOffsets(slice, offsetBuilder.build());
        }
        imagePsfBuilder.putNotes(TITLE, String.format("Solver=%s, Region=%d", PeakFit.getSolverName(fitConfig), settings.regionSize));
        imp.setProperty("Info", ImagePsfHelper.toString(imagePsfBuilder));
    }
}
Also used : LoessInterpolator(org.apache.commons.math3.analysis.interpolation.LoessInterpolator) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) ImagePSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) GenericDialog(ij.gui.GenericDialog) Ticker(uk.ac.sussex.gdsc.core.logging.Ticker) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) LinkedList(java.util.LinkedList) Offset(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.Offset) ConcurrentRuntimeException(org.apache.commons.lang3.concurrent.ConcurrentRuntimeException) ImagePsfModel(uk.ac.sussex.gdsc.smlm.model.ImagePsfModel)

Example 65 with LocalList

use of uk.ac.sussex.gdsc.core.utils.LocalList in project GDSC-SMLM by aherbert.

the class PsfCreator method align2D.

/**
 * Align the PSFs with the combined PSF using the Image2DAligner class to align the 2D max
 * intensity projections. The final alignment shift is the average of the shift from two
 * projection alignments for each dimension.
 *
 * @param combined the combined
 * @param psfs the psfs
 * @return The XYZ translations for each PSF
 */
private float[][] align2D(ExtractedPsf combined, final ExtractedPsf[] psfs) {
    // Note: For alignment we crop the X/Y projections around the current z-centre
    // so the middle of the 2D image is the middle of the projection.
    final int n = psfs.length * 3;
    final List<Future<?>> futures = new LocalList<>(n);
    final Image2DAligner[] align = new Image2DAligner[3];
    for (int i = 0; i < 3; i++) {
        align[i] = new Image2DAligner();
        // No need to set the bounds as the PSF will be smaller
        align[i].setReference(combined.getProjection(i, true).duplicate());
    }
    final float[][] results = new float[psfs.length][3];
    for (int j = 0; j < psfs.length; j++) {
        final int jj = j;
        for (int i = 0; i < 3; i++) {
            final int ii = i;
            futures.add(threadPool.submit(() -> {
                final ExtractedPsf psf = psfs[jj];
                final double[] result = align[ii].copy().align(psf.getProjection(ii, true).duplicate(), 10);
                // We just average the shift from each projection. There should be
                // two shifts for each dimension
                results[jj][Projection.getXDimension(ii)] -= result[0] / 2;
                results[jj][Projection.getYDimension(ii)] -= result[1] / 2;
            // psfs[index].show(TITLE + index);
            }));
        }
    }
    ConcurrencyUtils.waitForCompletionUnchecked(futures);
    return results;
}
Also used : LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) Future(java.util.concurrent.Future) Point(java.awt.Point) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) Image2DAligner(uk.ac.sussex.gdsc.smlm.ij.utils.Image2DAligner)

Aggregations

LocalList (uk.ac.sussex.gdsc.core.utils.LocalList)70 PeakResult (uk.ac.sussex.gdsc.smlm.results.PeakResult)19 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)15 MemoryPeakResults (uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)14 ImagePlus (ij.ImagePlus)13 Point (java.awt.Point)13 Future (java.util.concurrent.Future)13 Plot (ij.gui.Plot)11 ExecutorService (java.util.concurrent.ExecutorService)11 WindowOrganiser (uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser)11 TIntArrayList (gnu.trove.list.array.TIntArrayList)10 IJ (ij.IJ)10 PlugIn (ij.plugin.PlugIn)10 Rectangle (java.awt.Rectangle)10 AtomicReference (java.util.concurrent.atomic.AtomicReference)10 ImageJUtils (uk.ac.sussex.gdsc.core.ij.ImageJUtils)10 DistanceUnit (uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit)10 Color (java.awt.Color)9 Arrays (java.util.Arrays)9 Ticker (uk.ac.sussex.gdsc.core.logging.Ticker)9