Search in sources :

Example 6 with PSF

use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF in project GDSC-SMLM by aherbert.

the class PsfCreator method fitPsf.

/**
 * Fit the new PSF image and show a graph of the amplitude/width.
 *
 * @param psfStack the psf stack
 * @param loess the loess
 * @param cz the cz
 * @param averageRange the average range
 * @param fitCom the fit com
 * @return The width of the PSF in the z-centre
 */
private double fitPsf(ImageStack psfStack, LoessInterpolator loess, int cz, double averageRange, final double[][] fitCom) {
    IJ.showStatus("Fitting final PSF");
    // is not appropriate for a normalised PSF.
    if (fitConfig.getFitSolver() != FitSolver.LVM_LSE) {
        ImageJUtils.log("  " + FitProtosHelper.getName(fitConfig.getFitSolver()) + " is not appropriate for final PSF fitting.");
        ImageJUtils.log("  Switching to Least Square Estimation");
        fitConfig.setFitSolver(FitSolver.LVM_LSE);
        if (settings.getInteractiveMode()) {
            // This assumes the LVM does not need the calibration
            PeakFit.configureFitSolver(config, null, null, 0);
        }
    }
    // Update the box radius since this is used in the fitSpot method.
    boxRadius = psfStack.getWidth() / 2;
    final int x = boxRadius;
    final int y = boxRadius;
    final double shift = fitConfig.getCoordinateShiftFactor();
    // Scale the PSF
    final PSF.Builder localPsf = fitConfig.getPsf().toBuilder();
    for (int i = 0; i < localPsf.getParametersCount(); i++) {
        final PSFParameter param = localPsf.getParameters(i);
        if (param.getUnit() == PSFParameterUnit.DISTANCE) {
            final PSFParameter.Builder b = param.toBuilder();
            b.setValue(b.getValue() * settings.getMagnification());
            localPsf.setParameters(i, b);
        }
    }
    fitConfig.setPsf(localPsf.build());
    // Need to be updated after the widths have been set
    fitConfig.setCoordinateShiftFactor(shift);
    fitConfig.setBackgroundFitting(false);
    // Since the PSF will be normalised remove the camera calibration
    fitConfig.setCameraType(CameraType.CAMERA_TYPE_NA);
    fitConfig.setMinPhotons(0);
    fitConfig.setBias(0);
    fitConfig.setGain(1);
    // No complex filtering so we get a fit. It should be easy to fit anyway.
    fitConfig.setPrecisionThreshold(0);
    fitConfig.setDirectFilter(null);
    // fitConfig.setDisableSimpleFilter(true);
    // Use this for debugging the fit
    // fitConfig.setLog(uk.ac.sussex.gdsc.core.ij.ImageJPluginLoggerHelper.getDefaultLogger());
    final MemoryPeakResults results = fitSpot(psfStack, psfStack.getWidth(), psfStack.getHeight(), x, y);
    if (results.size() < 5) {
        ImageJUtils.log("  Final PSF: Not enough fit results %d", results.size());
        return 0;
    }
    // Get the results for the spot centre and width
    final double[] z = new double[results.size()];
    final double[] xCoord = new double[z.length];
    final double[] yCoord = new double[z.length];
    final double[] sd = new double[z.length];
    final double[] a = new double[z.length];
    // Set limits for the fit
    final float maxWidth = (float) (Math.max(fitConfig.getInitialXSd(), fitConfig.getInitialYSd()) * settings.getMagnification() * 4);
    // PSF is normalised to 1
    final float maxSignal = 2;
    final WidthResultProcedure wp = new WidthResultProcedure(results, DistanceUnit.PIXEL);
    wp.getWxWy();
    final HeightResultProcedure hp = new HeightResultProcedure(results, IntensityUnit.COUNT);
    hp.getH();
    final Counter counter = new Counter();
    final Counter counterOk = new Counter();
    // We have fit the results so they will be in the preferred units
    results.forEach((PeakResultProcedure) peak -> {
        int index = counter.getAndIncrement();
        final float w = Math.max(wp.wx[index], wp.wy[index]);
        if (peak.getIntensity() > maxSignal || w > maxWidth) {
            return;
        }
        index = counterOk.getAndIncrement();
        z[index] = peak.getFrame();
        fitCom[0][peak.getFrame() - 1] = xCoord[index] = peak.getXPosition() - x;
        fitCom[1][peak.getFrame() - 1] = yCoord[index] = peak.getYPosition() - y;
        sd[index] = w;
        a[index] = hp.heights[index];
    });
    // Truncate
    final double[] z2 = Arrays.copyOf(z, counter.getCount());
    final double[] xCoord2 = Arrays.copyOf(xCoord, z2.length);
    final double[] yCoord2 = Arrays.copyOf(yCoord, z2.length);
    final double[] sd2 = Arrays.copyOf(sd, z2.length);
    final double[] a2 = Arrays.copyOf(a, z2.length);
    // Extract the average smoothed range from the individual fits
    final int r = (int) Math.ceil(averageRange / 2);
    int start = 0;
    int stop = z2.length - 1;
    for (int j = 0; j < z2.length; j++) {
        if (z2[j] > cz - r) {
            start = j;
            break;
        }
    }
    for (int j = z2.length; j-- > 0; ) {
        if (z2[j] < cz + r) {
            stop = j;
            break;
        }
    }
    // Extract xy centre coords and smooth
    double[] smoothX = new double[stop - start + 1];
    double[] smoothY = new double[smoothX.length];
    double[] smoothSd = new double[smoothX.length];
    double[] smoothA = new double[smoothX.length];
    final double[] newZ = new double[smoothX.length];
    int smoothCzIndex = 0;
    for (int j = start, k = 0; j <= stop; j++, k++) {
        smoothX[k] = xCoord2[j];
        smoothY[k] = yCoord2[j];
        smoothSd[k] = sd2[j];
        smoothA[k] = a2[j];
        newZ[k] = z2[j];
        if (newZ[k] == cz) {
            smoothCzIndex = k;
        }
    }
    smoothX = loess.smooth(newZ, smoothX);
    smoothY = loess.smooth(newZ, smoothY);
    smoothSd = loess.smooth(newZ, smoothSd);
    smoothA = loess.smooth(newZ, smoothA);
    // Update the widths and positions using the magnification
    final double scale = 1.0 / settings.getMagnification();
    for (int j = 0; j < xCoord2.length; j++) {
        xCoord2[j] *= scale;
        yCoord2[j] *= scale;
        sd2[j] *= scale;
    }
    for (int j = 0; j < smoothX.length; j++) {
        smoothX[j] *= scale;
        smoothY[j] *= scale;
        smoothSd[j] *= scale;
    }
    showPlots(z2, a2, newZ, smoothA, xCoord2, yCoord2, sd2, newZ, smoothX, smoothY, smoothSd, cz);
    // Store the data for replotting
    this.z = z2;
    this.amplitude = a2;
    this.smoothAz = newZ;
    this.smoothA = smoothA;
    this.xCoord = xCoord2;
    this.yCoord = yCoord2;
    this.sd = sd2;
    this.newZ = newZ;
    this.smoothX = smoothX;
    this.smoothY = smoothY;
    this.smoothSd = smoothSd;
    // maximumIndex = findMinimumIndex(smoothSd, maximumIndex - start);
    return smoothSd[smoothCzIndex];
}
Also used : HeightResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.HeightResultProcedure) Color(java.awt.Color) Tensor2D(uk.ac.sussex.gdsc.smlm.utils.Tensor2D) Arrays(java.util.Arrays) ByteProcessor(ij.process.ByteProcessor) UnitConverterUtils(uk.ac.sussex.gdsc.smlm.data.config.UnitConverterUtils) ImageProcessor(ij.process.ImageProcessor) WindowMethod(uk.ac.sussex.gdsc.core.utils.ImageWindow.WindowMethod) MemoryUtils(uk.ac.sussex.gdsc.core.utils.MemoryUtils) PSFType(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFType) CustomTricubicFunction(uk.ac.sussex.gdsc.core.math.interpolation.CustomTricubicFunction) Future(java.util.concurrent.Future) PSFCreatorSettings(uk.ac.sussex.gdsc.smlm.ij.settings.GUIProtos.PSFCreatorSettings) ImageWindow(uk.ac.sussex.gdsc.core.utils.ImageWindow) ImageCanvas(ij.gui.ImageCanvas) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) Blitter(ij.process.Blitter) FitProtosHelper(uk.ac.sussex.gdsc.smlm.data.config.FitProtosHelper) ImageJImageConverter(uk.ac.sussex.gdsc.smlm.ij.utils.ImageJImageConverter) SoftLock(uk.ac.sussex.gdsc.core.utils.SoftLock) Frame(java.awt.Frame) LoessInterpolator(org.apache.commons.math3.analysis.interpolation.LoessInterpolator) DistanceUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit) ConcurrencyUtils(uk.ac.sussex.gdsc.core.utils.concurrent.ConcurrencyUtils) GuiProtosHelper(uk.ac.sussex.gdsc.smlm.ij.settings.GuiProtosHelper) TextUtils(uk.ac.sussex.gdsc.core.utils.TextUtils) Gaussian2DFunction(uk.ac.sussex.gdsc.smlm.function.gaussian.Gaussian2DFunction) Plot(ij.gui.Plot) Executors(java.util.concurrent.Executors) ImagePlus(ij.ImagePlus) Line(ij.gui.Line) ExceptionUtils(org.apache.commons.lang3.exception.ExceptionUtils) Prefs(ij.Prefs) StoredData(uk.ac.sussex.gdsc.core.utils.StoredData) SimpleDateFormat(java.text.SimpleDateFormat) WindowManager(ij.WindowManager) PeakResult(uk.ac.sussex.gdsc.smlm.results.PeakResult) ArrayList(java.util.ArrayList) GenericDialog(ij.gui.GenericDialog) SortUtils(uk.ac.sussex.gdsc.core.utils.SortUtils) RounderUtils(uk.ac.sussex.gdsc.core.data.utils.RounderUtils) SubPixelMethod(uk.ac.sussex.gdsc.core.ij.AlignImagesFft.SubPixelMethod) PeakResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure) ImagePsfHelper(uk.ac.sussex.gdsc.smlm.ij.settings.ImagePsfHelper) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration) Overlay(ij.gui.Overlay) ImageExtractor(uk.ac.sussex.gdsc.core.utils.ImageExtractor) SimpleImageJTrackProgress(uk.ac.sussex.gdsc.core.ij.SimpleImageJTrackProgress) Size(uk.ac.sussex.gdsc.core.math.interpolation.CustomTricubicInterpolatingFunction.Size) FitEngine(uk.ac.sussex.gdsc.smlm.engine.FitEngine) FloatProcessor(ij.process.FloatProcessor) FloatStackTrivalueProvider(uk.ac.sussex.gdsc.core.data.FloatStackTrivalueProvider) CubicSplinePsf(uk.ac.sussex.gdsc.smlm.ij.plugins.CubicSplineManager.CubicSplinePsf) DescriptiveStatistics(org.apache.commons.math3.stat.descriptive.DescriptiveStatistics) ImageStack(ij.ImageStack) CameraModel(uk.ac.sussex.gdsc.smlm.model.camera.CameraModel) PsfHelper(uk.ac.sussex.gdsc.smlm.data.config.PsfHelper) Erf(uk.ac.sussex.gdsc.smlm.function.Erf) FloatStackTrivalueProcedure(uk.ac.sussex.gdsc.core.data.procedures.FloatStackTrivalueProcedure) AngleUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.AngleUnit) Date(java.util.Date) Point(java.awt.Point) ImagePSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF) PSFParameter(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFParameter) FitSolver(uk.ac.sussex.gdsc.smlm.data.config.FitProtos.FitSolver) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) OptionCollectedListener(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog.OptionCollectedListener) Locale(java.util.Locale) DataException(uk.ac.sussex.gdsc.core.data.DataException) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) PlotWindow(ij.gui.PlotWindow) MathUtils(uk.ac.sussex.gdsc.core.utils.MathUtils) CalibrationWriter(uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter) CustomTricubicInterpolatingFunction(uk.ac.sussex.gdsc.core.math.interpolation.CustomTricubicInterpolatingFunction) PlugInFilter(ij.plugin.filter.PlugInFilter) PsfProtosHelper(uk.ac.sussex.gdsc.smlm.data.config.PsfProtosHelper) FitParameters(uk.ac.sussex.gdsc.smlm.engine.FitParameters) SettingsManager(uk.ac.sussex.gdsc.smlm.ij.settings.SettingsManager) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) CameraType(uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.CameraType) BlockMeanFilter(uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter) CustomTricubicInterpolator(uk.ac.sussex.gdsc.core.math.interpolation.CustomTricubicInterpolator) HeightResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.HeightResultProcedure) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) AlignImagesFft(uk.ac.sussex.gdsc.core.ij.AlignImagesFft) FitEngineConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitEngineConfiguration) FloatPolygon(ij.process.FloatPolygon) OffsetPointRoi(uk.ac.sussex.gdsc.core.ij.gui.OffsetPointRoi) WidthResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.WidthResultProcedure) PSFParameterUnit(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFParameterUnit) List(java.util.List) SimpleArrayUtils(uk.ac.sussex.gdsc.core.utils.SimpleArrayUtils) OptionCollectedEvent(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog.OptionCollectedEvent) FitQueue(uk.ac.sussex.gdsc.smlm.engine.FitQueue) TypeConverter(uk.ac.sussex.gdsc.core.data.utils.TypeConverter) Roi(ij.gui.Roi) ParameterisedFitJob(uk.ac.sussex.gdsc.smlm.engine.ParameterisedFitJob) Image3DAligner(uk.ac.sussex.gdsc.smlm.ij.utils.Image3DAligner) Rectangle(java.awt.Rectangle) PSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF) HashMap(java.util.HashMap) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) IntensityUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.IntensityUnit) AtomicReference(java.util.concurrent.atomic.AtomicReference) TextField(java.awt.TextField) OptionListener(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog.OptionListener) AWTEvent(java.awt.AWTEvent) IJImageSource(uk.ac.sussex.gdsc.smlm.ij.IJImageSource) LinkedList(java.util.LinkedList) CcdCameraModel(uk.ac.sussex.gdsc.smlm.model.camera.CcdCameraModel) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) ExecutorService(java.util.concurrent.ExecutorService) DialogListener(ij.gui.DialogListener) Calibration(ij.measure.Calibration) Checkbox(java.awt.Checkbox) CubicSplinePosition(uk.ac.sussex.gdsc.core.math.interpolation.CubicSplinePosition) Label(java.awt.Label) CreateData(uk.ac.sussex.gdsc.smlm.ij.plugins.benchmark.CreateData) Rounder(uk.ac.sussex.gdsc.core.data.utils.Rounder) CalibrationReader(uk.ac.sussex.gdsc.smlm.data.config.CalibrationReader) Counter(uk.ac.sussex.gdsc.smlm.results.count.Counter) ImageJUtils(uk.ac.sussex.gdsc.core.ij.ImageJUtils) SynchronizedPeakResults(uk.ac.sussex.gdsc.smlm.results.SynchronizedPeakResults) IJ(ij.IJ) FileInfo(ij.io.FileInfo) Image2DAligner(uk.ac.sussex.gdsc.smlm.ij.utils.Image2DAligner) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) ImagePSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.ImagePSF) PSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF) PSFParameter(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFParameter) WidthResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.WidthResultProcedure) Point(java.awt.Point) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) Counter(uk.ac.sussex.gdsc.smlm.results.count.Counter) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)

Example 7 with PSF

use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF in project GDSC-SMLM by aherbert.

the class PeakFit method configureFitSolver.

/**
 * Show a dialog to configure the fit solver. The updated settings are saved to the settings file.
 * An error message is shown if the dialog is cancelled or the configuration is invalid.
 *
 * <p>The bounds are used to validate the camera model. The camera model must be large enough to
 * cover the source bounds. If larger then it will be cropped. Optionally an internal region of
 * the input image can be specified. This is relative to the width and height of the input image.
 * If no camera model is present then the bounds can be null.
 *
 * @param config the configuration
 * @param sourceBounds the source image bounds (used to validate the camera model dimensions)
 * @param bounds the crop bounds (relative to the input image, used to validate the camera model
 *        dimensions)
 * @param flags the flags
 * @return True if the configuration succeeded
 */
public static boolean configureFitSolver(FitEngineConfiguration config, Rectangle sourceBounds, Rectangle bounds, int flags) {
    final boolean extraOptions = BitFlagUtils.anySet(flags, FLAG_EXTRA_OPTIONS);
    final boolean ignoreCalibration = BitFlagUtils.anySet(flags, FLAG_IGNORE_CALIBRATION);
    final boolean saveSettings = BitFlagUtils.anyNotSet(flags, FLAG_NO_SAVE);
    final FitConfiguration fitConfig = config.getFitConfiguration();
    final CalibrationWriter calibration = fitConfig.getCalibrationWriter();
    final FitSolver fitSolver = fitConfig.getFitSolver();
    final boolean isLvm = fitSolver == FitSolver.LVM_LSE || fitSolver == FitSolver.LVM_WLSE || fitSolver == FitSolver.LVM_MLE;
    // Support the deprecated backtracking FastMLE solver as a plain FastMLE solver
    final boolean isFastMml = fitSolver == FitSolver.FAST_MLE || fitSolver == FitSolver.BACKTRACKING_FAST_MLE;
    final boolean isSteppingFunctionSolver = isLvm || isFastMml;
    if (fitSolver == FitSolver.MLE) {
        final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
        if (!ignoreCalibration) {
            gd.addMessage("Maximum Likelihood Estimation requires CCD-type camera parameters");
            gd.addNumericField("Camera_bias", calibration.getBias(), 2, 6, "count");
            gd.addCheckbox("Model_camera_noise", fitConfig.isModelCamera());
            gd.addNumericField("Read_noise", calibration.getReadNoise(), 2, 6, "count");
            gd.addNumericField("Quantum_efficiency", calibration.getQuantumEfficiency(), 2, 6, "electron/photon");
            gd.addCheckbox("EM-CCD", calibration.isEmCcd());
        } else {
            gd.addMessage("Maximum Likelihood Estimation requires additional parameters");
        }
        final String[] searchNames = SettingsManager.getSearchMethodNames();
        gd.addChoice("Search_method", searchNames, FitProtosHelper.getName(fitConfig.getSearchMethod()));
        gd.addStringField("Relative_threshold", MathUtils.rounded(fitConfig.getRelativeThreshold()));
        gd.addStringField("Absolute_threshold", MathUtils.rounded(fitConfig.getAbsoluteThreshold()));
        gd.addNumericField("Max_iterations", fitConfig.getMaxIterations(), 0);
        gd.addNumericField("Max_function_evaluations", fitConfig.getMaxFunctionEvaluations(), 0);
        if (extraOptions) {
            gd.addCheckbox("Gradient_line_minimisation", fitConfig.isGradientLineMinimisation());
        }
        gd.showDialog();
        if (gd.wasCanceled()) {
            return false;
        }
        if (!ignoreCalibration) {
            calibration.setBias(Math.abs(gd.getNextNumber()));
            fitConfig.setModelCamera(gd.getNextBoolean());
            calibration.setReadNoise(Math.abs(gd.getNextNumber()));
            calibration.setQuantumEfficiency(Math.abs(gd.getNextNumber()));
            calibration.setCameraType((gd.getNextBoolean()) ? CameraType.EMCCD : CameraType.CCD);
            fitConfig.setCalibration(calibration.getCalibration());
        }
        fitConfig.setSearchMethod(SettingsManager.getSearchMethodValues()[gd.getNextChoiceIndex()]);
        fitConfig.setRelativeThreshold(getThresholdNumber(gd));
        fitConfig.setAbsoluteThreshold(getThresholdNumber(gd));
        fitConfig.setMaxIterations((int) gd.getNextNumber());
        fitConfig.setMaxFunctionEvaluations((int) gd.getNextNumber());
        if (extraOptions) {
            fitConfig.setGradientLineMinimisation(gd.getNextBoolean());
        } else {
            // This option is for the Conjugate Gradient optimiser and makes it less stable
            fitConfig.setGradientLineMinimisation(false);
        }
        if (saveSettings) {
            saveFitEngineSettings(config);
        }
        try {
            ParameterUtils.isAboveZero("Relative threshold", fitConfig.getRelativeThreshold());
            ParameterUtils.isAboveZero("Absolute threshold", fitConfig.getAbsoluteThreshold());
            ParameterUtils.isAboveZero("Max iterations", fitConfig.getMaxIterations());
            ParameterUtils.isAboveZero("Max function evaluations", fitConfig.getMaxFunctionEvaluations());
            fitConfig.getFunctionSolver();
        } catch (final IllegalArgumentException | IllegalStateException ex) {
            IJ.error(TITLE, ex.getMessage());
            return false;
        }
    } else if (isSteppingFunctionSolver) {
        final boolean requireCalibration = !ignoreCalibration && fitSolver != FitSolver.LVM_LSE;
        // Collect options for LVM fitting
        final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
        final String fitSolverName = FitProtosHelper.getName(fitSolver);
        gd.addMessage(fitSolverName + " requires additional parameters");
        gd.addStringField("Relative_threshold", MathUtils.rounded(fitConfig.getRelativeThreshold()));
        gd.addStringField("Absolute_threshold", MathUtils.rounded(fitConfig.getAbsoluteThreshold()));
        gd.addStringField("Parameter_relative_threshold", MathUtils.rounded(fitConfig.getParameterRelativeThreshold()));
        gd.addStringField("Parameter_absolute_threshold", MathUtils.rounded(fitConfig.getParameterAbsoluteThreshold()));
        gd.addNumericField("Max_iterations", fitConfig.getMaxIterations(), 0);
        if (isLvm) {
            gd.addNumericField("Lambda", fitConfig.getLambda(), 4);
        }
        if (isFastMml) {
            gd.addCheckbox("Fixed_iterations", fitConfig.isFixedIterations());
            // This works because the proto configuration enum matches the named enum
            final String[] lineSearchNames = SettingsManager.getNames((Object[]) FastMleSteppingFunctionSolver.LineSearchMethod.values());
            gd.addChoice("Line_search_method", lineSearchNames, lineSearchNames[fitConfig.getLineSearchMethod().getNumber()]);
        }
        gd.addCheckbox("Use_clamping", fitConfig.isUseClamping());
        gd.addCheckbox("Dynamic_clamping", fitConfig.isUseDynamicClamping());
        final PSF psf = fitConfig.getPsf();
        final boolean isAstigmatism = psf.getPsfType() == PSFType.ASTIGMATIC_GAUSSIAN_2D;
        final int nParams = PsfHelper.getParameterCount(psf);
        if (extraOptions) {
            gd.addNumericField("Clamp_background", fitConfig.getClampBackground(), 2);
            gd.addNumericField("Clamp_signal", fitConfig.getClampSignal(), 2);
            gd.addNumericField("Clamp_x", fitConfig.getClampX(), 2);
            gd.addNumericField("Clamp_y", fitConfig.getClampY(), 2);
            if (isAstigmatism) {
                gd.addNumericField("Clamp_z", fitConfig.getClampZ(), 2);
            } else {
                if (nParams > 1 || !fitConfig.isFixedPsf()) {
                    gd.addNumericField("Clamp_sx", fitConfig.getClampXSd(), 2);
                }
                if (nParams > 1) {
                    gd.addNumericField("Clamp_sy", fitConfig.getClampYSd(), 2);
                }
                if (nParams > 2) {
                    gd.addNumericField("Clamp_angle", fitConfig.getClampAngle(), 2);
                }
            }
        }
        // Extra parameters are needed for calibrated fit solvers
        if (requireCalibration) {
            switch(calibration.getCameraType()) {
                case CCD:
                case EMCCD:
                case SCMOS:
                    break;
                default:
                    IJ.error(TITLE, fitSolverName + " requires camera calibration");
                    return false;
            }
            gd.addMessage(fitSolverName + " requires calibration for camera: " + CalibrationProtosHelper.getName(calibration.getCameraType()));
            if (calibration.isScmos()) {
                final String[] models = CameraModelManager.listCameraModels(true);
                gd.addChoice("Camera_model_name", models, fitConfig.getCameraModelName());
            } else {
                gd.addNumericField("Camera_bias", calibration.getBias(), 2, 6, "Count");
                gd.addNumericField("Gain", calibration.getCountPerPhoton(), 2, 6, "Count/photon");
                gd.addNumericField("Read_noise", calibration.getReadNoise(), 2, 6, "Count");
            }
        }
        gd.showDialog();
        if (gd.wasCanceled()) {
            return false;
        }
        fitConfig.setRelativeThreshold(getThresholdNumber(gd));
        fitConfig.setAbsoluteThreshold(getThresholdNumber(gd));
        fitConfig.setParameterRelativeThreshold(getThresholdNumber(gd));
        fitConfig.setParameterAbsoluteThreshold(getThresholdNumber(gd));
        fitConfig.setMaxIterations((int) gd.getNextNumber());
        if (isLvm) {
            fitConfig.setLambda(gd.getNextNumber());
        }
        if (isFastMml) {
            fitConfig.setFixedIterations(gd.getNextBoolean());
            fitConfig.setLineSearchMethod(gd.getNextChoiceIndex());
        }
        fitConfig.setUseClamping(gd.getNextBoolean());
        fitConfig.setUseDynamicClamping(gd.getNextBoolean());
        if (extraOptions) {
            fitConfig.setClampBackground(Math.abs(gd.getNextNumber()));
            fitConfig.setClampSignal(Math.abs(gd.getNextNumber()));
            fitConfig.setClampX(Math.abs(gd.getNextNumber()));
            fitConfig.setClampY(Math.abs(gd.getNextNumber()));
            if (isAstigmatism) {
                fitConfig.setClampZ(Math.abs(gd.getNextNumber()));
            } else {
                if (nParams > 1 || !fitConfig.isFixedPsf()) {
                    fitConfig.setClampXSd(Math.abs(gd.getNextNumber()));
                }
                if (nParams > 1) {
                    fitConfig.setClampYSd(Math.abs(gd.getNextNumber()));
                }
                if (nParams > 2) {
                    fitConfig.setClampAngle(Math.abs(gd.getNextNumber()));
                }
            }
        }
        if (requireCalibration) {
            if (calibration.isScmos()) {
                fitConfig.setCameraModelName(gd.getNextChoice());
            } else {
                calibration.setBias(Math.abs(gd.getNextNumber()));
                calibration.setCountPerPhoton(Math.abs(gd.getNextNumber()));
                calibration.setReadNoise(Math.abs(gd.getNextNumber()));
                fitConfig.setCalibration(calibration.getCalibration());
            }
        }
        // camera model is set.
        if (calibration.isScmos()) {
            fitConfig.setCameraModel(CameraModelManager.load(fitConfig.getCameraModelName()));
            if (!checkCameraModel(fitConfig, sourceBounds, bounds, true)) {
                return false;
            }
        }
        if (saveSettings) {
            saveFitEngineSettings(config);
        }
        try {
            if (isLvm) {
                ParameterUtils.isAboveZero("Lambda", fitConfig.getLambda());
            }
            // This call will check if the configuration is OK (including convergence criteria)
            fitConfig.getFunctionSolver();
        } catch (final IllegalArgumentException | IllegalStateException ex) {
            IJ.error(TITLE, ex.getMessage());
            return false;
        }
    } else {
        IJ.error(TITLE, "Unknown fit solver: " + fitSolver);
        return false;
    }
    if (config.isIncludeNeighbours() && !fitConfig.getFunctionSolver().isBounded()) {
        IJ.error(TITLE, "Including neighbours requires a bounded fit solver");
        return false;
    }
    return true;
}
Also used : FitSolver(uk.ac.sussex.gdsc.smlm.data.config.FitProtos.FitSolver) PSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF) FitConfiguration(uk.ac.sussex.gdsc.smlm.engine.FitConfiguration) CalibrationWriter(uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)

Example 8 with PSF

use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF in project GDSC-SMLM by aherbert.

the class PeakResultsReader method simplifyTwoAxis.

/**
 * Simplify two axis Gaussian 2D data.
 *
 * @param results the results
 * @param removeTheta the remove theta flag
 */
private void simplifyTwoAxis(MemoryPeakResults results, boolean removeTheta) {
    final int[] indices = PsfHelper.getGaussian2DWxWyIndices(psf);
    final int isx = indices[0];
    final int isy = indices[1];
    // Columns to remove
    int remove = (removeTheta) ? 1 : 0;
    // New PSF type
    PSFType psfType;
    // Determine if sy is redundant
    if (results.forEach((PeakResultProcedureX) peakResult -> peakResult.getParameter(isx) != peakResult.getParameter(isy))) {
        if (!removeTheta) {
            // Already a TwoAxis Gaussian
            return;
        }
        // Otherwise this was a TwoAxisAndTheta with 1 column to remove
        // so it should be simplified
        psfType = PSFType.TWO_AXIS_GAUSSIAN_2D;
    } else {
        // sy is redundant so remove another column
        psfType = PSFType.ONE_AXIS_GAUSSIAN_2D;
        remove++;
    }
    // Update the PSF
    final PSF.Builder builder = psf.toBuilder();
    builder.setPsfType(psfType);
    psf = builder.build();
    results.setPsf(psf);
    // Update the results.
    // We can directly manipulate the params array
    final int newLength = results.getf(0).getNumberOfParameters() - remove;
    if (deviations) {
        results.forEach((PeakResultProcedure) peakResult -> {
            peakResult.resizeParameters(newLength);
            peakResult.resizeParameterDeviations(newLength);
        });
    } else {
        results.forEach((PeakResultProcedure) peakResult -> peakResult.resizeParameters(newLength));
    }
}
Also used : Rectangle(java.awt.Rectangle) DataInputStream(java.io.DataInputStream) AngleUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.AngleUnit) Calibration(uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.Calibration) PeakResultProcedureX(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedureX) Scanner(java.util.Scanner) PSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF) IntensityUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.IntensityUnit) PSFType(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFType) TrackProgress(uk.ac.sussex.gdsc.core.logging.TrackProgress) Level(java.util.logging.Level) Matcher(java.util.regex.Matcher) NotNull(uk.ac.sussex.gdsc.core.annotation.NotNull) Locale(java.util.Locale) XStreamUtils(uk.ac.sussex.gdsc.smlm.utils.XStreamUtils) UnicodeReader(uk.ac.sussex.gdsc.core.utils.UnicodeReader) PeakResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure) CalibrationWriter(uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter) NoSuchElementException(java.util.NoSuchElementException) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) CameraType(uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.CameraType) IOException(java.io.IOException) DistanceUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit) FileInputStream(java.io.FileInputStream) Logger(java.util.logging.Logger) EOFException(java.io.EOFException) TextUtils(uk.ac.sussex.gdsc.core.utils.TextUtils) TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit) Objects(java.util.Objects) BitFlagUtils(uk.ac.sussex.gdsc.core.utils.BitFlagUtils) JsonFormat(com.google.protobuf.util.JsonFormat) Nullable(uk.ac.sussex.gdsc.core.annotation.Nullable) FileUtils(uk.ac.sussex.gdsc.core.utils.FileUtils) PsfHelper(uk.ac.sussex.gdsc.smlm.data.config.PsfHelper) BufferedReader(java.io.BufferedReader) Pattern(java.util.regex.Pattern) FileChannel(java.nio.channels.FileChannel) PSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF) PSFType(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFType)

Example 9 with PSF

use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF in project GDSC-SMLM by aherbert.

the class PeakResultsReader method readNStorm.

private MemoryPeakResults readNStorm() {
    final MemoryPeakResults results = createResults();
    results.setName(FileUtils.getName(filename));
    try (FileInputStream fis = new FileInputStream(filename);
        BufferedReader input = new BufferedReader(new UnicodeReader(fis, null))) {
        final ProgressReporter reporter = createProgressReporter(fis);
        String line;
        int errors = 0;
        // The single line header
        final String header = input.readLine();
        if (header == null) {
            throw new IOException("NStorm header missing");
        }
        // NStorm files added more column fields for later formats.
        // If the header contains 'Photons' then this can be used to determine the gain
        boolean readPhotons = header.contains("\tPhotons\t");
        while ((line = input.readLine()) != null) {
            if (line.isEmpty()) {
                continue;
            }
            final PeakResult result = createNStormResult(line, readPhotons);
            if (result != null) {
                results.add(result);
                // Just read the photons from the first 100
                if (readPhotons) {
                    readPhotons = results.size() < 100;
                }
            } else if (++errors >= 10) {
                break;
            }
            reporter.showProgress();
        }
    } catch (final IOException ex) {
        logError(ex);
    }
    // The following relationship holds when length == 1:
    // intensity = height * 2 * pi * sd0 * sd1 / pixel_pitch^2
    // => Pixel_pitch = sqrt(height * 2 * pi * sd0 * sd1 / intensity)
    // Try and create a calibration
    final Statistics pixelPitch = new Statistics();
    results.forEach(new PeakResultProcedureX() {

        static final double TWO_PI = 2 * Math.PI;

        @Override
        public boolean execute(PeakResult peakResult) {
            if (peakResult.getFrame() == peakResult.getEndFrame()) {
                final float height = peakResult.getOrigValue();
                final float intensity = peakResult.getParameter(PeakResult.INTENSITY);
                final float sd0 = peakResult.getParameter(INDEX_SX);
                final float sd1 = peakResult.getParameter(INDEX_SY);
                pixelPitch.add(Math.sqrt(height * TWO_PI * sd0 * sd1 / intensity));
                // Stop when we have enough for a good guess
                return (pixelPitch.getN() > 100);
            }
            return false;
        }
    });
    // Determine the gain using the photons column
    final Statistics gain = new Statistics();
    results.forEach((PeakResultProcedureX) peakResult -> {
        double photons = peakResult.getError();
        if (photons != 0) {
            peakResult.setError(0);
            gain.add(peakResult.getIntensity() / photons);
            return false;
        }
        return true;
    });
    // TODO - Support all the NSTORM formats: one-axis, two-axis, rotated, 3D.
    // Is this information in the header?
    // We could support setting the PSF as a Gaussian2D with one/two axis SD.
    // This would mean updating all the result params if it is a one axis PSF.
    // For now just record it as a 2 axis PSF.
    // Create a calibration
    calibration = new CalibrationWriter();
    // NSTORM data is in counts when the Photons column is present.
    // Q. Is it in counts when this column is not present?
    calibration.setIntensityUnit(IntensityUnit.COUNT);
    calibration.setDistanceUnit(DistanceUnit.NM);
    if (pixelPitch.getN() > 0) {
        final double nmPerPixel = pixelPitch.getMean();
        calibration.setNmPerPixel(nmPerPixel);
    }
    if (gain.getN() > 0 && gain.getStandardError() < 1e-3) {
        calibration.setCountPerPhoton(gain.getMean());
    }
    results.setCalibration(calibration.getCalibration());
    return results;
}
Also used : Rectangle(java.awt.Rectangle) DataInputStream(java.io.DataInputStream) AngleUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.AngleUnit) Calibration(uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.Calibration) PeakResultProcedureX(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedureX) Scanner(java.util.Scanner) PSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF) IntensityUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.IntensityUnit) PSFType(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFType) TrackProgress(uk.ac.sussex.gdsc.core.logging.TrackProgress) Level(java.util.logging.Level) Matcher(java.util.regex.Matcher) NotNull(uk.ac.sussex.gdsc.core.annotation.NotNull) Locale(java.util.Locale) XStreamUtils(uk.ac.sussex.gdsc.smlm.utils.XStreamUtils) UnicodeReader(uk.ac.sussex.gdsc.core.utils.UnicodeReader) PeakResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure) CalibrationWriter(uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter) NoSuchElementException(java.util.NoSuchElementException) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) CameraType(uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.CameraType) IOException(java.io.IOException) DistanceUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit) FileInputStream(java.io.FileInputStream) Logger(java.util.logging.Logger) EOFException(java.io.EOFException) TextUtils(uk.ac.sussex.gdsc.core.utils.TextUtils) TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit) Objects(java.util.Objects) BitFlagUtils(uk.ac.sussex.gdsc.core.utils.BitFlagUtils) JsonFormat(com.google.protobuf.util.JsonFormat) Nullable(uk.ac.sussex.gdsc.core.annotation.Nullable) FileUtils(uk.ac.sussex.gdsc.core.utils.FileUtils) PsfHelper(uk.ac.sussex.gdsc.smlm.data.config.PsfHelper) BufferedReader(java.io.BufferedReader) Pattern(java.util.regex.Pattern) FileChannel(java.nio.channels.FileChannel) UnicodeReader(uk.ac.sussex.gdsc.core.utils.UnicodeReader) IOException(java.io.IOException) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) FileInputStream(java.io.FileInputStream) BufferedReader(java.io.BufferedReader) CalibrationWriter(uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter) PeakResultProcedureX(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedureX)

Example 10 with PSF

use of uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF in project GDSC-SMLM by aherbert.

the class TraceManager method convertToCentroidPeakResults.

/**
 * Convert a list of traces into peak results. The signal weighted centroid of each trace is used
 * as the coordinates. The weighted localisation precision is used as the width. The amplitude is
 * the average from all the peaks in the trace.
 *
 * <p>Uses the title and bounds from the provided peak results. The title has the word 'Traced
 * Centroids' appended.
 *
 * @param source the source
 * @param traces the traces
 * @return the peak results
 */
public static MemoryPeakResults convertToCentroidPeakResults(MemoryPeakResults source, final Trace[] traces) {
    final MemoryPeakResults results = toCentroidPeakResults(traces, source.getCalibration());
    // Do not copy the PSF as it is invalid for centroids
    final PSF psf = results.getPsf();
    results.copySettings(source);
    results.setPsf(psf);
    // Change name
    results.setName(source.getSource() + " Traced Centroids");
    // TODO - Add the tracing settings
    return results;
}
Also used : PSF(uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF)

Aggregations

PSF (uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSF)18 Rectangle (java.awt.Rectangle)8 CalibrationWriter (uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter)8 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)5 Calibration (uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.Calibration)5 PSFType (uk.ac.sussex.gdsc.smlm.data.config.PSFProtos.PSFType)5 DistanceUnit (uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit)5 FileInputStream (java.io.FileInputStream)4 IOException (java.io.IOException)4 Statistics (uk.ac.sussex.gdsc.core.utils.Statistics)4 TextUtils (uk.ac.sussex.gdsc.core.utils.TextUtils)4 CameraType (uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.CameraType)4 PsfHelper (uk.ac.sussex.gdsc.smlm.data.config.PsfHelper)4 IntensityUnit (uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.IntensityUnit)4 PeakResultProcedure (uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure)4 InvalidProtocolBufferException (com.google.protobuf.InvalidProtocolBufferException)3 BufferedReader (java.io.BufferedReader)3 Locale (java.util.Locale)3 FileUtils (uk.ac.sussex.gdsc.core.utils.FileUtils)3 UnicodeReader (uk.ac.sussex.gdsc.core.utils.UnicodeReader)3