Source code for radiosim.utils.gauss

import numpy as np
from astropy.convolution import Gaussian2DKernel
from astropy.nddata.utils import Cutout2D
from scipy.stats import norm, skewnorm

__all__ = [
    "gauss",
    "skewed_gauss",
    "twodgaussian",
]


[docs] def gauss(params: list, size: int) -> np.ndarray: """ Returns a 2d gaussian distribution. Creates a gaussian in the center with twice the image size and then cuts out the correct position. Pro: Easy to understand and maintain Con: Slower than twodgaussian; maybe faster, if the cutout could be removed Parameters ---------- params: list [amplitude, center_x, center_y, width_x, width_y, rot] (rot (rotation) in radian) shape: int length of the image Returns ------- gaussian_scaled: 2darray gaussian distribution in two dimensions """ gaussian_2D_kernel = Gaussian2DKernel( x_stddev=params[3], y_stddev=params[4], theta=params[5], x_size=size * 2, y_size=size * 2, ) gaussian_cutout = Cutout2D( data=gaussian_2D_kernel, position=(size * 1.5 - params[1], size * 1.5 - params[2]), size=(size, size), ).data gaussian_scaled = gaussian_cutout / gaussian_cutout.max() * params[0] return gaussian_scaled
[docs] def twodgaussian(params: list, size: int) -> np.ndarray: r""" Returns a 2d gaussian function of the form: .. math:: x' &= \cos(rot) * x - \sin(rot) * y \\ y' &= \sin(rot) * x + \cos(rot) * y \\ g &= a * \exp(-(((x - \mathtt{center\_x})/ \mathtt{width\_x})^2 \\ &\phantom{=} + ((y - \mathtt{center\_y}) / \mathtt{width\_y})^2 ) / 2 ) - Pro: Faster than gauss - Con: More difficult to understand Parameters ---------- params: list [amplitude, center_x, center_y, width_x, width_y, rot] (rot (rotation) in radian) size: int length of the image Returns ------- rotgauss: array_like gaussian distribution in two dimensions Notes ----- Short version of ``twodgaussian``: https://github.com/keflavich/gaussfitter/blob/0891cd3605ab5ba000c2d5e1300dd21c15eee1fd/gaussfitter/gaussfitter.py#L75 """ amplitude = params[0] center_y, center_x = params[1], params[2] width_y, width_x = params[3], params[4] rot = params[5] rcen_x = center_x * np.cos(rot) - center_y * np.sin(rot) rcen_y = center_x * np.sin(rot) + center_y * np.cos(rot) def rotgauss(x, y): xp = x * np.cos(rot) - y * np.sin(rot) yp = x * np.sin(rot) + y * np.cos(rot) g = amplitude * np.exp( -(((rcen_x - xp) / width_x) ** 2 + ((rcen_y - yp) / width_y) ** 2) / 2.0 ) return g return rotgauss(*np.indices((size, size)))
[docs] def skewed_gauss( size: int, x: float, y: float, amp: float, width: float, length: float, a: float, ) -> np.ndarray: """ Generate a skewed 2d normal distribution. Parameters ---------- size: int length of the square image x: float x coordinate of the center y: float y coordinate of the center amp: float maximal amplitude of the distribution width: float width of the distribution (perpendicular to the skewed function) length: float length of the distribution a: float skewness parameter Returns ------- skew_gauss: array_like two dimensional skewed gaussian distribution """ def skewfunc(x: float, **args) -> np.ndarray: func = skewnorm.pdf(x, **args) func /= func.max() return func vals = np.arange(size) normal = norm.pdf(vals, loc=y, scale=width).reshape(-1, 1) normal /= normal.max() skew = skewfunc(vals, a=a, loc=x, scale=length) skew_gauss = normal * skew skew_gauss *= amp skew_gauss[np.isclose(skew_gauss, 0)] = 0 return skew_gauss