package gdsc.smlm.function.gaussian;
import gdsc.smlm.function.gaussian.erf.SingleCircularErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.SingleFixedErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.SingleFreeCircularErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.SingleNBFreeCircularErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.MultiAstigmatismErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.MultiCircularErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.MultiFixedErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.MultiFreeCircularErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.MultiNBFreeCircularErfGaussian2DFunction;
import gdsc.smlm.function.gaussian.erf.SingleAstigmatismErfGaussian2DFunction;
/*-----------------------------------------------------------------------------
* GDSC SMLM Software
*
* Copyright (C) 2013 Alex Herbert
* Genome Damage and Stability Centre
* University of Sussex, UK
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------*/
/**
* Creates the appropriate Gaussian function.
* <p>
* Note that currently all functions support computing gradients for x/y position.
*/
public class GaussianFunctionFactory
{
/**
* Compute gradients for background
*/
public static final int FIT_BACKGROUND = 0x00000001;
/**
* Compute gradients for rotation angle
*/
public static final int FIT_ANGLE = 0x00000002;
/**
* Compute gradients for x width
*/
public static final int FIT_X_WIDTH = 0x00000004;
/**
* Compute gradients for y width
*/
public static final int FIT_Y_WIDTH = 0x00000008;
/**
* Compute gradients for signal
*/
public static final int FIT_SIGNAL = 0x00000010;
/**
* Compute gradients for z position
*/
public static final int FIT_Z = 0x00000020;
/**
* An elliptical 2D Gaussian with gradients for background, signal, rotation angle, x/y position, x/y width
*/
public static final int FIT_ELLIPTICAL = FIT_BACKGROUND | FIT_ANGLE | FIT_X_WIDTH | FIT_Y_WIDTH | FIT_SIGNAL;
/**
* An elliptical 2D Gaussian with gradients for background, signal, x/y position, x/y width
*/
public static final int FIT_FREE_CIRCLE = FIT_BACKGROUND | FIT_X_WIDTH | FIT_Y_WIDTH | FIT_SIGNAL;
/**
* A 2D Gaussian with gradients for background, signal, x/y position, width
*/
public static final int FIT_CIRCLE = FIT_BACKGROUND | FIT_X_WIDTH | FIT_SIGNAL;
/**
* A 2D Gaussian with gradients for background, signal, x/y position
*/
public static final int FIT_FIXED = FIT_BACKGROUND | FIT_SIGNAL;
/**
* An elliptical 2D Gaussian with gradients for background, signal, x/y/z position. The z position determines the
* x/y width using an astigmatism model.
*/
public static final int FIT_ASTIGMATISM = FIT_BACKGROUND | FIT_Z | FIT_SIGNAL;
// -=-=-=-=-=-=-=-=-=-=-=-=-
// Flags for ERF Gaussian functions.
// These are evaluated as a full integration over the pixel using the error function (erf)
// -=-=-=-=-=-=-=-=-=-=-=-=-
/**
* Use a full integration over the pixel using the error function (erf). A rotation angle is not supported.
*/
public static final int FIT_ERF = 0x00000100;
/**
* An elliptical 2D Gaussian (full integration per pixel) with gradients for background, signal, x/y position, x/y
* width
*/
public static final int FIT_ERF_FREE_CIRCLE = FIT_FREE_CIRCLE | FIT_ERF;
/**
* A 2D Gaussian (full integration per pixel) with gradients for background, signal, x/y position, width
*/
public static final int FIT_ERF_CIRCLE = FIT_CIRCLE | FIT_ERF;
/**
* A 2D Gaussian (full integration per pixel) with gradients for background, signal, x/y position
*/
public static final int FIT_ERF_FIXED = FIT_FIXED | FIT_ERF;
/**
* An elliptical 2D Gaussian (full integration per pixel) with gradients for background, signal, x/y/z position. The
* z position determines the x/y width using an astigmatism model.
*/
public static final int FIT_ERF_ASTIGMATISM = FIT_BACKGROUND | FIT_Z | FIT_SIGNAL | FIT_ERF;
// -=-=-=-=-=-=-=-=-=-=-=-=-
// Flags for simple Gaussian functions.
// These are evaluated using a single exponential at the centre of the pixel.
// They support rotating the X/Y elliptical Gaussian (if X and Y are different).
// -=-=-=-=-=-=-=-=-=-=-=-=-
/**
* Use a single exponential at the centre of the pixel. A rotation angle is supported.
*/
public static final int FIT_SIMPLE = 0x00000200;
/**
* An elliptical 2D Gaussian (single exponential per pixel) with gradients for background, signal, rotation angle,
* x/y position, x/y width
*/
public static final int FIT_SIMPLE_ELLIPTICAL = FIT_ELLIPTICAL | FIT_SIMPLE;
/**
* An elliptical 2D Gaussian (single exponential per pixel) with gradients for background, signal, x/y position, x/y
* width
*/
public static final int FIT_SIMPLE_FREE_CIRCLE = FIT_FREE_CIRCLE | FIT_SIMPLE;
/**
* A 2D Gaussian (single exponential per pixel) with gradients for background, signal, x/y position, width
*/
public static final int FIT_SIMPLE_CIRCLE = FIT_CIRCLE | FIT_SIMPLE;
/**
* A 2D Gaussian (single exponential per pixel) with gradients for background, signal, x/y position
*/
public static final int FIT_SIMPLE_FIXED = FIT_FIXED | FIT_SIMPLE;
// Extra support for functions without background
/**
* An elliptical 2D Gaussian (full integration per pixel) with gradients for signal, x/y position, x/y
* width
*/
public static final int FIT_ERF_NB_FREE_CIRCLE = FIT_X_WIDTH | FIT_Y_WIDTH | FIT_SIGNAL | FIT_ERF;
/**
* An elliptical 2D Gaussian (single exponential per pixel) with gradients for signal, rotation angle,
* x/y position, x/y width
*/
public static final int FIT_SIMPLE_NB_ELLIPTICAL = FIT_ANGLE | FIT_X_WIDTH | FIT_Y_WIDTH | FIT_SIGNAL | FIT_SIMPLE;
/**
* An elliptical 2D Gaussian (single exponential per pixel) with gradients for signal, x/y position, x/y
* width
*/
public static final int FIT_SIMPLE_NB_FREE_CIRCLE = FIT_X_WIDTH | FIT_Y_WIDTH | FIT_SIGNAL | FIT_SIMPLE;
/**
* A 2D Gaussian (single exponential per pixel) with gradients for signal, x/y position, width
*/
public static final int FIT_SIMPLE_NB_CIRCLE = FIT_X_WIDTH | FIT_SIGNAL | FIT_SIMPLE;
/**
* A 2D Gaussian (single exponential per pixel) with gradients for signal, x/y position
*/
public static final int FIT_SIMPLE_NB_FIXED = FIT_SIGNAL | FIT_SIMPLE;
/**
* A 2D Gaussian (single exponential per pixel) with gradients for background, x/y position
*/
public static final int FIT_SIMPLE_NS_FIXED = FIT_BACKGROUND | FIT_SIMPLE;
/**
* A 2D Gaussian (single exponential per pixel) with gradients for x/y position
*/
public static final int FIT_SIMPLE_NS_NB_FIXED = FIT_SIMPLE;
/**
* Create the correct 2D Gaussian function for the specified parameters.
* <p>
* Defaults to using the ERF Gaussian functions if the user has not requested a simple Gaussian or angle fitting.
*
* @param nPeaks
* The number of peaks (N)
* @param maxx
* The maximum X-dimension
* @param maxy
* The maximum Y-dimension
* @param flags
* Enable all the parameters that should evaluate gradient
* @param zModel
* the z model
* @return The function
*/
public static Gaussian2DFunction create2D(int nPeaks, int maxx, int maxy, int flags, AstimatismZModel zModel)
{
// Default to using the ERF functions if the user has not requested a simple Gaussian or angle fitting
if ((flags & (FIT_SIMPLE | FIT_ANGLE)) == 0)
{
if (nPeaks == 1)
{
if ((flags & FIT_BACKGROUND) == FIT_BACKGROUND)
{
// Independent X/Y width
if ((flags & FIT_Y_WIDTH) == FIT_Y_WIDTH)
return new SingleFreeCircularErfGaussian2DFunction(maxx, maxy);
// Combined X/Y width
if ((flags & FIT_X_WIDTH) == FIT_X_WIDTH)
return new SingleCircularErfGaussian2DFunction(maxx, maxy);
// Z-depth function
if ((flags & FIT_Z) == FIT_Z)
return new SingleAstigmatismErfGaussian2DFunction(maxx, maxy, zModel);
// Fixed width
if ((flags & FIT_SIGNAL) == FIT_SIGNAL)
return new SingleFixedErfGaussian2DFunction(maxx, maxy);
}
if ((flags & FIT_Y_WIDTH) == FIT_Y_WIDTH)
return new SingleNBFreeCircularErfGaussian2DFunction(maxx, maxy);
}
else
{
if ((flags & FIT_BACKGROUND) == FIT_BACKGROUND)
{
// Independent X/Y width
if ((flags & FIT_Y_WIDTH) == FIT_Y_WIDTH)
return new MultiFreeCircularErfGaussian2DFunction(nPeaks, maxx, maxy);
// Combined X/Y width
if ((flags & FIT_X_WIDTH) == FIT_X_WIDTH)
return new MultiCircularErfGaussian2DFunction(nPeaks, maxx, maxy);
// Z-depth function
if ((flags & FIT_Z) == FIT_Z)
return new MultiAstigmatismErfGaussian2DFunction(nPeaks, maxx, maxy, zModel);
// Fixed width
if ((flags & FIT_SIGNAL) == FIT_SIGNAL)
return new MultiFixedErfGaussian2DFunction(nPeaks, maxx, maxy);
}
if ((flags & FIT_Y_WIDTH) == FIT_Y_WIDTH)
return new MultiNBFreeCircularErfGaussian2DFunction(nPeaks, maxx, maxy);
}
}
// Legacy simple Gaussian functions
if (nPeaks == 1)
{
if ((flags & FIT_BACKGROUND) == FIT_BACKGROUND)
{
if ((flags & FIT_ANGLE) == FIT_ANGLE)
return new SingleEllipticalGaussian2DFunction(maxx, maxy);
if ((flags & FIT_Y_WIDTH) == FIT_Y_WIDTH)
return new SingleFreeCircularGaussian2DFunction(maxx, maxy);
if ((flags & FIT_X_WIDTH) == FIT_X_WIDTH)
return new SingleCircularGaussian2DFunction(maxx, maxy);
// Fixed function
if ((flags & FIT_SIGNAL) == FIT_SIGNAL)
return new SingleFixedGaussian2DFunction(maxx, maxy);
return new SingleNSFixedGaussian2DFunction(maxx, maxy);
}
if ((flags & FIT_ANGLE) == FIT_ANGLE)
return new SingleNBEllipticalGaussian2DFunction(maxx, maxy);
if ((flags & FIT_Y_WIDTH) == FIT_Y_WIDTH)
return new SingleNBFreeCircularGaussian2DFunction(maxx, maxy);
if ((flags & FIT_X_WIDTH) == FIT_X_WIDTH)
return new SingleNBCircularGaussian2DFunction(maxx, maxy);
// Fixed function
if ((flags & FIT_SIGNAL) == FIT_SIGNAL)
return new SingleNBFixedGaussian2DFunction(maxx, maxy);
return new SingleNSNBFixedGaussian2DFunction(maxx, maxy);
}
else
{
if ((flags & FIT_BACKGROUND) == FIT_BACKGROUND)
{
if ((flags & FIT_ANGLE) == FIT_ANGLE)
return new EllipticalGaussian2DFunction(nPeaks, maxx, maxy);
if ((flags & FIT_Y_WIDTH) == FIT_Y_WIDTH)
return new FreeCircularGaussian2DFunction(nPeaks, maxx, maxy);
if ((flags & FIT_X_WIDTH) == FIT_X_WIDTH)
return new CircularGaussian2DFunction(nPeaks, maxx, maxy);
// Fixed function
if ((flags & FIT_SIGNAL) == FIT_SIGNAL)
return new FixedGaussian2DFunction(nPeaks, maxx, maxy);
return new NSFixedGaussian2DFunction(nPeaks, maxx, maxy);
}
if ((flags & FIT_ANGLE) == FIT_ANGLE)
return new NBEllipticalGaussian2DFunction(nPeaks, maxx, maxy);
if ((flags & FIT_Y_WIDTH) == FIT_Y_WIDTH)
return new NBFreeCircularGaussian2DFunction(nPeaks, maxx, maxy);
if ((flags & FIT_X_WIDTH) == FIT_X_WIDTH)
return new NBCircularGaussian2DFunction(nPeaks, maxx, maxy);
// Fixed function
if ((flags & FIT_SIGNAL) == FIT_SIGNAL)
return new NBFixedGaussian2DFunction(nPeaks, maxx, maxy);
return new NSNBFixedGaussian2DFunction(nPeaks, maxx, maxy);
}
}
}