def setup(self): """ :return: :rtype: """ self.gaussian_kappa = GaussianKappa() self.gaussian_kappa_ellipse = GaussianEllipseKappa()
class TestGaussianKappa(object): """ test the Gaussian with Gaussian kappa """ def setup(self): self.gaussian_kappa = MultiGaussian_kappa() self.gaussian = Gaussian() self.g_kappa = GaussianKappa() def test_derivatives(self): x = np.linspace(0, 5, 10) y = np.linspace(0, 5, 10) amp = [1. * 2 * np.pi] center_x = 0. center_y = 0. sigma = [1.] f_x, f_y = self.gaussian_kappa.derivatives(x, y, amp, sigma, center_x, center_y) npt.assert_almost_equal(f_x[2], 0.63813558702212059, decimal=8) npt.assert_almost_equal(f_y[2], 0.63813558702212059, decimal=8) def test_hessian(self): x = np.linspace(0, 5, 10) y = np.linspace(0, 5, 10) amp = [1. * 2 * np.pi] center_x = 0. center_y = 0. sigma = [1.] f_xx, f_yy, f_xy = self.gaussian_kappa.hessian(x, y, amp, sigma, center_x, center_y) kappa = 1. / 2 * (f_xx + f_yy) kappa_true = self.gaussian.function(x, y, amp[0], sigma[0], sigma[0], center_x, center_y) print(kappa_true) print(kappa) npt.assert_almost_equal(kappa[0], kappa_true[0], decimal=5) npt.assert_almost_equal(kappa[1], kappa_true[1], decimal=5) def test_density_2d(self): x = np.linspace(0, 5, 10) y = np.linspace(0, 5, 10) amp = [1. * 2 * np.pi] center_x = 0. center_y = 0. sigma = [1.] f_xx, f_yy, f_xy = self.gaussian_kappa.hessian(x, y, amp, sigma, center_x, center_y) kappa = 1. / 2 * (f_xx + f_yy) amp_3d = self.g_kappa._amp2d_to_3d(amp, sigma[0], sigma[0]) density_2d = self.gaussian_kappa.density_2d(x, y, amp_3d, sigma, center_x, center_y) npt.assert_almost_equal(kappa[1], density_2d[1], decimal=5) npt.assert_almost_equal(kappa[2], density_2d[2], decimal=5) def test_density(self): amp = [1. * 2 * np.pi] sigma = [1.] density = self.gaussian_kappa.density(1., amp, sigma) npt.assert_almost_equal(density, 0.6065306597126334, decimal=8)
def __init__(self, use_scipy_wofz=True, min_ellipticity=1e-5): """ Setup which method to use the Faddeeva function and the ellipticity limit for spherical approximation. :param use_scipy_wofz: If ``True``, use ``scipy.special.wofz``. :type use_scipy_wofz: ``bool`` :param min_ellipticity: Minimum allowed ellipticity. For ``q > 1 - min_ellipticity``, values for spherical case will be returned. :type min_ellipticity: ``float`` """ if use_scipy_wofz: self.w_f = wofz else: self.w_f = self.w_f_approx self.min_ellipticity = min_ellipticity self.spherical = GaussianKappa()
class GaussianEllipseKappa(LensProfileBase): """ This class contains functions to evaluate the derivative and hessian matrix of the deflection potential for an elliptical Gaussian convergence. The formulae are from Shajib (2019). """ param_names = ['amp', 'sigma', 'e1', 'e2', 'center_x', 'center_y'] lower_limit_default = { 'amp': 0, 'sigma': 0, 'e1': -0.5, 'e2': -0.5, 'center_x': -100, 'center_y': -100 } upper_limit_default = { 'amp': 100, 'sigma': 100, 'e1': 0.5, 'e2': 0.5, 'center_x': 100, 'center_y': 100 } def __init__(self, use_scipy_wofz=True, min_ellipticity=1e-5): """ Setup which method to use the Faddeeva function and the ellipticity limit for spherical approximation. :param use_scipy_wofz: If ``True``, use ``scipy.special.wofz``. :type use_scipy_wofz: ``bool`` :param min_ellipticity: Minimum allowed ellipticity. For ``q > 1 - min_ellipticity``, values for spherical case will be returned. :type min_ellipticity: ``float`` """ if use_scipy_wofz: self.w_f = wofz else: self.w_f = self.w_f_approx self.min_ellipticity = min_ellipticity self.spherical = GaussianKappa() super(GaussianEllipseKappa, self).__init__() def function(self, x, y, amp, sigma, e1, e2, center_x=0, center_y=0): """ Compute the potential function for elliptical Gaussian convergence. :param x: x coordinate :type x: ``float`` or ``numpy.array`` :param y: y coordinate :type y: ``float`` or ``numpy.array`` :param amp: Amplitude of Gaussian, convention: :math:`A/(2 \pi\sigma^2) \exp(-(x^2+y^2/q^2)/2\sigma^2)` :type amp: ``float`` :param sigma: Standard deviation of Gaussian :type sigma: ``float`` :param e1: Ellipticity parameter 1 :type e1: ``float`` :param e2: Ellipticity parameter 2 :type e2: ``float`` :param center_x: x coordinate of centroid :type center_x: ``float`` :param center_y: y coordianate of centroid :type center_y: ``float`` :return: Potential for elliptical Gaussian convergence :rtype: ``float``, or ``numpy.array`` with shape equal to ``x.shape`` """ phi_g, q = param_util.ellipticity2phi_q(e1, e2) if q > 1 - self.min_ellipticity: return self.spherical.function(x, y, amp, sigma, center_x, center_y) # adjusting amplitude to make the notation compatible with the # formulae given in Shajib (2019). amp_ = amp / (2 * np.pi * sigma**2) # converting ellipticity definition from q*x^2 + y^2/q to q^2*x^2 + y^2 sigma_ = sigma * np.sqrt(q) # * q x_shift = x - center_x y_shift = y - center_y cos_phi = np.cos(phi_g) sin_phi = np.sin(phi_g) x_ = cos_phi * x_shift + sin_phi * y_shift y_ = -sin_phi * x_shift + cos_phi * y_shift _b = 1. / 2. / sigma_**2 _p = np.sqrt(_b * q**2 / (1. - q**2)) if isinstance(x_, int) or isinstance(x_, float): return self._num_integral(x_, y_, amp_, sigma_, _p, q) else: f_ = [] for i in range(len(x_)): f_.append(self._num_integral(x_[i], y_[i], amp_, sigma_, _p, q)) return np.array(f_) def _num_integral(self, x_, y_, amp_, sigma_, _p, q): """ :param x_: :param y_: :param _p: :param q: :return: """ def pot_real_line_integrand(_x): sig_func_re, sig_func_im = self.sigma_function(_p * _x, 0, q) alpha_x_ = amp_ * sigma_ * self.sgn(_x) * np.sqrt( 2 * np.pi / (1. - q**2)) * sig_func_re return alpha_x_ def pot_imag_line_integrand(_y): sig_func_re, sig_func_im = self.sigma_function(_p * x_, _p * _y, q) alpha_y_ = -amp_ * sigma_ * self.sgn(x_ + 1j * _y) * np.sqrt( 2 * np.pi / (1. - q**2)) * sig_func_im return alpha_y_ pot_on_real_line = quad(pot_real_line_integrand, 0, x_)[0] pot_on_imag_parallel = quad(pot_imag_line_integrand, 0, y_)[0] return (pot_on_real_line + pot_on_imag_parallel) def derivatives(self, x, y, amp, sigma, e1, e2, center_x=0, center_y=0): """ Compute the derivatives of function angles :math:`\partial f/\partial x`, :math:`\partial f/\partial y` at :math:`x,\ y`. :param x: x coordinate :type x: ``float`` or ``numpy.array`` :param y: y coordinate :type y: ``float`` or ``numpy.array`` :param amp: Amplitude of Gaussian, convention: :math:`A/(2 \pi\sigma^2) \exp(-(x^2+y^2/q^2)/2\sigma^2)` :type amp: ``float`` :param sigma: Standard deviation of Gaussian :type sigma: ``float`` :param e1: Ellipticity parameter 1 :type e1: ``float`` :param e2: Ellipticity parameter 2 :type e2: ``float`` :param center_x: x coordinate of centroid :type center_x: ``float`` :param center_y: y coordianate of centroid :type center_y: ``float`` :return: Deflection angle :math:`\partial f/\partial x`, :math:`\partial f/\partial y` for elliptical Gaussian convergence. :rtype: tuple ``(float, float)`` or ``(numpy.array, numpy.array)`` with each ``numpy.array``'s shape equal to ``x.shape``. """ phi_g, q = param_util.ellipticity2phi_q(e1, e2) if q > 1 - self.min_ellipticity: return self.spherical.derivatives(x, y, amp, sigma, center_x, center_y) # adjusting amplitude to make the notation compatible with the # formulae given in Shajib (2019). amp_ = amp / (2 * np.pi * sigma**2) # converting ellipticity definition from q*x^2 + y^2/q to q^2*x^2 + y^2 sigma_ = sigma * np.sqrt(q) # * q x_shift = x - center_x y_shift = y - center_y cos_phi = np.cos(phi_g) sin_phi = np.sin(phi_g) # rotated coordinates x_ = cos_phi * x_shift + sin_phi * y_shift y_ = -sin_phi * x_shift + cos_phi * y_shift _p = q / sigma_ / np.sqrt(2 * (1. - q**2)) sig_func_re, sig_func_im = self.sigma_function(_p * x_, _p * y_, q) alpha_x_ = amp_ * sigma_ * self.sgn(x_ + 1j * y_) * np.sqrt( 2 * np.pi / (1. - q**2)) * sig_func_re alpha_y_ = -amp_ * sigma_ * self.sgn(x_ + 1j * y_) * np.sqrt( 2 * np.pi / (1. - q**2)) * sig_func_im # rotate back to the original frame f_x = alpha_x_ * cos_phi - alpha_y_ * sin_phi f_y = alpha_x_ * sin_phi + alpha_y_ * cos_phi return f_x, f_y def hessian(self, x, y, amp, sigma, e1, e2, center_x=0, center_y=0): """ Compute Hessian matrix of function :math:`\partial^2f/\partial x^2`, :math:`\partial^2 f/\partial y^2`, :math:`\partial^2/\partial x\partial y`. :param x: x coordinate :type x: ``float`` or ``numpy.array`` :param y: y coordinate :type y: ``float`` or ``numpy.array`` :param amp: Amplitude of Gaussian, convention: :math:`A/(2 \pi\sigma^2) \exp(-(x^2+y^2/q^2)/2\sigma^2)` :type amp: ``float`` :param sigma: Standard deviation of Gaussian :type sigma: ``float`` :param e1: Ellipticity parameter 1 :type e1: ``float`` :param e2: Ellipticity parameter 2 :type e2: ``float`` :param center_x: x coordinate of centroid :type center_x: ``float`` :param center_y: y coordianate of centroid :type center_y: ``float`` :return: Hessian :math:`A/(2 \pi \sigma^2) \exp(-(x^2+y^2/q^2)/2\sigma^2)` for elliptical Gaussian convergence. :rtype: tuple ``(float, float, float)`` , or ``(numpy.array, numpy.array, numpy.array)`` with each ``numpy.array``'s shape equal to ``x.shape``. """ phi_g, q = param_util.ellipticity2phi_q(e1, e2) if q > 1 - self.min_ellipticity: return self.spherical.hessian(x, y, amp, sigma, center_x, center_y) # adjusting amplitude to make the notation compatible with the # formulae given in Shajib (2019). amp_ = amp / (2 * np.pi * sigma**2) # converting ellipticity definition from q*x^2 + y^2/q to q^2*x^2 + y^2 sigma_ = sigma * np.sqrt(q) # * q x_shift = x - center_x y_shift = y - center_y cos_phi = np.cos(phi_g) sin_phi = np.sin(phi_g) # rotated coordinates x_ = cos_phi * x_shift + sin_phi * y_shift y_ = -sin_phi * x_shift + cos_phi * y_shift _p = q / sigma_ / np.sqrt(2 * (1. - q**2)) sig_func_re, sig_func_im = self.sigma_function(_p * x_, _p * y_, q) kappa = amp_ * np.exp(-(q**2 * x_**2 + y_**2) / 2 / sigma_**2) shear = -1 / (1 - q * q) * ( (1 + q**2) * kappa - 2 * q * amp_ + np.sqrt(2 * np.pi) * q * q * amp_ * (x_ - 1j * y_) / sigma_ / np.sqrt(1 - q * q) * (sig_func_re - 1j * sig_func_im)) # in rotated frame f_xx_ = kappa + shear.real f_yy_ = kappa - shear.real f_xy_ = shear.imag # rotate back to the original frame f_xx = f_xx_ * cos_phi**2 + f_yy_ * sin_phi**2 \ - 2 * sin_phi * cos_phi * f_xy_ f_yy = f_xx_ * sin_phi**2 + f_yy_ * cos_phi**2 \ + 2 * sin_phi * cos_phi * f_xy_ f_xy = sin_phi * cos_phi * (f_xx_ - f_yy_) \ + (cos_phi**2 - sin_phi**2) * f_xy_ return f_xx, f_xy, f_xy, f_yy def density_2d(self, x, y, amp, sigma, e1, e2, center_x=0, center_y=0): """ Compute the density of elliptical Gaussian :math:`A/(2 \pi \sigma^2) \exp(-(x^2+y^2/q^2)/2\sigma^2)`. :param x: x coordinate. :type x: ``float`` or ``numpy.array`` :param y: y coordinate. :type y: ``float`` or ``numpy.array`` :param amp: Amplitude of Gaussian, convention: :math:`A/(2 \pi\sigma^2) \exp(-(x^2+y^2/q^2)/2\sigma^2)` :type amp: ``float`` :param sigma: Standard deviation of Gaussian. :type sigma: ``float`` :param e1: Ellipticity parameter 1. :type e1: ``float`` :param e2: Ellipticity parameter 2. :type e2: ``float`` :param center_x: x coordinate of centroid. :type center_x: ``float`` :param center_y: y coordianate of centroid. :type center_y: ``float`` :return: Density :math:`\kappa` for elliptical Gaussian convergence. :rtype: ``float``, or ``numpy.array`` with shape = ``x.shape``. """ f_xx, f_xy, f_yx, f_yy = self.hessian(x, y, amp, sigma, e1, e2, center_x, center_y) return (f_xx + f_yy) / 2 @staticmethod def sgn(z): """ Compute the sign function :math:`\mathrm{sgn}(z)` factor for deflection as sugggested by Bray (1984). For current implementation, returning 1 is sufficient. :param z: Complex variable :math:`z = x + \mathrm{i}y` :type z: ``complex`` :return: :math:`\mathrm{sgn}(z)` :rtype: ``float`` """ return 1. # np.sqrt(z*z)/z #np.sign(z.real*z.imag) #return np.sign(z.real) #if z.real != 0: # return np.sign(z.real) #else: # return np.sign(z.imag) #return np.where(z.real == 0, np.sign(z.real), np.sign(z.imag)) def sigma_function(self, x, y, q): r""" Compute the function :math:`\varsigma (z; q)` from equation (4.12) of Shajib (2019). :param x: Real part of complex variable, :math:`x = \mathrm{Re}(z)` :type x: ``float`` or ``numpy.array`` :param y: Imaginary part of complex variable, :math:`y = \mathrm{Im}(z)` :type y: ``float`` or ``numpy.array`` :param q: Axis ratio :type q: ``float`` :return: real and imaginary part of :math:`\varsigma(z; q)` function :rtype: tuple ``(type(x), type(x))`` """ y_sign = np.sign(y) y_ = deepcopy(y) * y_sign z = x + 1j * y_ zq = q * x + 1j * y_ / q w = self.w_f(z) wq = self.w_f(zq) # exponential factor in the 2nd term of eqn. (4.15) of Shajib (2019) exp_factor = np.exp(-x * x * (1 - q * q) - y_ * y_ * (1 / q / q - 1)) sigma_func_real = w.imag - exp_factor * wq.imag sigma_func_imag = (-w.real + exp_factor * wq.real) * y_sign return sigma_func_real, sigma_func_imag @staticmethod def w_f_approx(z): """ Compute the Faddeeva function :math:`w_{\mathrm F}(z)` using the approximation given in Zaghloul (2017). :param z: complex number :type z: ``complex`` or ``numpy.array(dtype=complex)`` :return: :math:`w_\mathrm{F}(z)` :rtype: ``complex`` """ sqrt_pi = 1 / np.sqrt(np.pi) i_sqrt_pi = 1j * sqrt_pi wz = np.empty_like(z) z_imag2 = z.imag**2 abs_z2 = z.real**2 + z_imag2 reg1 = (abs_z2 >= 38000.) if np.any(reg1): wz[reg1] = i_sqrt_pi / z[reg1] reg2 = (256. <= abs_z2) & (abs_z2 < 38000.) if np.any(reg2): t = z[reg2] wz[reg2] = i_sqrt_pi * t / (t * t - 0.5) reg3 = (62. <= abs_z2) & (abs_z2 < 256.) if np.any(reg3): t = z[reg3] wz[reg3] = (i_sqrt_pi / t) * (1 + 0.5 / (t * t - 1.5)) reg4 = (30. <= abs_z2) & (abs_z2 < 62.) & (z_imag2 >= 1e-13) if np.any(reg4): t = z[reg4] tt = t * t wz[reg4] = (i_sqrt_pi * t) * (tt - 2.5) / (tt * (tt - 3.) + 0.75) reg5 = (62. > abs_z2) & np.logical_not(reg4) & (abs_z2 > 2.5) & ( z_imag2 < 0.072) if np.any(reg5): t = z[reg5] u = -t * t f1 = sqrt_pi f2 = 1 s1 = [1.320522, 35.7668, 219.031, 1540.787, 3321.99, 36183.31] s2 = [ 1.841439, 61.57037, 364.2191, 2186.181, 9022.228, 24322.84, 32066.6 ] for s in s1: f1 = s - f1 * u for s in s2: f2 = s - f2 * u wz[reg5] = np.exp(u) + 1j * t * f1 / f2 reg6 = (30.0 > abs_z2) & np.logical_not(reg5) if np.any(reg6): t3 = -1j * z[reg6] f1 = sqrt_pi f2 = 1 s1 = [ 5.9126262, 30.180142, 93.15558, 181.92853, 214.38239, 122.60793 ] s2 = [ 10.479857, 53.992907, 170.35400, 348.70392, 457.33448, 352.73063, 122.60793 ] for s in s1: f1 = f1 * t3 + s for s in s2: f2 = f2 * t3 + s wz[reg6] = f1 / f2 return wz
def setup(self): self.gaussian_kappa = MultiGaussian_kappa() self.gaussian = Gaussian() self.g_kappa = GaussianKappa()
def setup(self): self.gaussian_kappa = GaussianKappa() self.ellipse = GaussianEllipsePotential()
def __init__(self): self.gaussian_kappa = GaussianKappa() super(MultiGaussianKappa, self).__init__()
def __init__(self): self.gaussian_kappa = GaussianKappa()
def __init__(self): self.spherical = GaussianKappa() self._diff = 0.000001 super(GaussianEllipsePotential, self).__init__()
def __init__(self): self.spherical = GaussianKappa() self._diff = 0.000001
def _import_class(lens_type, custom_class, kwargs_interp, z_lens=None, z_source=None): """ :param lens_type: string, lens model type :param custom_class: custom class :param z_lens: lens redshift # currently only used in NFW_MC model as this is redshift dependent :param z_source: source redshift # currently only used in NFW_MC model as this is redshift dependent :param kwargs_interp: interpolation keyword arguments specifying the numerics. See description in the Interpolate() class. Only applicable for 'INTERPOL' and 'INTERPOL_SCALED' models. :return: class instance of the lens model type """ if lens_type == 'SHIFT': from lenstronomy.LensModel.Profiles.constant_shift import Shift return Shift() elif lens_type == 'NIE_POTENTIAL': from lenstronomy.LensModel.Profiles.nie_potential import NIE_POTENTIAL return NIE_POTENTIAL() elif lens_type == 'CONST_MAG': from lenstronomy.LensModel.Profiles.const_mag import ConstMag return ConstMag() elif lens_type == 'SHEAR': from lenstronomy.LensModel.Profiles.shear import Shear return Shear() elif lens_type == 'SHEAR_GAMMA_PSI': from lenstronomy.LensModel.Profiles.shear import ShearGammaPsi return ShearGammaPsi() elif lens_type == 'SHEAR_REDUCED': from lenstronomy.LensModel.Profiles.shear import ShearReduced return ShearReduced() elif lens_type == 'CONVERGENCE': from lenstronomy.LensModel.Profiles.convergence import Convergence return Convergence() elif lens_type == 'HESSIAN': from lenstronomy.LensModel.Profiles.hessian import Hessian return Hessian() elif lens_type == 'FLEXION': from lenstronomy.LensModel.Profiles.flexion import Flexion return Flexion() elif lens_type == 'FLEXIONFG': from lenstronomy.LensModel.Profiles.flexionfg import Flexionfg return Flexionfg() elif lens_type == 'POINT_MASS': from lenstronomy.LensModel.Profiles.point_mass import PointMass return PointMass() elif lens_type == 'SIS': from lenstronomy.LensModel.Profiles.sis import SIS return SIS() elif lens_type == 'SIS_TRUNCATED': from lenstronomy.LensModel.Profiles.sis_truncate import SIS_truncate return SIS_truncate() elif lens_type == 'SIE': from lenstronomy.LensModel.Profiles.sie import SIE return SIE() elif lens_type == 'SPP': from lenstronomy.LensModel.Profiles.spp import SPP return SPP() elif lens_type == 'NIE': from lenstronomy.LensModel.Profiles.nie import NIE return NIE() elif lens_type == 'NIE_SIMPLE': from lenstronomy.LensModel.Profiles.nie import NIEMajorAxis return NIEMajorAxis() elif lens_type == 'CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import Chameleon return Chameleon() elif lens_type == 'DOUBLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import DoubleChameleon return DoubleChameleon() elif lens_type == 'TRIPLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import TripleChameleon return TripleChameleon() elif lens_type == 'SPEP': from lenstronomy.LensModel.Profiles.spep import SPEP return SPEP() elif lens_type == 'PEMD': from lenstronomy.LensModel.Profiles.pemd import PEMD return PEMD() elif lens_type == 'SPEMD': from lenstronomy.LensModel.Profiles.spemd import SPEMD return SPEMD() elif lens_type == 'EPL': from lenstronomy.LensModel.Profiles.epl import EPL return EPL() elif lens_type == 'EPL_NUMBA': from lenstronomy.LensModel.Profiles.epl_numba import EPL_numba return EPL_numba() elif lens_type == 'SPL_CORE': from lenstronomy.LensModel.Profiles.splcore import SPLCORE return SPLCORE() elif lens_type == 'NFW': from lenstronomy.LensModel.Profiles.nfw import NFW return NFW() elif lens_type == 'NFW_ELLIPSE': from lenstronomy.LensModel.Profiles.nfw_ellipse import NFW_ELLIPSE return NFW_ELLIPSE() elif lens_type == 'NFW_ELLIPSE_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import NFWEllipseGaussDec return NFWEllipseGaussDec() elif lens_type == 'NFW_ELLIPSE_CSE': from lenstronomy.LensModel.Profiles.nfw_ellipse_cse import NFW_ELLIPSE_CSE return NFW_ELLIPSE_CSE() elif lens_type == 'TNFW': from lenstronomy.LensModel.Profiles.tnfw import TNFW return TNFW() elif lens_type == 'TNFW_ELLIPSE': from lenstronomy.LensModel.Profiles.tnfw_ellipse import TNFW_ELLIPSE return TNFW_ELLIPSE() elif lens_type == 'CNFW': from lenstronomy.LensModel.Profiles.cnfw import CNFW return CNFW() elif lens_type == 'CNFW_ELLIPSE': from lenstronomy.LensModel.Profiles.cnfw_ellipse import CNFW_ELLIPSE return CNFW_ELLIPSE() elif lens_type == 'CTNFW_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import CTNFWGaussDec return CTNFWGaussDec() elif lens_type == 'NFW_MC': from lenstronomy.LensModel.Profiles.nfw_mass_concentration import NFWMC return NFWMC(z_lens=z_lens, z_source=z_source) elif lens_type == 'SERSIC': from lenstronomy.LensModel.Profiles.sersic import Sersic return Sersic() elif lens_type == 'SERSIC_ELLIPSE_POTENTIAL': from lenstronomy.LensModel.Profiles.sersic_ellipse_potential import SersicEllipse return SersicEllipse() elif lens_type == 'SERSIC_ELLIPSE_KAPPA': from lenstronomy.LensModel.Profiles.sersic_ellipse_kappa import SersicEllipseKappa return SersicEllipseKappa() elif lens_type == 'SERSIC_ELLIPSE_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import SersicEllipseGaussDec return SersicEllipseGaussDec() elif lens_type == 'PJAFFE': from lenstronomy.LensModel.Profiles.p_jaffe import PJaffe return PJaffe() elif lens_type == 'PJAFFE_ELLIPSE': from lenstronomy.LensModel.Profiles.p_jaffe_ellipse import PJaffe_Ellipse return PJaffe_Ellipse() elif lens_type == 'HERNQUIST': from lenstronomy.LensModel.Profiles.hernquist import Hernquist return Hernquist() elif lens_type == 'HERNQUIST_ELLIPSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse import Hernquist_Ellipse return Hernquist_Ellipse() elif lens_type == 'HERNQUIST_ELLIPSE_CSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse_cse import HernquistEllipseCSE return HernquistEllipseCSE() elif lens_type == 'GAUSSIAN': from lenstronomy.LensModel.Profiles.gaussian_potential import Gaussian return Gaussian() elif lens_type == 'GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_kappa import GaussianKappa return GaussianKappa() elif lens_type == 'GAUSSIAN_ELLIPSE_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_ellipse_kappa import GaussianEllipseKappa return GaussianEllipseKappa() elif lens_type == 'GAUSSIAN_ELLIPSE_POTENTIAL': from lenstronomy.LensModel.Profiles.gaussian_ellipse_potential import GaussianEllipsePotential return GaussianEllipsePotential() elif lens_type == 'MULTI_GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappa return MultiGaussianKappa() elif lens_type == 'MULTI_GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappaEllipse return MultiGaussianKappaEllipse() elif lens_type == 'INTERPOL': from lenstronomy.LensModel.Profiles.interpol import Interpol return Interpol(**kwargs_interp) elif lens_type == 'INTERPOL_SCALED': from lenstronomy.LensModel.Profiles.interpol import InterpolScaled return InterpolScaled(**kwargs_interp) elif lens_type == 'SHAPELETS_POLAR': from lenstronomy.LensModel.Profiles.shapelet_pot_polar import PolarShapelets return PolarShapelets() elif lens_type == 'SHAPELETS_CART': from lenstronomy.LensModel.Profiles.shapelet_pot_cartesian import CartShapelets return CartShapelets() elif lens_type == 'DIPOLE': from lenstronomy.LensModel.Profiles.dipole import Dipole return Dipole() elif lens_type == 'CURVED_ARC_CONST': from lenstronomy.LensModel.Profiles.curved_arc_const import CurvedArcConst return CurvedArcConst() elif lens_type == 'CURVED_ARC_CONST_MST': from lenstronomy.LensModel.Profiles.curved_arc_const import CurvedArcConstMST return CurvedArcConstMST() elif lens_type == 'CURVED_ARC_SPP': from lenstronomy.LensModel.Profiles.curved_arc_spp import CurvedArcSPP return CurvedArcSPP() elif lens_type == 'CURVED_ARC_SIS_MST': from lenstronomy.LensModel.Profiles.curved_arc_sis_mst import CurvedArcSISMST return CurvedArcSISMST() elif lens_type == 'CURVED_ARC_SPT': from lenstronomy.LensModel.Profiles.curved_arc_spt import CurvedArcSPT return CurvedArcSPT() elif lens_type == 'CURVED_ARC_TAN_DIFF': from lenstronomy.LensModel.Profiles.curved_arc_tan_diff import CurvedArcTanDiff return CurvedArcTanDiff() elif lens_type == 'ARC_PERT': from lenstronomy.LensModel.Profiles.arc_perturbations import ArcPerturbations return ArcPerturbations() elif lens_type == 'coreBURKERT': from lenstronomy.LensModel.Profiles.coreBurkert import CoreBurkert return CoreBurkert() elif lens_type == 'CORED_DENSITY': from lenstronomy.LensModel.Profiles.cored_density import CoredDensity return CoredDensity() elif lens_type == 'CORED_DENSITY_2': from lenstronomy.LensModel.Profiles.cored_density_2 import CoredDensity2 return CoredDensity2() elif lens_type == 'CORED_DENSITY_EXP': from lenstronomy.LensModel.Profiles.cored_density_exp import CoredDensityExp return CoredDensityExp() elif lens_type == 'CORED_DENSITY_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY') elif lens_type == 'CORED_DENSITY_2_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY_2') elif lens_type == 'CORED_DENSITY_EXP_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY_EXP') elif lens_type == 'NumericalAlpha': from lenstronomy.LensModel.Profiles.numerical_deflections import NumericalAlpha return NumericalAlpha(custom_class) elif lens_type == 'MULTIPOLE': from lenstronomy.LensModel.Profiles.multipole import Multipole return Multipole() elif lens_type == 'CSE': from lenstronomy.LensModel.Profiles.cored_steep_ellipsoid import CSE return CSE() elif lens_type == 'ElliSLICE': from lenstronomy.LensModel.Profiles.elliptical_density_slice import ElliSLICE return ElliSLICE() elif lens_type == 'ULDM': from lenstronomy.LensModel.Profiles.uldm import Uldm return Uldm() elif lens_type == 'CORED_DENSITY_ULDM_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY_ULDM') else: raise ValueError( '%s is not a valid lens model. Supported are: %s.' % (lens_type, _SUPPORTED_MODELS))
class TestGaussianEllipseKappa(object): """ This class tests the methods for elliptical Gaussian convergence. """ def setup(self): """ :return: :rtype: """ self.gaussian_kappa = GaussianKappa() self.gaussian_kappa_ellipse = GaussianEllipseKappa() def test_function(self): """ Test the `function()` method at the spherical limit. :return: :rtype: """ # almost spherical case x = 1. y = 1. e1, e2 = 5e-5, 0. sigma = 1. amp = 2. f_ = self.gaussian_kappa_ellipse.function(x, y, amp, sigma, e1, e2) r2 = x*x + y*y f_sphere = amp/(2.*np.pi*sigma**2) * sigma**2 * (np.euler_gamma - expi(-r2/2./sigma**2) + np.log(r2/2./sigma**2)) npt.assert_almost_equal(f_, f_sphere, decimal=4) # spherical case e1, e2 = 0., 0. f_ = self.gaussian_kappa_ellipse.function(x, y, amp, sigma, e1, e2) npt.assert_almost_equal(f_, f_sphere, decimal=4) def test_derivatives(self): """ Test the `derivatives()` method at the spherical limit. :return: :rtype: """ # almost spherical case x = 1. y = 1. e1, e2 = 5e-5, 0. sigma = 1. amp = 2. f_x, f_y = self.gaussian_kappa_ellipse.derivatives(x, y, amp, sigma, e1, e2) f_x_sphere, f_y_sphere = self.gaussian_kappa.derivatives(x, y, amp=amp, sigma=sigma) npt.assert_almost_equal(f_x, f_x_sphere, decimal=4) npt.assert_almost_equal(f_y, f_y_sphere, decimal=4) # spherical case e1, e2 = 0., 0. f_x, f_y = self.gaussian_kappa_ellipse.derivatives(x, y, amp, sigma, e1, e2) npt.assert_almost_equal(f_x, f_x_sphere, decimal=4) npt.assert_almost_equal(f_y, f_y_sphere, decimal=4) def test_hessian(self): """ Test the `hessian()` method at the spherical limit. :return: :rtype: """ # almost spherical case x = 1. y = 1. e1, e2 = 5e-5, 0. sigma = 1. amp = 2. f_xx, f_yy, f_xy = self.gaussian_kappa_ellipse.hessian(x, y, amp, sigma, e1, e2) f_xx_sphere, f_yy_sphere, f_xy_sphere = self.gaussian_kappa.hessian(x, y, amp=amp, sigma=sigma) npt.assert_almost_equal(f_xx, f_xx_sphere, decimal=4) npt.assert_almost_equal(f_yy, f_yy_sphere, decimal=4) npt.assert_almost_equal(f_xy, f_xy_sphere, decimal=4) # spherical case e1, e2 = 0., 0. f_xx, f_yy, f_xy = self.gaussian_kappa_ellipse.hessian(x, y, amp, sigma, e1, e2) npt.assert_almost_equal(f_xx, f_xx_sphere, decimal=4) npt.assert_almost_equal(f_yy, f_yy_sphere, decimal=4) npt.assert_almost_equal(f_xy, f_xy_sphere, decimal=4) def test_density_2d(self): """ Test the `density_2d()` method at the spherical limit. :return: :rtype: """ # almost spherical case x = 1. y = 1. e1, e2 = 5e-5, 0. sigma = 1. amp = 2. f_ = self.gaussian_kappa_ellipse.density_2d(x, y, amp, sigma, e1, e2) f_sphere = amp / (2.*np.pi*sigma**2) * np.exp(-(x*x+y*y)/2./sigma**2) npt.assert_almost_equal(f_, f_sphere, decimal=4) def test_w_f_approx(self): """ Test the `w_f_approx()` method with values computed using `scipy.special.wofz()`. :return: :rtype: """ x = np.logspace(-3., 3., 100) y = np.logspace(-3., 3., 100) X, Y = np.meshgrid(x, y) w_f_app = self.gaussian_kappa_ellipse.w_f_approx(X+1j*Y) w_f_scipy = wofz(X+1j*Y) npt.assert_allclose(w_f_app.real, w_f_scipy.real, rtol=4e-5, atol=0) npt.assert_allclose(w_f_app.imag, w_f_scipy.imag, rtol=4e-5, atol=0) # check `derivatives()` method with and without `scipy.special.wofz()` x = 1. y = 1. e1, e2 = 5e-5, 0 sigma = 1. amp = 2. # with `scipy.special.wofz()` gauss_scipy = GaussianEllipseKappa(use_scipy_wofz=True) f_x_sp, f_y_sp = gauss_scipy.derivatives(x, y, amp, sigma, e1, e2) # with `GaussEllipseKappa.w_f_approx()` gauss_approx = GaussianEllipseKappa(use_scipy_wofz=False) f_x_ap, f_y_ap = gauss_approx.derivatives(x, y, amp, sigma, e1, e2) npt.assert_almost_equal(f_x_sp, f_x_ap, decimal=4) npt.assert_almost_equal(f_y_sp, f_y_ap, decimal=4)
class MultiGaussian_kappa(object): """ """ def __init__(self): self.gaussian_kappa = GaussianKappa() def function(self, x, y, amp, sigma, center_x=0, center_y=0): """ :param x: :param y: :param amp: :param sigma: :param center_x: :param center_y: :return: """ f_ = np.zeros_like(x) for i in range(len(amp)): f_ += self.gaussian_kappa.function(x, y, amp=amp[i], sigma_x=sigma[i], sigma_y=sigma[i], center_x=center_x, center_y=center_y) return f_ def derivatives(self, x, y, amp, sigma, center_x=0, center_y=0): """ :param x: :param y: :param amp: :param sigma: :param center_x: :param center_y: :return: """ f_x, f_y = np.zeros_like(x), np.zeros_like(x) for i in range(len(amp)): f_x_i, f_y_i = self.gaussian_kappa.derivatives(x, y, amp=amp[i], sigma_x=sigma[i], sigma_y=sigma[i], center_x=center_x, center_y=center_y) f_x += f_x_i f_y += f_y_i return f_x, f_y def hessian(self, x, y, amp, sigma, center_x=0, center_y=0): """ :param x: :param y: :param amp: :param sigma: :param center_x: :param center_y: :return: """ f_xx, f_yy, f_xy = np.zeros_like(x), np.zeros_like(x), np.zeros_like(x) for i in range(len(amp)): f_xx_i, f_yy_i, f_xy_i = self.gaussian_kappa.hessian( x, y, amp=amp[i], sigma_x=sigma[i], sigma_y=sigma[i], center_x=center_x, center_y=center_y) f_xx += f_xx_i f_yy += f_yy_i f_xy += f_xy_i return f_xx, f_yy, f_xy def density(self, r, amp, sigma): """ :param r: :param amp: :param sigma: :return: """ d_ = np.zeros_like(r) for i in range(len(amp)): d_ += self.gaussian_kappa.density(r, amp[i], sigma[i], sigma[i]) return d_ def density_2d(self, x, y, amp, sigma, center_x=0, center_y=0): """ :param R: :param am: :param sigma_x: :param sigma_y: :return: """ d_3d = np.zeros_like(x) for i in range(len(amp)): d_3d += self.gaussian_kappa.density_2d(x, y, amp[i], sigma[i], sigma[i], center_x, center_y) return d_3d def mass_3d_lens(self, R, amp, sigma): """ :param R: :param amp: :param sigma: :return: """ mass_3d = np.zeros_like(R) for i in range(len(amp)): mass_3d += self.gaussian_kappa.mass_3d_lens( R, amp[i], sigma[i], sigma[i]) return mass_3d
def __init__(self, lens_model_list, **kwargs): """ :param lens_model_list: list of strings with lens model names :param foreground_shear: bool, when True, models a foreground non-linear shear distortion """ self.func_list = [] self._foreground_shear = False for i, lens_type in enumerate(lens_model_list): if lens_type == 'SHEAR': from lenstronomy.LensModel.Profiles.external_shear import ExternalShear self.func_list.append(ExternalShear()) elif lens_type == 'CONVERGENCE': from lenstronomy.LensModel.Profiles.mass_sheet import MassSheet self.func_list.append(MassSheet()) elif lens_type == 'FLEXION': from lenstronomy.LensModel.Profiles.flexion import Flexion self.func_list.append(Flexion()) elif lens_type == 'POINT_MASS': from lenstronomy.LensModel.Profiles.point_mass import PointMass self.func_list.append(PointMass()) elif lens_type == 'SIS': from lenstronomy.LensModel.Profiles.sis import SIS self.func_list.append(SIS()) elif lens_type == 'SIS_TRUNCATED': from lenstronomy.LensModel.Profiles.sis_truncate import SIS_truncate self.func_list.append(SIS_truncate()) elif lens_type == 'SIE': from lenstronomy.LensModel.Profiles.sie import SIE self.func_list.append(SIE()) elif lens_type == 'SPP': from lenstronomy.LensModel.Profiles.spp import SPP self.func_list.append(SPP()) elif lens_type == 'NIE': from lenstronomy.LensModel.Profiles.nie import NIE self.func_list.append(NIE()) elif lens_type == 'NIE_SIMPLE': from lenstronomy.LensModel.Profiles.nie import NIE_simple self.func_list.append(NIE_simple()) elif lens_type == 'CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import Chameleon self.func_list.append(Chameleon()) elif lens_type == 'DOUBLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import DoubleChameleon self.func_list.append(DoubleChameleon()) elif lens_type == 'SPEP': from lenstronomy.LensModel.Profiles.spep import SPEP self.func_list.append(SPEP()) elif lens_type == 'SPEMD': from lenstronomy.LensModel.Profiles.spemd import SPEMD self.func_list.append(SPEMD()) elif lens_type == 'SPEMD_SMOOTH': from lenstronomy.LensModel.Profiles.spemd_smooth import SPEMD_SMOOTH self.func_list.append(SPEMD_SMOOTH()) elif lens_type == 'NFW': from lenstronomy.LensModel.Profiles.nfw import NFW self.func_list.append(NFW(**kwargs)) elif lens_type == 'NFW_ELLIPSE': from lenstronomy.LensModel.Profiles.nfw_ellipse import NFW_ELLIPSE self.func_list.append( NFW_ELLIPSE(interpol=False, num_interp_X=1000, max_interp_X=100)) elif lens_type == 'TNFW': from lenstronomy.LensModel.Profiles.tnfw import TNFW self.func_list.append(TNFW()) elif lens_type == 'SERSIC': from lenstronomy.LensModel.Profiles.sersic import Sersic self.func_list.append(Sersic()) elif lens_type == 'SERSIC_ELLIPSE': from lenstronomy.LensModel.Profiles.sersic_ellipse import SersicEllipse self.func_list.append(SersicEllipse()) elif lens_type == 'PJAFFE': from lenstronomy.LensModel.Profiles.p_jaffe import PJaffe self.func_list.append(PJaffe()) elif lens_type == 'PJAFFE_ELLIPSE': from lenstronomy.LensModel.Profiles.p_jaffe_ellipse import PJaffe_Ellipse self.func_list.append(PJaffe_Ellipse()) elif lens_type == 'HERNQUIST': from lenstronomy.LensModel.Profiles.hernquist import Hernquist self.func_list.append(Hernquist()) elif lens_type == 'HERNQUIST_ELLIPSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse import Hernquist_Ellipse self.func_list.append(Hernquist_Ellipse()) elif lens_type == 'GAUSSIAN': from lenstronomy.LensModel.Profiles.gaussian_potential import Gaussian self.func_list.append(Gaussian()) elif lens_type == 'GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_kappa import GaussianKappa self.func_list.append(GaussianKappa()) elif lens_type == 'GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.gaussian_kappa_ellipse import GaussianKappaEllipse self.func_list.append(GaussianKappaEllipse()) elif lens_type == 'MULTI_GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappa self.func_list.append(MultiGaussianKappa()) elif lens_type == 'MULTI_GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappaEllipse self.func_list.append(MultiGaussianKappaEllipse()) elif lens_type == 'INTERPOL': from lenstronomy.LensModel.Profiles.interpol import Interpol_func self.func_list.append( Interpol_func(grid=False, min_grid_number=100)) elif lens_type == 'INTERPOL_SCALED': from lenstronomy.LensModel.Profiles.interpol import Interpol_func_scaled self.func_list.append( Interpol_func_scaled(grid=False, min_grid_number=100)) elif lens_type == 'SHAPELETS_POLAR': from lenstronomy.LensModel.Profiles.shapelet_pot_polar import PolarShapelets self.func_list.append(PolarShapelets()) elif lens_type == 'SHAPELETS_CART': from lenstronomy.LensModel.Profiles.shapelet_pot_cartesian import CartShapelets self.func_list.append(CartShapelets()) elif lens_type == 'DIPOLE': from lenstronomy.LensModel.Profiles.dipole import Dipole self.func_list.append(Dipole()) elif lens_type == 'FOREGROUND_SHEAR': from lenstronomy.LensModel.Profiles.external_shear import ExternalShear self.func_list.append(ExternalShear()) self._foreground_shear = True self._foreground_shear_idex = i else: raise ValueError('%s is not a valid lens model' % lens_type) self._model_list = lens_model_list
def _import_class(self, lens_type, i, custom_class): if lens_type == 'SHIFT': from lenstronomy.LensModel.Profiles.alpha_shift import Shift return Shift() elif lens_type == 'SHEAR': from lenstronomy.LensModel.Profiles.shear import Shear return Shear() elif lens_type == 'CONVERGENCE': from lenstronomy.LensModel.Profiles.convergence import Convergence return Convergence() elif lens_type == 'FLEXION': from lenstronomy.LensModel.Profiles.flexion import Flexion return Flexion() elif lens_type == 'POINT_MASS': from lenstronomy.LensModel.Profiles.point_mass import PointMass return PointMass() elif lens_type == 'SIS': from lenstronomy.LensModel.Profiles.sis import SIS return SIS() elif lens_type == 'SIS_TRUNCATED': from lenstronomy.LensModel.Profiles.sis_truncate import SIS_truncate return SIS_truncate() elif lens_type == 'SIE': from lenstronomy.LensModel.Profiles.sie import SIE return SIE() elif lens_type == 'SPP': from lenstronomy.LensModel.Profiles.spp import SPP return SPP() elif lens_type == 'NIE': from lenstronomy.LensModel.Profiles.nie import NIE return NIE() elif lens_type == 'NIE_SIMPLE': from lenstronomy.LensModel.Profiles.nie import NIE_simple return NIE_simple() elif lens_type == 'CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import Chameleon return Chameleon() elif lens_type == 'DOUBLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import DoubleChameleon return DoubleChameleon() elif lens_type == 'SPEP': from lenstronomy.LensModel.Profiles.spep import SPEP return SPEP() elif lens_type == 'SPEMD': from lenstronomy.LensModel.Profiles.spemd import SPEMD return SPEMD() elif lens_type == 'SPEMD_SMOOTH': from lenstronomy.LensModel.Profiles.spemd_smooth import SPEMD_SMOOTH return SPEMD_SMOOTH() elif lens_type == 'NFW': from lenstronomy.LensModel.Profiles.nfw import NFW return NFW() elif lens_type == 'NFW_ELLIPSE': from lenstronomy.LensModel.Profiles.nfw_ellipse import NFW_ELLIPSE return NFW_ELLIPSE() elif lens_type == 'TNFW': from lenstronomy.LensModel.Profiles.tnfw import TNFW return TNFW() elif lens_type == 'CNFW': from lenstronomy.LensModel.Profiles.cnfw import CNFW return CNFW() elif lens_type == 'SERSIC': from lenstronomy.LensModel.Profiles.sersic import Sersic return Sersic() elif lens_type == 'SERSIC_ELLIPSE': from lenstronomy.LensModel.Profiles.sersic_ellipse import SersicEllipse return SersicEllipse() elif lens_type == 'PJAFFE': from lenstronomy.LensModel.Profiles.p_jaffe import PJaffe return PJaffe() elif lens_type == 'PJAFFE_ELLIPSE': from lenstronomy.LensModel.Profiles.p_jaffe_ellipse import PJaffe_Ellipse return PJaffe_Ellipse() elif lens_type == 'HERNQUIST': from lenstronomy.LensModel.Profiles.hernquist import Hernquist return Hernquist() elif lens_type == 'HERNQUIST_ELLIPSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse import Hernquist_Ellipse return Hernquist_Ellipse() elif lens_type == 'GAUSSIAN': from lenstronomy.LensModel.Profiles.gaussian_potential import Gaussian return Gaussian() elif lens_type == 'GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_kappa import GaussianKappa return GaussianKappa() elif lens_type == 'GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.gaussian_kappa_ellipse import GaussianKappaEllipse return GaussianKappaEllipse() elif lens_type == 'MULTI_GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappa return MultiGaussianKappa() elif lens_type == 'MULTI_GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappaEllipse return MultiGaussianKappaEllipse() elif lens_type == 'INTERPOL': from lenstronomy.LensModel.Profiles.interpol import Interpol return Interpol(grid=False, min_grid_number=100) elif lens_type == 'INTERPOL_SCALED': from lenstronomy.LensModel.Profiles.interpol import InterpolScaled return InterpolScaled() elif lens_type == 'SHAPELETS_POLAR': from lenstronomy.LensModel.Profiles.shapelet_pot_polar import PolarShapelets return PolarShapelets() elif lens_type == 'SHAPELETS_CART': from lenstronomy.LensModel.Profiles.shapelet_pot_cartesian import CartShapelets return CartShapelets() elif lens_type == 'DIPOLE': from lenstronomy.LensModel.Profiles.dipole import Dipole return Dipole() elif lens_type == 'FOREGROUND_SHEAR': from lenstronomy.LensModel.Profiles.shear import Shear self._foreground_shear = True self._foreground_shear_idex = i return Shear() elif lens_type == 'coreBURKERT': from lenstronomy.LensModel.Profiles.coreBurkert import coreBurkert return coreBurkert() elif lens_type == 'NumericalAlpha': from lenstronomy.LensModel.Profiles.numerical_deflections import NumericalAlpha return NumericalAlpha(custom_class[i]) else: raise ValueError('%s is not a valid lens model' % lens_type)
class GaussianEllipsePotential(LensProfileBase): """ this class contains functions to evaluate a Gaussian function and calculates its derivative and hessian matrix with ellipticity in the convergence the calculation follows Glenn van de Ven et al. 2009 """ param_names = ['amp', 'sigma', 'e1', 'e2', 'center_x', 'center_y'] lower_limit_default = { 'amp': 0, 'sigma': 0, 'e1': -0.5, 'e2': -0.5, 'center_x': -100, 'center_y': -100 } upper_limit_default = { 'amp': 100, 'sigma': 100, 'e1': 0.5, 'e2': 0.5, 'center_x': 100, 'center_y': 100 } def __init__(self): self.spherical = GaussianKappa() self._diff = 0.000001 super(GaussianEllipsePotential, self).__init__() def function(self, x, y, amp, sigma, e1, e2, center_x=0, center_y=0): """ returns Gaussian """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) x_shift = x - center_x y_shift = y - center_y cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) e = abs(1 - q) x_ = (cos_phi * x_shift + sin_phi * y_shift) * np.sqrt(1 - e) y_ = (-sin_phi * x_shift + cos_phi * y_shift) * np.sqrt(1 + e) f_ = self.spherical.function(x_, y_, amp=amp, sigma=sigma) return f_ def derivatives(self, x, y, amp, sigma, e1, e2, center_x=0, center_y=0): """ returns df/dx and df/dy of the function """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) x_shift = x - center_x y_shift = y - center_y cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) e = abs(1 - q) x_ = (cos_phi * x_shift + sin_phi * y_shift) * np.sqrt(1 - e) y_ = (-sin_phi * x_shift + cos_phi * y_shift) * np.sqrt(1 + e) f_x_prim, f_y_prim = self.spherical.derivatives(x_, y_, amp=amp, sigma=sigma) f_x_prim *= np.sqrt(1 - e) f_y_prim *= np.sqrt(1 + e) f_x = cos_phi * f_x_prim - sin_phi * f_y_prim f_y = sin_phi * f_x_prim + cos_phi * f_y_prim return f_x, f_y def hessian(self, x, y, amp, sigma, e1, e2, center_x=0, center_y=0): """ returns Hessian matrix of function d^2f/dx^2, d^2/dxdy, d^2/dydx, d^f/dy^2 """ alpha_ra, alpha_dec = self.derivatives(x, y, amp, sigma, e1, e2, center_x, center_y) diff = self._diff alpha_ra_dx, alpha_dec_dx = self.derivatives(x + diff, y, amp, sigma, e1, e2, center_x, center_y) alpha_ra_dy, alpha_dec_dy = self.derivatives(x, y + diff, amp, sigma, e1, e2, center_x, center_y) f_xx = (alpha_ra_dx - alpha_ra) / diff f_xy = (alpha_ra_dy - alpha_ra) / diff f_yx = (alpha_dec_dx - alpha_dec) / diff f_yy = (alpha_dec_dy - alpha_dec) / diff return f_xx, f_xy, f_yx, f_yy def density(self, r, amp, sigma, e1, e2): """ :param r: :param amp: :param sigma: :return: """ return self.spherical.density(r, amp, sigma) def density_2d(self, x, y, amp, sigma, e1, e2, center_x=0, center_y=0): """ :param R: :param am: :param sigma_x: :param sigma_y: :return: """ return self.spherical.density_2d(x, y, amp, sigma, center_x, center_y) def mass_2d(self, R, amp, sigma, e1, e2): """ :param R: :param amp: :param sigma_x: :param sigma_y: :return: """ return self.spherical.mass_2d(R, amp, sigma) def mass_3d(self, R, amp, sigma, e1, e2): """ :param R: :param amp: :param sigma: :param e1: :param e2: :return: """ return self.spherical.mass_3d(R, amp, sigma) def mass_3d_lens(self, R, amp, sigma, e1, e2): """ :param R: :param amp: :param sigma: :param e1: :param e2: :return: """ return self.spherical.mass_3d_lens(R, amp, sigma) def mass_2d_lens(self, R, amp, sigma, e1, e2): """ :param R: :param amp: :param sigma_x: :param sigma_y: :return: """ return self.spherical.mass_2d_lens(R, amp, sigma)
def setup(self): self.gaussian_kappa = GaussianKappa() self.ellipse = GaussianKappaEllipse()
def _import_class(lens_type, custom_class, z_lens=None, z_source=None): """ :param lens_type: string, lens model type :param custom_class: custom class :param z_lens: lens redshift # currently only used in NFW_MC model as this is redshift dependent :param z_source: source redshift # currently only used in NFW_MC model as this is redshift dependent :return: class instance of the lens model type """ if lens_type == 'SHIFT': from lenstronomy.LensModel.Profiles.alpha_shift import Shift return Shift() elif lens_type == 'SHEAR': from lenstronomy.LensModel.Profiles.shear import Shear return Shear() elif lens_type == 'SHEAR_GAMMA_PSI': from lenstronomy.LensModel.Profiles.shear import ShearGammaPsi return ShearGammaPsi() elif lens_type == 'CONVERGENCE': from lenstronomy.LensModel.Profiles.convergence import Convergence return Convergence() elif lens_type == 'FLEXION': from lenstronomy.LensModel.Profiles.flexion import Flexion return Flexion() elif lens_type == 'FLEXIONFG': from lenstronomy.LensModel.Profiles.flexionfg import Flexionfg return Flexionfg() elif lens_type == 'POINT_MASS': from lenstronomy.LensModel.Profiles.point_mass import PointMass return PointMass() elif lens_type == 'SIS': from lenstronomy.LensModel.Profiles.sis import SIS return SIS() elif lens_type == 'SIS_TRUNCATED': from lenstronomy.LensModel.Profiles.sis_truncate import SIS_truncate return SIS_truncate() elif lens_type == 'SIE': from lenstronomy.LensModel.Profiles.sie import SIE return SIE() elif lens_type == 'SPP': from lenstronomy.LensModel.Profiles.spp import SPP return SPP() elif lens_type == 'NIE': from lenstronomy.LensModel.Profiles.nie import NIE return NIE() elif lens_type == 'NIE_SIMPLE': from lenstronomy.LensModel.Profiles.nie import NIEMajorAxis return NIEMajorAxis() elif lens_type == 'CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import Chameleon return Chameleon() elif lens_type == 'DOUBLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import DoubleChameleon return DoubleChameleon() elif lens_type == 'TRIPLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import TripleChameleon return TripleChameleon() elif lens_type == 'SPEP': from lenstronomy.LensModel.Profiles.spep import SPEP return SPEP() elif lens_type == 'SPEMD': from lenstronomy.LensModel.Profiles.spemd import SPEMD return SPEMD() elif lens_type == 'SPEMD_SMOOTH': from lenstronomy.LensModel.Profiles.spemd_smooth import SPEMD_SMOOTH return SPEMD_SMOOTH() elif lens_type == 'NFW': from lenstronomy.LensModel.Profiles.nfw import NFW return NFW() elif lens_type == 'NFW_ELLIPSE': from lenstronomy.LensModel.Profiles.nfw_ellipse import NFW_ELLIPSE return NFW_ELLIPSE() elif lens_type == 'NFW_ELLIPSE_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import NFWEllipseGaussDec return NFWEllipseGaussDec() elif lens_type == 'TNFW': from lenstronomy.LensModel.Profiles.tnfw import TNFW return TNFW() elif lens_type == 'CNFW': from lenstronomy.LensModel.Profiles.cnfw import CNFW return CNFW() elif lens_type == 'CNFW_ELLIPSE': from lenstronomy.LensModel.Profiles.cnfw_ellipse import CNFW_ELLIPSE return CNFW_ELLIPSE() elif lens_type == 'CTNFW_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import CTNFWGaussDec return CTNFWGaussDec() elif lens_type == 'NFW_MC': from lenstronomy.LensModel.Profiles.nfw_mass_concentration import NFWMC return NFWMC(z_lens=z_lens, z_source=z_source) elif lens_type == 'SERSIC': from lenstronomy.LensModel.Profiles.sersic import Sersic return Sersic() elif lens_type == 'SERSIC_ELLIPSE_POTENTIAL': from lenstronomy.LensModel.Profiles.sersic_ellipse_potential import SersicEllipse return SersicEllipse() elif lens_type == 'SERSIC_ELLIPSE_KAPPA': from lenstronomy.LensModel.Profiles.sersic_ellipse_kappa import SersicEllipseKappa return SersicEllipseKappa() elif lens_type == 'SERSIC_ELLIPSE_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition \ import SersicEllipseGaussDec return SersicEllipseGaussDec() elif lens_type == 'PJAFFE': from lenstronomy.LensModel.Profiles.p_jaffe import PJaffe return PJaffe() elif lens_type == 'PJAFFE_ELLIPSE': from lenstronomy.LensModel.Profiles.p_jaffe_ellipse import PJaffe_Ellipse return PJaffe_Ellipse() elif lens_type == 'HERNQUIST': from lenstronomy.LensModel.Profiles.hernquist import Hernquist return Hernquist() elif lens_type == 'HERNQUIST_ELLIPSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse import Hernquist_Ellipse return Hernquist_Ellipse() elif lens_type == 'GAUSSIAN': from lenstronomy.LensModel.Profiles.gaussian_potential import Gaussian return Gaussian() elif lens_type == 'GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_kappa import GaussianKappa return GaussianKappa() elif lens_type == 'GAUSSIAN_ELLIPSE_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_ellipse_kappa import GaussianEllipseKappa return GaussianEllipseKappa() elif lens_type == 'GAUSSIAN_ELLIPSE_POTENTIAL': from lenstronomy.LensModel.Profiles.gaussian_ellipse_potential import GaussianEllipsePotential return GaussianEllipsePotential() elif lens_type == 'MULTI_GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappa return MultiGaussianKappa() elif lens_type == 'MULTI_GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappaEllipse return MultiGaussianKappaEllipse() elif lens_type == 'INTERPOL': from lenstronomy.LensModel.Profiles.interpol import Interpol return Interpol() elif lens_type == 'INTERPOL_SCALED': from lenstronomy.LensModel.Profiles.interpol import InterpolScaled return InterpolScaled() elif lens_type == 'SHAPELETS_POLAR': from lenstronomy.LensModel.Profiles.shapelet_pot_polar import PolarShapelets return PolarShapelets() elif lens_type == 'SHAPELETS_CART': from lenstronomy.LensModel.Profiles.shapelet_pot_cartesian import CartShapelets return CartShapelets() elif lens_type == 'DIPOLE': from lenstronomy.LensModel.Profiles.dipole import Dipole return Dipole() elif lens_type == 'CURVED_ARC': from lenstronomy.LensModel.Profiles.curved_arc import CurvedArc return CurvedArc() elif lens_type == 'ARC_PERT': from lenstronomy.LensModel.Profiles.arc_perturbations import ArcPerturbations return ArcPerturbations() elif lens_type == 'coreBURKERT': from lenstronomy.LensModel.Profiles.coreBurkert import CoreBurkert return CoreBurkert() elif lens_type == 'CORED_DENSITY': from lenstronomy.LensModel.Profiles.cored_density import CoredDensity return CoredDensity() elif lens_type == 'CORED_DENSITY_2': from lenstronomy.LensModel.Profiles.cored_density_2 import CoredDensity2 return CoredDensity2() elif lens_type == 'CORED_DENSITY_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY') elif lens_type == 'CORED_DENSITY_2_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY_2') elif lens_type == 'NumericalAlpha': from lenstronomy.LensModel.Profiles.numerical_deflections import NumericalAlpha return NumericalAlpha(custom_class) else: raise ValueError('%s is not a valid lens model' % lens_type)
class TestGaussianKappaPot(object): """ test the Gaussian with Gaussian kappa """ def setup(self): self.gaussian_kappa = GaussianKappa() self.ellipse = GaussianEllipsePotential() def test_function(self): x = 1 y = 1 e1, e2 = 0, 0 sigma = 1 amp = 1 f_ = self.ellipse.function(x, y, amp, sigma, e1, e2) f_sphere = self.gaussian_kappa.function(x, y, amp=amp, sigma=sigma) npt.assert_almost_equal(f_, f_sphere, decimal=8) def test_derivatives(self): x = 1 y = 1 e1, e2 = 0, 0 sigma = 1 amp = 1 f_x, f_y = self.ellipse.derivatives(x, y, amp, sigma, e1, e2) f_x_sphere, f_y_sphere = self.gaussian_kappa.derivatives(x, y, amp=amp, sigma=sigma) npt.assert_almost_equal(f_x, f_x_sphere, decimal=8) npt.assert_almost_equal(f_y, f_y_sphere, decimal=8) def test_hessian(self): x = 1 y = 1 e1, e2 = 0, 0 sigma = 1 amp = 1 f_xx, f_xy, f_yx, f_yy = self.ellipse.hessian(x, y, amp, sigma, e1, e2) f_xx_sphere, f_xy_sphere, f_yx_sphere, f_yy_sphere = self.gaussian_kappa.hessian(x, y, amp=amp, sigma=sigma) npt.assert_almost_equal(f_xx, f_xx_sphere, decimal=5) npt.assert_almost_equal(f_yy, f_yy_sphere, decimal=5) npt.assert_almost_equal(f_xy, f_xy_sphere, decimal=5) npt.assert_almost_equal(f_xy, f_yx, decimal=8) def test_density_2d(self): x = 1 y = 1 e1, e2 = 0, 0 sigma = 1 amp = 1 f_ = self.ellipse.density_2d(x, y, amp, sigma, e1, e2) f_sphere = self.gaussian_kappa.density_2d(x, y, amp=amp, sigma=sigma) npt.assert_almost_equal(f_, f_sphere, decimal=8) def test_mass_2d(self): r = 1 e1, e2 = 0, 0 sigma = 1 amp = 1 f_ = self.ellipse.mass_2d(r, amp, sigma, e1, e2) f_sphere = self.gaussian_kappa.mass_2d(r, amp=amp, sigma=sigma) npt.assert_almost_equal(f_, f_sphere, decimal=8) def test_mass_2d_lens(self): r = 1 e1, e2 = 0, 0 sigma = 1 amp = 1 f_ = self.ellipse.mass_2d_lens(r, amp, sigma, e1, e2) f_sphere = self.gaussian_kappa.mass_2d_lens(r, amp=amp, sigma=sigma) npt.assert_almost_equal(f_, f_sphere, decimal=8)
class MultiGaussianKappa(object): """ """ param_names = ['amp', 'sigma', 'center_x', 'center_y'] lower_limit_default = { 'amp': 0, 'sigma': 0, 'center_x': -100, 'center_y': -100 } upper_limit_default = { 'amp': 100, 'sigma': 100, 'center_x': 100, 'center_y': 100 } def __init__(self): self.gaussian_kappa = GaussianKappa() def function(self, x, y, amp, sigma, center_x=0, center_y=0, scale_factor=1): """ :param x: :param y: :param amp: :param sigma: :param center_x: :param center_y: :return: """ f_ = np.zeros_like(x, dtype=float) for i in range(len(amp)): f_ += self.gaussian_kappa.function(x, y, amp=scale_factor * amp[i], sigma=sigma[i], center_x=center_x, center_y=center_y) return f_ def derivatives(self, x, y, amp, sigma, center_x=0, center_y=0, scale_factor=1): """ :param x: :param y: :param amp: :param sigma: :param center_x: :param center_y: :return: """ f_x, f_y = np.zeros_like(x, dtype=float), np.zeros_like(x, dtype=float) for i in range(len(amp)): f_x_i, f_y_i = self.gaussian_kappa.derivatives(x, y, amp=scale_factor * amp[i], sigma=sigma[i], center_x=center_x, center_y=center_y) f_x += f_x_i f_y += f_y_i return f_x, f_y def hessian(self, x, y, amp, sigma, center_x=0, center_y=0, scale_factor=1): """ :param x: :param y: :param amp: :param sigma: :param center_x: :param center_y: :return: """ f_xx, f_yy, f_xy = np.zeros_like(x, dtype=float), np.zeros_like( x, dtype=float), np.zeros_like(x, dtype=float) for i in range(len(amp)): f_xx_i, f_yy_i, f_xy_i = self.gaussian_kappa.hessian( x, y, amp=scale_factor * amp[i], sigma=sigma[i], center_x=center_x, center_y=center_y) f_xx += f_xx_i f_yy += f_yy_i f_xy += f_xy_i return f_xx, f_yy, f_xy def density(self, r, amp, sigma, scale_factor=1): """ :param r: :param amp: :param sigma: :return: """ d_ = np.zeros_like(r, dtype=float) for i in range(len(amp)): d_ += self.gaussian_kappa.density(r, scale_factor * amp[i], sigma[i]) return d_ def density_2d(self, x, y, amp, sigma, center_x=0, center_y=0, scale_factor=1): """ :param R: :param am: :param sigma_x: :param sigma_y: :return: """ d_3d = np.zeros_like(x, dtype=float) for i in range(len(amp)): d_3d += self.gaussian_kappa.density_2d(x, y, scale_factor * amp[i], sigma[i], center_x, center_y) return d_3d def mass_3d_lens(self, R, amp, sigma, scale_factor=1): """ :param R: :param amp: :param sigma: :return: """ mass_3d = np.zeros_like(R, dtype=float) for i in range(len(amp)): mass_3d += self.gaussian_kappa.mass_3d_lens( R, scale_factor * amp[i], sigma[i]) return mass_3d
class TestGaussianKappa(object): """ test the Gaussian with Gaussian kappa """ def setup(self): self.gaussian_kappa = GaussianKappa() self.gaussian = Gaussian() def test_derivatives(self): x = np.linspace(0, 5, 10) y = np.linspace(0, 5, 10) amp = 1. * 2 * np.pi center_x = 0. center_y = 0. sigma_x = 1. sigma_y = 1. f_x, f_y = self.gaussian_kappa.derivatives(x, y, amp, sigma_x, sigma_y, center_x, center_y) npt.assert_almost_equal(f_x[2], 0.63813558702212059, decimal=8) npt.assert_almost_equal(f_y[2], 0.63813558702212059, decimal=8) def test_hessian(self): x = np.linspace(0, 5, 10) y = np.linspace(0, 5, 10) amp = 1. * 2 * np.pi center_x = 0. center_y = 0. sigma_x = 1. sigma_y = 1. f_xx, f_yy, f_xy = self.gaussian_kappa.hessian(x, y, amp, sigma_x, sigma_y, center_x, center_y) kappa = 1. / 2 * (f_xx + f_yy) kappa_true = self.gaussian.function(x, y, amp, sigma_x, sigma_y, center_x, center_y) print(kappa_true) print(kappa) npt.assert_almost_equal(kappa[0], kappa_true[0], decimal=5) npt.assert_almost_equal(kappa[1], kappa_true[1], decimal=5) def test_density_2d(self): x = np.linspace(0, 5, 10) y = np.linspace(0, 5, 10) amp = 1. * 2 * np.pi center_x = 0. center_y = 0. sigma_x = 1. sigma_y = 1. f_xx, f_yy, f_xy = self.gaussian_kappa.hessian(x, y, amp, sigma_x, sigma_y, center_x, center_y) kappa = 1. / 2 * (f_xx + f_yy) amp_3d = self.gaussian_kappa._amp2d_to_3d(amp, sigma_x, sigma_y) density_2d = self.gaussian_kappa.density_2d(x, y, amp_3d, sigma_x, sigma_y, center_x, center_y) npt.assert_almost_equal(kappa[1], density_2d[1], decimal=5) npt.assert_almost_equal(kappa[2], density_2d[2], decimal=5) def test_3d_2d_convention(self): x = np.linspace(0, 5, 10) y = np.linspace(0, 5, 10) amp = 1. * 2 * np.pi center_x = 0. center_y = 0. sigma_x = 1. sigma_y = 1. amp_3d = self.gaussian_kappa._amp2d_to_3d(amp, sigma_x, sigma_y) density_2d_gauss = self.gaussian_kappa.density_2d( x, y, amp_3d, sigma_x, sigma_y, center_x, center_y) density_2d = self.gaussian.function(x, y, amp, sigma_x, sigma_y, center_x, center_y) npt.assert_almost_equal(density_2d_gauss[1], density_2d[1], decimal=5)