Beispiel #1
0
    def __init__(self, suppress_fastell=False):
        """

        :param suppress_fastell: bool, if True, does not raise if fastell4py is not installed
        """
        self._s_scale = 0.0000001  # smoothing scale as used to numerically compute a power-law profile
        self.spp = SPP()
        self.spemd_smooth = SPEMD(suppress_fastell=suppress_fastell)
        super(PEMD, self).__init__()
Beispiel #2
0
class SPEMD(object):
    """
    class for smooth power law ellipse mass density profile
    """
    param_names = ['theta_E', 'gamma', 'e1', 'e2', 'center_x', 'center_y']
    lower_limit_default = {'theta_E': 0, 'gamma': 0, 'e1': -0.5, 'e2': -0.5, 'center_x': -100, 'center_y': -100}
    upper_limit_default = {'theta_E': 100, 'gamma': 100, 'e1': 0.5, 'e2': 0.5, 'center_x': 100, 'center_y': 100}

    def __init__(self):
        self.s2 = 0.00000001
        self.spp = SPP()
        self.spemd_smooth = SPEMD_SMOOTH()

    def function(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        return self.spemd_smooth.function(x, y, theta_E, gamma, e1, e2, self.s2, center_x, center_y)

    def derivatives(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        return self.spemd_smooth.derivatives(x, y, theta_E, gamma, e1, e2, self.s2, center_x, center_y)

    def hessian(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        return self.spemd_smooth.hessian(x, y, theta_E, gamma, e1, e2, self.s2, center_x, center_y)

    def mass_3d_lens(self, r, theta_E, gamma, e1, e2):
        """
        computes the spherical power-law mass enclosed (with SPP routiune)
        :param r:
        :param theta_E:
        :param gamma:
        :param q:
        :param phi_G:
        :return:
        """
        return self.spp.mass_3d_lens(r, theta_E, gamma)
Beispiel #3
0
    def __init__(self,
                 kwargs_cosmo,
                 interpol_grid_num=100,
                 log_integration=False,
                 max_integrate=100,
                 min_integrate=0.001):
        """

        :param kwargs_cosmo: keyword argument with angular diameter distances
        """

        self._interp_grid_num = interpol_grid_num
        self._log_int = log_integration
        self._max_integrate = max_integrate  # maximal integration (and interpolation) in units of arcsecs
        self._min_integrate = min_integrate  # min integration (and interpolation) in units of arcsecs
        self._max_interpolate = max_integrate  # we chose to set the interpolation range to the integration range
        self._min_interpolate = min_integrate  # we chose to set the interpolation range to the integration range

        self._cosmo = Cosmo(**kwargs_cosmo)
        self._spp = SPP()
        Anisotropy.__init__(self, anisotropy_type='OM')
Beispiel #4
0
    def test_function(self):
        """

        :return:
        """
        profile = PowerLaw()
        spp = SPP()
        sis = SIS()
        x = np.linspace(0.1, 10, 10)
        kwargs_light = {'amp': 1., 'gamma': 2, 'e1': 0, 'e2': 0}
        kwargs_spp = {'theta_E': 1., 'gamma': 2}
        kwargs_sis = {'theta_E': 1.}
        flux = profile.function(x=x, y=1., **kwargs_light)
        f_xx, f_xy, f_yx, f_yy = spp.hessian(x=x, y=1., **kwargs_spp)
        kappa_spp = 1 / 2. * (f_xx + f_yy)
        f_xx, f_xy, f_yx, f_yy = sis.hessian(x=x, y=1., **kwargs_sis)
        kappa_sis = 1 / 2. * (f_xx + f_yy)
        npt.assert_almost_equal(kappa_sis, kappa_spp, decimal=5)
        npt.assert_almost_equal(flux / flux[0],
                                kappa_sis / kappa_sis[0],
                                decimal=5)
Beispiel #5
0
class SPEMD(object):
    """
    class for smooth power law ellipse mass density profile
    """
    def __init__(self):
        self.s2 = 0.00000001
        self.spp = SPP()
        self.spemd_smooth = SPEMD_SMOOTH()

    def function(self, x, y, theta_E, gamma, q, phi_G, center_x=0, center_y=0):
        return self.spemd_smooth.function(x, y, theta_E, gamma, q, phi_G, self.s2, center_x, center_y)

    def derivatives(self, x, y, theta_E, gamma, q, phi_G, center_x=0, center_y=0):
        return self.spemd_smooth.derivatives(x, y, theta_E, gamma, q, phi_G, self.s2, center_x, center_y)

    def hessian(self, x, y, theta_E, gamma, q, phi_G, center_x=0, center_y=0):
        return self.spemd_smooth.hessian(x, y, theta_E, gamma, q, phi_G, self.s2, center_x, center_y)

    def mass_3d_lens(self, r, theta_E, gamma, q, phi_G):
        """
        computes the spherical power-law mass enclosed (with SPP routiune)
        :param r:
        :param theta_E:
        :param gamma:
        :param q:
        :param phi_G:
        :return:
        """
        return self.spp.mass_3d_lens(r, theta_E, gamma)

    def convert_params(self, theta_E, gamma, q):
        """

        :param theta_E: Einstein radius
        :param gamma: power law slope
        :param q: axis ratio
        :return:   prefactor to SPEMP profile for FASTELL
        """
        return self.spemd_smooth.convert_params(theta_E, gamma, q)
    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)
Beispiel #7
0
 def __init__(self):
     self.lens = SPP()
Beispiel #8
0
 def setup(self):
     self.SPEP = SPEP()
     self.SPP = SPP()
     self.SIS = SIS()
Beispiel #9
0
class TestSPEP(object):
    """
    tests the Gaussian methods
    """
    def setup(self):
        self.SPEP = SPEP()
        self.SPP = SPP()
        self.SIS = SIS()

    def test_function(self):
        x = np.array([1])
        y = np.array([2])
        phi_E = 1.
        gamma = 1.9
        q = 1
        phi_G = 0.
        E = phi_E / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        values_spep = self.SPEP.function(x, y, E, gamma, q, phi_G)
        values_spp = self.SPP.function(x, y, E, gamma)
        assert values_spep[0] == values_spp[0]
        x = np.array([0])
        y = np.array([0])
        values_spep = self.SPEP.function(x, y, E, gamma, q, phi_G)
        values_spp = self.SPP.function(x, y, E, gamma)
        assert values_spep[0] == values_spp[0]

        x = np.array([2, 3, 4])
        y = np.array([1, 1, 1])
        values_spep = self.SPEP.function(x, y, E, gamma, q, phi_G)
        values_spp = self.SPP.function(x, y, E, gamma)
        assert values_spep[0] == values_spp[0]
        assert values_spep[1] == values_spp[1]
        assert values_spep[2] == values_spp[2]

    def test_derivatives(self):
        x = np.array([1])
        y = np.array([2])
        phi_E = 1.
        gamma = 1.9
        q = 1
        phi_G = 0.
        E = phi_E / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        f_x_spep, f_y_spep = self.SPEP.derivatives(x, y, E, gamma, q, phi_G)
        f_x_spp, f_y_spp = self.SPP.derivatives(x, y, E, gamma)
        assert f_x_spep[0] == f_x_spp[0]
        assert f_y_spep[0] == f_y_spp[0]
        x = np.array([0])
        y = np.array([0])
        f_x_spep, f_y_spep = self.SPEP.derivatives(x, y, E, gamma, q, phi_G)
        f_x_spp, f_y_spp = self.SPP.derivatives(x, y, E, gamma)
        assert f_x_spep[0] == f_x_spp[0]
        assert f_y_spep[0] == f_y_spp[0]

        x = np.array([1, 3, 4])
        y = np.array([2, 1, 1])
        f_x_spep, f_y_spep = self.SPEP.derivatives(x, y, E, gamma, q, phi_G)
        f_x_spp, f_y_spp = self.SPP.derivatives(x, y, E, gamma)
        assert f_x_spep[0] == f_x_spp[0]
        assert f_y_spep[0] == f_y_spp[0]
        assert f_x_spep[1] == f_x_spp[1]
        assert f_y_spep[1] == f_y_spp[1]
        assert f_x_spep[2] == f_x_spp[2]
        assert f_y_spep[2] == f_y_spp[2]

    def test_hessian(self):
        x = np.array([1])
        y = np.array([2])
        phi_E = 1.
        gamma = 1.9
        q = 1.
        phi_G = 0.
        E = phi_E / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        f_xx, f_yy, f_xy = self.SPEP.hessian(x, y, E, gamma, q, phi_G)
        f_xx_spep, f_yy_spep, f_xy_spep = self.SPEP.hessian(
            x, y, E, gamma, q, phi_G)
        f_xx_spp, f_yy_spp, f_xy_spp = self.SPP.hessian(x, y, E, gamma)
        assert f_xx_spep[0] == f_xx_spp[0]
        assert f_yy_spep[0] == f_yy_spp[0]
        assert f_xy_spep[0] == f_xy_spp[0]
        x = np.array([1, 3, 4])
        y = np.array([2, 1, 1])
        f_xx_spep, f_yy_spep, f_xy_spep = self.SPEP.hessian(
            x, y, E, gamma, q, phi_G)
        f_xx_spp, f_yy_spp, f_xy_spp = self.SPP.hessian(x, y, E, gamma)
        assert f_xx_spep[0] == f_xx_spp[0]
        assert f_yy_spep[0] == f_yy_spp[0]
        assert f_xy_spep[0] == f_xy_spp[0]
        assert f_xx_spep[1] == f_xx_spp[1]
        assert f_yy_spep[1] == f_yy_spp[1]
        assert f_xy_spep[1] == f_xy_spp[1]
        assert f_xx_spep[2] == f_xx_spp[2]
        assert f_yy_spep[2] == f_yy_spp[2]
        assert f_xy_spep[2] == f_xy_spp[2]

    def test_compare_sis(self):
        x = np.array([1])
        y = np.array([2])
        theta_E = 1.
        gamma = 2.
        f_sis = self.SIS.function(x, y, theta_E)
        f_spp = self.SPP.function(x, y, theta_E, gamma)
        f_x_sis, f_y_sis = self.SIS.derivatives(x, y, theta_E)
        f_x_spp, f_y_spp = self.SPP.derivatives(x, y, theta_E, gamma)
        f_xx_sis, f_yy_sis, f_xy_sis = self.SIS.hessian(x, y, theta_E)
        f_xx_spp, f_yy_spp, f_xy_spp = self.SPP.hessian(x, y, theta_E, gamma)
        npt.assert_almost_equal(f_sis[0], f_spp[0], decimal=7)
        npt.assert_almost_equal(f_x_sis[0], f_x_spp[0], decimal=7)
        npt.assert_almost_equal(f_y_sis[0], f_y_spp[0], decimal=7)
        npt.assert_almost_equal(f_xx_sis[0], f_xx_spp[0], decimal=7)
        npt.assert_almost_equal(f_yy_sis[0], f_yy_spp[0], decimal=7)
        npt.assert_almost_equal(f_xy_sis[0], f_xy_spp[0], decimal=7)

    def test_unit_conversion(self):
        theta_E = 2.
        gamma = 2.2
        rho0 = self.SPP.theta2rho(theta_E, gamma)
        theta_E_out = self.SPP.rho2theta(rho0, gamma)
        assert theta_E == theta_E_out

    def test_mass_2d_lens(self):
        r = 1
        theta_E = 1
        gamma = 2
        m_2d = self.SPP.mass_2d_lens(r, theta_E, gamma)
        npt.assert_almost_equal(m_2d, 3.1415926535897931, decimal=8)

    def test_grav_pot(self):
        x, y = 1, 0
        rho0 = 1
        gamma = 2
        grav_pot = self.SPP.grav_pot(x, y, rho0, gamma, center_x=0, center_y=0)
        npt.assert_almost_equal(grav_pot, 12.566370614359172, decimal=8)
Beispiel #10
0
 def __init__(self):
     self.epl_major_axis = EPLMajorAxis()
     self.spp = SPP()
     super(EPL, self).__init__()
Beispiel #11
0
 def __init__(self):
     self._spp = SPP()
     super(CurvedArcSPP, self).__init__()
Beispiel #12
0
class TestCurvedArc(object):
    """
    tests the source model routines
    """
    def setup(self):
        self.model = CurvedArc()
        self.spp = SPP()

    def test_function(self):
        output = self.model.function(1, 1, tangential_stretch=2, radial_stretch=1, r_curvature=2, direction=0, center_x=0, center_y=0)
        theta_E, gamma, center_x_spp, center_y_spp = self.model._input2spp_parameterization(tangential_stretch=2, radial_stretch=1, r_curvature=2, direction=0,
                                               center_x=0, center_y=0)
        out_spp = self.spp.function(1, 1, theta_E, gamma, center_x_spp, center_y_spp) - self.spp.function(0, 0,  theta_E, gamma, center_x_spp, center_y_spp)
        npt.assert_almost_equal(output, out_spp, decimal=8)

    def test_derivatives(self):
        tangential_stretch = 5
        radial_stretch = 1
        r_curvature = 10
        direction = 0.3
        center_x = 0
        center_y = 0
        x, y = 1, 1
        theta_E, gamma, center_x_spp, center_y_spp = self.model._input2spp_parameterization(tangential_stretch,
                                                                                      radial_stretch, r_curvature,
                                                                                      direction, center_x, center_y)
        f_x, f_y = self.spp.derivatives(x, y, theta_E, gamma, center_x_spp, center_y_spp)
        f_x0, f_y0 = self.spp.derivatives(center_x, center_y, theta_E, gamma, center_x_spp, center_y_spp)
        f_x_new, f_y_new = self.model.derivatives(x, y, tangential_stretch, radial_stretch, r_curvature, direction, center_x, center_y)
        npt.assert_almost_equal(f_x_new, f_x - f_x0, decimal=8)
        npt.assert_almost_equal(f_y_new, f_y - f_y0, decimal=8)

    def test_hessian(self):
        lens = LensModel(lens_model_list=['CURVED_ARC'])
        center_x, center_y = 0, 0
        tangential_stretch = 10
        radial_stretch = 1
        kwargs_lens = [
            {'tangential_stretch': tangential_stretch, 'radial_stretch': radial_stretch, 'r_curvature': 10.5, 'direction': 0.,
             'center_x': center_x, 'center_y': center_y}]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag, tangential_stretch * radial_stretch, decimal=8)

        center_x, center_y = 2, 3
        tangential_stretch = 10
        radial_stretch = 1
        kwargs_lens = [
            {'tangential_stretch': tangential_stretch, 'radial_stretch': radial_stretch, 'r_curvature': 10.5, 'direction': 0.,
             'center_x': center_x, 'center_y': center_y}]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag, tangential_stretch * radial_stretch, decimal=8)

        center_x, center_y = 0, 0
        tangential_stretch = 3
        radial_stretch = -1
        kwargs_lens = [
            {'tangential_stretch': tangential_stretch, 'radial_stretch': radial_stretch, 'r_curvature': 10.5,
             'direction': 0.,
             'center_x': center_x, 'center_y': center_y}]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag, tangential_stretch * radial_stretch, decimal=8)

        center_x, center_y = 0, 0
        tangential_stretch = -3
        radial_stretch = -1
        kwargs_lens = [
            {'tangential_stretch': tangential_stretch, 'radial_stretch': radial_stretch, 'r_curvature': 10.5,
             'direction': 0.,
             'center_x': center_x, 'center_y': center_y}]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag, tangential_stretch * radial_stretch, decimal=8)

        center_x, center_y = 0, 0
        tangential_stretch = 10.4
        radial_stretch = 0.6
        kwargs_lens = [
            {'tangential_stretch': tangential_stretch, 'radial_stretch': radial_stretch, 'r_curvature': 10.5,
             'direction': 0.,
             'center_x': center_x, 'center_y': center_y}]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag, tangential_stretch * radial_stretch, decimal=8)
Beispiel #13
0
class AnalyticKinematics(Anisotropy):
    """
    class to compute eqn 20 in Suyu+2010 with a Monte-Carlo from rendering from the
    light profile distribution and displacing them with a Gaussian seeing convolution.

    This class assumes spherical symmetry in light and mass distribution and
        - a Hernquist light profile (parameterised by the half-light radius)
        - a power-law mass profile (parameterized by the Einstein radius and logarithmic slop)

    The analytic equations for the kinematics in this approximation are presented e.g. in Suyu et al. 2010 and
    the spectral rendering approach to compute the seeing convolved slit measurement is presented in Birrer et al. 2016.
    The stellar anisotropy is parameterised based on Osipkov 1979; Merritt 1985.

    All units are meant to be in angular arc seconds. The physical units are fold in through the angular diameter
    distances

    """
    def __init__(self,
                 kwargs_cosmo,
                 interpol_grid_num=100,
                 log_integration=False,
                 max_integrate=100,
                 min_integrate=0.001):
        """

        :param kwargs_cosmo: keyword argument with angular diameter distances
        """

        self._interp_grid_num = interpol_grid_num
        self._log_int = log_integration
        self._max_integrate = max_integrate  # maximal integration (and interpolation) in units of arcsecs
        self._min_integrate = min_integrate  # min integration (and interpolation) in units of arcsecs
        self._max_interpolate = max_integrate  # we chose to set the interpolation range to the integration range
        self._min_interpolate = min_integrate  # we chose to set the interpolation range to the integration range

        self._cosmo = Cosmo(**kwargs_cosmo)
        self._spp = SPP()
        Anisotropy.__init__(self, anisotropy_type='OM')

    def _rho0_r0_gamma(self, theta_E, gamma):
        # equation (14) in Suyu+ 2010
        return -1 * math.gamma(gamma/2) / (np.sqrt(np.pi)*math.gamma((gamma-3)/2.)) * theta_E ** gamma / \
               self._cosmo.arcsec2phys_lens(theta_E) * self._cosmo.epsilon_crit * const.M_sun / const.Mpc ** 3

    @staticmethod
    def draw_light(kwargs_light):
        """

        :param kwargs_light: keyword argument (list) of the light model
        :return: 3d radius (if possible), 2d projected radius, x-projected coordinate, y-projected coordinate
        """
        if 'a' not in kwargs_light:
            kwargs_light['a'] = 0.551 * kwargs_light['r_eff']
        a = kwargs_light['a']
        r = vel_util.draw_hernquist(a)
        R, x, y = vel_util.project2d_random(r)
        return r, R, x, y

    def _sigma_s2(self, r, R, r_ani, a, gamma, rho0_r0_gamma):
        """
        projected velocity dispersion
        :param r: 3d radius of the light tracer particle
        :param R: 2d projected radius of the light tracer particle
        :param r_ani: anisotropy radius
        :param a: scale of the Hernquist light profile
        :param gamma: power-law slope of the mass profile
        :param rho0_r0_gamma: combination of Einstein radius and power-law slope as equation (14) in Suyu+ 2010
        :return: projected velocity dispersion
        """
        beta = self.beta_r(r, **{'r_ani': r_ani})
        return (1 - beta * R**2 / r**2) * self._sigma_r2_interp(
            r, a, gamma, rho0_r0_gamma, r_ani)

    def sigma_s2(self, r, R, kwargs_mass, kwargs_light, kwargs_anisotropy):
        """
        returns unweighted los velocity dispersion for a specified projected radius, with weight 1

        :param r: 3d radius (not needed for this calculation)
        :param R: 2d projected radius (in angular units of arcsec)
        :param kwargs_mass: mass model parameters (following lenstronomy lens model conventions)
        :param kwargs_light: deflector light parameters (following lenstronomy light model conventions)
        :param kwargs_anisotropy: anisotropy parameters, may vary according to anisotropy type chosen.
            We refer to the Anisotropy() class for details on the parameters.
        :return: line-of-sight projected velocity dispersion at projected radius R from 3d radius r
        """
        a, gamma, rho0_r0_gamma, r_ani = self._read_out_params(
            kwargs_mass, kwargs_light, kwargs_anisotropy)
        return self._sigma_s2(r, R, r_ani, a, gamma, rho0_r0_gamma), 1

    def sigma_r2(self, r, kwargs_mass, kwargs_light, kwargs_anisotropy):
        """
        equation (19) in Suyu+ 2010

        :param r: 3d radius
        :param kwargs_mass: mass profile keyword arguments
        :param kwargs_light: light profile keyword arguments
        :param kwargs_anisotropy: anisotropy keyword arguments
        :return: velocity dispersion in [m/s]
        """
        a, gamma, rho0_r0_gamma, r_ani = self._read_out_params(
            kwargs_mass, kwargs_light, kwargs_anisotropy)
        return self._sigma_r2(r, a, gamma, rho0_r0_gamma, r_ani)

    def _read_out_params(self, kwargs_mass, kwargs_light, kwargs_anisotropy):
        """
        reads the relevant parameters out of the keyword arguments and transforms them to the conventions used in this
        class

        :param kwargs_mass: mass profile keyword arguments
        :param kwargs_light: light profile keyword arguments
        :param kwargs_anisotropy: anisotropy keyword arguments
        :return: a (Rs of Hernquist profile), gamma, rho0_r0_gamma, r_ani
        """
        if 'a' not in kwargs_light:
            kwargs_light['a'] = 0.551 * kwargs_light['r_eff']
        if 'rho0_r0_gamma' not in kwargs_mass:
            kwargs_mass['rho0_r0_gamma'] = self._rho0_r0_gamma(
                kwargs_mass['theta_E'], kwargs_mass['gamma'])
        a = kwargs_light['a']
        gamma = kwargs_mass['gamma']
        rho0_r0_gamma = kwargs_mass['rho0_r0_gamma']
        r_ani = kwargs_anisotropy['r_ani']
        return a, gamma, rho0_r0_gamma, r_ani

    def _sigma_r2(self, r, a, gamma, rho0_r0_gamma, r_ani):
        """
        equation (19) in Suyu+ 2010
        """
        # first term
        prefac1 = 4 * np.pi * const.G * a**(-gamma) * rho0_r0_gamma / (3 -
                                                                       gamma)
        prefac2 = r * (r + a)**3 / (r**2 + r_ani**2)
        # TODO check whether interpolation functions can speed this up
        hyp1 = vel_util.hyp_2F1(a=2 + gamma,
                                b=gamma,
                                c=3 + gamma,
                                z=1. / (1 + r / a))
        hyp2 = vel_util.hyp_2F1(a=3, b=gamma, c=1 + gamma, z=-a / r)
        fac = r_ani**2 / a**2 * hyp1 / (
            (2 + gamma) * (r / a + 1)**(2 + gamma)) + hyp2 / (gamma *
                                                              (r / a)**gamma)
        return prefac1 * prefac2 * fac * (const.arcsec * self._cosmo.dd *
                                          const.Mpc)**2

    def _sigma_r2_interp(self, r, a, gamma, rho0_r0_gamma, r_ani):
        """

        :param r:
        :param a:
        :param gamma:
        :param rho0_r0_gamma:
        :param r_ani:
        :return:
        """
        if not hasattr(self, '_interp_sigma_r2'):
            min_log = np.log10(self._min_integrate)
            max_log = np.log10(self._max_integrate)
            r_array = np.logspace(min_log, max_log, self._interp_grid_num)
            I_R_sigma2_array = []
            for r_i in r_array:
                I_R_sigma2_array.append(
                    self._sigma_r2(r_i, a, gamma, rho0_r0_gamma, r_ani))
            self._interp_sigma_r2 = interp1d(np.log(r_array),
                                             np.array(I_R_sigma2_array),
                                             fill_value="extrapolate")
        return self._interp_sigma_r2(np.log(r))

    def grav_potential(self, r, kwargs_mass):
        """
        Gravitational potential in SI units

        :param r: radius (arc seconds)
        :param kwargs_mass:
        :return: gravitational potential
        """
        theta_E = kwargs_mass['theta_E']
        gamma = kwargs_mass['gamma']
        mass_dimless = self._spp.mass_3d_lens(r, theta_E, gamma)
        mass_dim = mass_dimless * const.arcsec ** 2 * self._cosmo.dd * self._cosmo.ds / self._cosmo.dds * const.Mpc * \
                    const.c ** 2 / (4 * np.pi * const.G)
        grav_pot = -const.G * mass_dim / (r * const.arcsec * self._cosmo.dd *
                                          const.Mpc)
        return grav_pot

    def delete_cache(self):
        """
        deletes temporary cache tight to a specific model

        :return:
        """
        if hasattr(self, '_interp_sigma_r2'):
            del self._interp_sigma_r2
Beispiel #14
0
class CurvedArc(object):
    """
    lens model that describes a section of a highly magnified deflector region.
    The parameterization is chosen to describe local observables efficient.

    Observables are:
    - curvature radius (basically bending relative to the center of the profile)
    - radial stretch (plus sign) thickness of arc with parity (more generalized than the power-law slope)
    - tangential stretch (plus sign). Infinity means at critical curve
    - direction of curvature
    - position of arc

    Requirements:
    - Should work with other perturbative models without breaking its meaning (say when adding additional shear terms)
    - Must best reflect the observables in lensing
    - minimal covariances between the parameters, intuitive parameterization.

    """
    def __init__(self):
        self._spp = SPP()

    def _input2spp_parameterization(self, tangential_stretch, radial_stretch,
                                    r_curvature, direction, center_x,
                                    center_y):
        """

        :param tangential_stretch: float, stretch of intrinsic source in tangential direction
        :param radial_stretch: float, stretch of intrinsic source in radial direction
        :param r_curvature: curvature radius
        :param direction: float, angle in radian
        :param center_x: center of source in image plane
        :param center_y: center of source in image plane
        :return: parameters in terms of a spherical power-law profile resulting in the same observables
        """
        center_x_spp = center_x - r_curvature * np.cos(direction)
        center_y_spp = center_y - r_curvature * np.sin(direction)

        theta_E, gamma = self._stretch2profile(tangential_stretch,
                                               radial_stretch, r_curvature)
        return theta_E, gamma, center_x_spp, center_y_spp

    @staticmethod
    def _stretch2profile(tangential_stretch, radial_stretch, r_curvature):
        """

        :param tangential_stretch: float, stretch of intrinsic source in tangential direction
        :param radial_stretch: float, stretch of intrinsic source in radial direction
        :param r_curvature: radius of SPP where to have the specific tangential and radial stretch values
        :return: theta_E, gamma of SPP profile
        """
        gamma = (1. / radial_stretch - 1) / (1 - 1. / tangential_stretch) + 2
        theta_E = abs(1 - 1. / tangential_stretch)**(1. /
                                                     (gamma - 1)) * r_curvature
        return theta_E, gamma

    def function(self, x, y, tangential_stretch, radial_stretch, r_curvature,
                 direction, center_x, center_y):
        """
        ATTENTION: there may not be a global lensing potential!

        :param x:
        :param y:
        :param tangential_stretch:
        :param radial_stretch:
        :param r_curvature:
        :param direction:
        :param center_x:
        :param center_y:
        :return:
        """
        theta_E, gamma, center_x_spp, center_y_spp = self._input2spp_parameterization(
            tangential_stretch, radial_stretch, r_curvature, direction,
            center_x, center_y)
        return self._spp.function(x, y, theta_E, gamma, center_x_spp,
                                  center_y_spp) - self._spp.function(
                                      center_x, center_y, theta_E, gamma,
                                      center_x_spp, center_y_spp)

    def derivatives(self, x, y, tangential_stretch, radial_stretch,
                    r_curvature, direction, center_x, center_y):
        """

        :param x:
        :param y:
        :param tangential_stretch:
        :param radial_stretch:
        :param r_curvature:
        :param direction:
        :param center_x:
        :param center_y:
        :return:
        """
        theta_E, gamma, center_x_spp, center_y_spp = self._input2spp_parameterization(
            tangential_stretch, radial_stretch, r_curvature, direction,
            center_x, center_y)
        f_x, f_y = self._spp.derivatives(x, y, theta_E, gamma, center_x_spp,
                                         center_y_spp)
        f_x0, f_y0 = self._spp.derivatives(center_x, center_y, theta_E, gamma,
                                           center_x_spp, center_y_spp)
        return f_x - f_x0, f_y - f_y0

    def hessian(self, x, y, tangential_stretch, radial_stretch, r_curvature,
                direction, center_x, center_y):
        """

        :param x:
        :param y:
        :param tangential_stretch:
        :param radial_stretch:
        :param r_curvature:
        :param direction:
        :param center_x:
        :param center_y:
        :return:
        """
        theta_E, gamma, center_x_spp, center_y_spp = self._input2spp_parameterization(
            tangential_stretch, radial_stretch, r_curvature, direction,
            center_x, center_y)
        return self._spp.hessian(x, y, theta_E, gamma, center_x_spp,
                                 center_y_spp)
Beispiel #15
0
 def __init__(self):
     self.s2 = 0.00000001
     self.spp = SPP()
     self.spemd_smooth = SPEMD_SMOOTH()
Beispiel #16
0
class PEMD(LensProfileBase):
    """
    class for power law ellipse mass density profile.
    This class effectively calls the class SPEMD_SMOOTH with a fixed and very small central smoothing scale
    to perform the numerical integral using the FASTELL code by Renan Barkana.


    The Einstein ring parameter converts to the definition used by GRAVLENS as follow:
    (theta_E / theta_E_gravlens) = sqrt[ (1+q^2) / (2 q) ]
    """
    param_names = ['theta_E', 'gamma', 'e1', 'e2', 'center_x', 'center_y']
    lower_limit_default = {
        'theta_E': 0,
        'gamma': 1.5,
        'e1': -0.5,
        'e2': -0.5,
        'center_x': -100,
        'center_y': -100
    }
    upper_limit_default = {
        'theta_E': 100,
        'gamma': 2.5,
        'e1': 0.5,
        'e2': 0.5,
        'center_x': 100,
        'center_y': 100
    }

    def __init__(self, suppress_fastell=False):
        """

        :param suppress_fastell: bool, if True, does not raise if fastell4py is not installed
        """
        self._s_scale = 0.0001  # smoothing scale as used to numerically compute a power-law profile
        self.spp = SPP()
        self.spemd_smooth = SPEMD(suppress_fastell=suppress_fastell)
        super(PEMD, self).__init__()

    def function(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """

        :param x: x-coordinate (angle)
        :param y: y-coordinate (angle)
        :param theta_E: Einstein radius (angle), pay attention to specific definition!
        :param gamma: logarithmic slope of the power-law profile. gamma=2 corresponds to isothermal
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: x-position of lens center
        :param center_y: y-position of lens center
        :return: lensing potential
        """
        return self.spemd_smooth.function(x, y, theta_E, gamma, e1, e2,
                                          self._s_scale, center_x, center_y)

    def derivatives(self,
                    x,
                    y,
                    theta_E,
                    gamma,
                    e1,
                    e2,
                    center_x=0,
                    center_y=0):
        """

        :param x: x-coordinate (angle)
        :param y: y-coordinate (angle)
        :param theta_E: Einstein radius (angle), pay attention to specific definition!
        :param gamma: logarithmic slope of the power-law profile. gamma=2 corresponds to isothermal
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: x-position of lens center
        :param center_y: y-position of lens center
        :return: deflection angles alpha_x, alpha_y
        """
        return self.spemd_smooth.derivatives(x, y, theta_E, gamma, e1, e2,
                                             self._s_scale, center_x, center_y)

    def hessian(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """

        :param x: x-coordinate (angle)
        :param y: y-coordinate (angle)
        :param theta_E: Einstein radius (angle), pay attention to specific definition!
        :param gamma: logarithmic slope of the power-law profile. gamma=2 corresponds to isothermal
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: x-position of lens center
        :param center_y: y-position of lens center
        :return: Hessian components f_xx, f_yy, f_xy
        """
        return self.spemd_smooth.hessian(x, y, theta_E, gamma, e1, e2,
                                         self._s_scale, center_x, center_y)

    def mass_3d_lens(self, r, theta_E, gamma, e1=None, e2=None):
        """
        computes the spherical power-law mass enclosed (with SPP routine)
        :param r: radius within the mass is computed
        :param theta_E: Einstein radius
        :param gamma: power-law slope
        :param e1: eccentricity component (not used)
        :param e2: eccentricity component (not used)
        :return: mass enclosed a 3D radius r
        """
        return self.spp.mass_3d_lens(r, theta_E, gamma)

    def density_lens(self, r, theta_E, gamma, e1=None, e2=None):
        """
        computes the density at 3d radius r given lens model parameterization.
        The integral in the LOS projection of this quantity results in the convergence quantity.

        :param r: radius within the mass is computed
        :param theta_E: Einstein radius
        :param gamma: power-law slope
        :param e1: eccentricity component (not used)
        :param e2: eccentricity component (not used)
        :return: mass enclosed a 3D radius r
        """
        return self.spp.density_lens(r, theta_E, gamma)
Beispiel #17
0
 def __init__(self):
     self.s2 = 0.00000001  # smoothing scale as used to numerically compute a power-law profile
     self.spp = SPP()
     self.spemd_smooth = SPEMD_SMOOTH()
     super(SPEMD, self).__init__()
Beispiel #18
0
 def __init__(self):
     from lenstronomy.LensModel.Profiles.spp import SPP
     self.spp = SPP()
Beispiel #19
0
class SPEP(object):
    """
    class for Softened power-law elliptical potential (SPEP)
    """
    def __init__(self):
        from lenstronomy.LensModel.Profiles.spp import SPP
        self.spp = SPP()

    def function(self, x, y, theta_E, gamma, q, phi_G, center_x=0, center_y=0):
        """
        :param x: set of x-coordinates
        :type x: array of size (n)
        :param theta_E: Einstein radius of lense
        :type theta_E: float.
        :param gamma: power law slope of mass profifle
        :type gamma: <2 float
        :param q: Axis ratio
        :type q: 0<q<1
        :param phi_G: position angel of SES
        :type q: 0<phi_G<pi/2
        :returns:  function
        :raises: AttributeError, KeyError
        """
        gamma, q = self._param_bounds(gamma, q)
        theta_E *= q
        x_shift = x - center_x
        y_shift = y - center_y
        E = theta_E / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        #E = phi_E
        eta = -gamma + 3
        xt1 = np.cos(phi_G) * x_shift + np.sin(phi_G) * y_shift
        xt2 = -np.sin(phi_G) * x_shift + np.cos(phi_G) * y_shift
        p2 = xt1**2 + xt2**2 / q**2
        s2 = 0.  # softening
        return 2 * E**2 / eta**2 * ((p2 + s2) / E**2)**(eta / 2)

    def derivatives(self,
                    x,
                    y,
                    theta_E,
                    gamma,
                    q,
                    phi_G,
                    center_x=0,
                    center_y=0):

        # # @hope.jit
        # def xy_prime(dx, dy, eta, a, E, xt1, xt2, q):
        #     fac = 1./eta*(a/(E*E))**(eta/2-1)*2
        #     dx[:] = fac*xt1
        #     dy[:] = fac*xt2/(q*q)
        gamma, q = self._param_bounds(gamma, q)
        phi_E_new = theta_E * q
        x_shift = x - center_x
        y_shift = y - center_y
        E = phi_E_new / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        # E = phi_E
        eta = float(-gamma + 3)
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)

        xt1 = cos_phi * x_shift + sin_phi * y_shift
        xt2 = -sin_phi * x_shift + cos_phi * y_shift
        xt2difq2 = xt2 / (q * q)
        P2 = xt1 * xt1 + xt2 * xt2difq2
        if isinstance(P2, int) or isinstance(P2, float):
            a = max(0.000001, P2)
        else:
            a = np.empty_like(P2)
            p2 = P2[P2 > 0]  #in the SIS regime
            a[P2 == 0] = 0.000001
            a[P2 > 0] = p2
        fac = 1. / eta * (a / (E * E))**(eta / 2 - 1) * 2
        f_x_prim = fac * xt1
        f_y_prim = fac * xt2difq2

        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, theta_E, gamma, q, phi_G, center_x=0, center_y=0):
        gamma, q = self._param_bounds(gamma, q)
        phi_E_new = theta_E * q
        x_shift = x - center_x
        y_shift = y - center_y
        E = phi_E_new / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        # E = phi_E
        eta = float(-gamma + 3)
        xt1 = np.cos(phi_G) * x_shift + np.sin(phi_G) * y_shift
        xt2 = -np.sin(phi_G) * x_shift + np.cos(phi_G) * y_shift
        P2 = xt1**2 + xt2**2 / q**2
        if isinstance(P2, int) or isinstance(P2, float):
            a = max(0.000001, P2)
        else:
            a = np.empty_like(P2)
            p2 = P2[P2 > 0]  #in the SIS regime
            a[P2 == 0] = 0.000001
            a[P2 > 0] = p2
        s2 = 0.  # softening

        kappa = 1. / eta * (a / E**2)**(eta / 2 - 1) * (
            (eta - 2) * (xt1**2 + xt2**2 / q**4) / a + (1 + 1 / q**2))
        gamma1_value = 1. / eta * (a / E**2)**(
            eta / 2 - 1) * (1 - 1 / q**2 + (eta / 2 - 1) *
                            (2 * xt1**2 - 2 * xt2**2 / q**4) / a)
        gamma2_value = 4 * xt1 * xt2 / q**2 * (1. / 2 - 1 / eta) * (
            a / E**2)**(eta / 2 - 2) / E**2

        gamma1 = np.cos(2 * phi_G) * gamma1_value - np.sin(
            2 * phi_G) * gamma2_value
        gamma2 = +np.sin(2 * phi_G) * gamma1_value + np.cos(
            2 * phi_G) * gamma2_value
        f_xx = kappa + gamma1
        f_yy = kappa - gamma1
        f_xy = gamma2
        return f_xx, f_yy, f_xy

    def mass_3d_lens(self, r, theta_E, gamma, q, phi_G):
        """
        computes the spherical power-law mass enclosed (with SPP routiune)
        :param r:
        :param theta_E:
        :param gamma:
        :param q:
        :param phi_G:
        :return:
        """
        return self.spp.mass_3d_lens(r, theta_E, gamma)

    def _param_bounds(self, gamma, q):
        """
        bounds parameters

        :param gamma:
        :param q:
        :return:
        """
        if gamma < 1.4:
            gamma = 1.4
        if gamma > 2.9:
            gamma = 2.9
        if q < 0.3:
            q = 0.3
        return float(gamma), q
Beispiel #20
0
 def __init__(self):
     self._spp = SPP()
Beispiel #21
0
class PEMD(LensProfileBase):
    """
    class for power law ellipse mass density profile.
    This class effectively calls the class SPEMD_SMOOTH with a fixed and very small central smoothing scale
    to perform the numerical integral using the FASTELL code by Renan Barkana.

    .. math::
        \\kappa(x, y) = \\frac{3-\\gamma}{2} \\left(\\frac{\\theta_{E}}{\\sqrt{q x^2 + y^2/q}} \\right)^{\\gamma-1}

    with :math:`\\theta_{E}` is the (circularized) Einstein radius,
    :math:`\\gamma` is the negative power-law slope of the 3D mass distributions,
    :math:`q` is the minor/major axis ratio,
    and :math:`x` and :math:`y` are defined in a coordinate system aligned with the major and minor axis of the lens.

    In terms of eccentricities, this profile is defined as

    .. math::
        \\kappa(r) = \\frac{3-\\gamma}{2} \\left(\\frac{\\theta'_{E}}{r \\sqrt{1 − e*\\cos(2*\\phi)}} \\right)^{\\gamma-1}

    with :math:`\\epsilon` is the ellipticity defined as

    .. math::
        \\epsilon = \\frac{1-q^2}{1+q^2}

    And an Einstein radius :math:`\\theta'_{\\rm E}` related to the definition used is

    .. math::
        \\left(\\frac{\\theta'_{\\rm E}}{\\theta_{\\rm E}}\\right)^{2} = \\frac{2q}{1+q^2}.


    """
    param_names = ['theta_E', 'gamma', 'e1', 'e2', 'center_x', 'center_y']
    lower_limit_default = {
        'theta_E': 0,
        'gamma': 1.5,
        'e1': -0.5,
        'e2': -0.5,
        'center_x': -100,
        'center_y': -100
    }
    upper_limit_default = {
        'theta_E': 100,
        'gamma': 2.5,
        'e1': 0.5,
        'e2': 0.5,
        'center_x': 100,
        'center_y': 100
    }

    def __init__(self, suppress_fastell=False):
        """

        :param suppress_fastell: bool, if True, does not raise if fastell4py is not installed
        """
        self._s_scale = 0.0000001  # smoothing scale as used to numerically compute a power-law profile
        self.spp = SPP()
        self.spemd_smooth = SPEMD(suppress_fastell=suppress_fastell)
        super(PEMD, self).__init__()

    def function(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """

        :param x: x-coordinate (angle)
        :param y: y-coordinate (angle)
        :param theta_E: Einstein radius (angle), pay attention to specific definition!
        :param gamma: logarithmic slope of the power-law profile. gamma=2 corresponds to isothermal
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: x-position of lens center
        :param center_y: y-position of lens center
        :return: lensing potential
        """
        return self.spemd_smooth.function(x, y, theta_E, gamma, e1, e2,
                                          self._s_scale, center_x, center_y)

    def derivatives(self,
                    x,
                    y,
                    theta_E,
                    gamma,
                    e1,
                    e2,
                    center_x=0,
                    center_y=0):
        """

        :param x: x-coordinate (angle)
        :param y: y-coordinate (angle)
        :param theta_E: Einstein radius (angle), pay attention to specific definition!
        :param gamma: logarithmic slope of the power-law profile. gamma=2 corresponds to isothermal
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: x-position of lens center
        :param center_y: y-position of lens center
        :return: deflection angles alpha_x, alpha_y
        """
        return self.spemd_smooth.derivatives(x, y, theta_E, gamma, e1, e2,
                                             self._s_scale, center_x, center_y)

    def hessian(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """

        :param x: x-coordinate (angle)
        :param y: y-coordinate (angle)
        :param theta_E: Einstein radius (angle), pay attention to specific definition!
        :param gamma: logarithmic slope of the power-law profile. gamma=2 corresponds to isothermal
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: x-position of lens center
        :param center_y: y-position of lens center
        :return: Hessian components f_xx, f_xy, f_yx, f_yy
        """
        return self.spemd_smooth.hessian(x, y, theta_E, gamma, e1, e2,
                                         self._s_scale, center_x, center_y)

    def mass_3d_lens(self, r, theta_E, gamma, e1=None, e2=None):
        """
        computes the spherical power-law mass enclosed (with SPP routine)
        :param r: radius within the mass is computed
        :param theta_E: Einstein radius
        :param gamma: power-law slope
        :param e1: eccentricity component (not used)
        :param e2: eccentricity component (not used)
        :return: mass enclosed a 3D radius r
        """
        return self.spp.mass_3d_lens(r, theta_E, gamma)

    def density_lens(self, r, theta_E, gamma, e1=None, e2=None):
        """
        computes the density at 3d radius r given lens model parameterization.
        The integral in the LOS projection of this quantity results in the convergence quantity.

        :param r: radius within the mass is computed
        :param theta_E: Einstein radius
        :param gamma: power-law slope
        :param e1: eccentricity component (not used)
        :param e2: eccentricity component (not used)
        :return: mass enclosed a 3D radius r
        """
        return self.spp.density_lens(r, theta_E, gamma)
Beispiel #22
0
class SPEP(LensProfileBase):
    """
    class for Softened power-law elliptical potential (SPEP)
    """
    param_names = ['theta_E', 'gamma', 'e1', 'e2', 'center_x', 'center_y']
    lower_limit_default = {
        'theta_E': 0,
        'gamma': 0,
        'e1': -0.5,
        'e2': -0.5,
        'center_x': -100,
        'center_y': -100
    }
    upper_limit_default = {
        'theta_E': 100,
        'gamma': 100,
        'e1': 0.5,
        'e2': 0.5,
        'center_x': 100,
        'center_y': 100
    }

    def __init__(self):
        self.spp = SPP()
        super(SPEP, self).__init__()

    def function(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """
        :param x: set of x-coordinates
        :type x: array of size (n)
        :param theta_E: Einstein radius of lense
        :type theta_E: float.
        :param gamma: power law slope of mass profifle
        :type gamma: <2 float
        :param e1: eccentricity
        :type e1: -1<e1<1
        :param e2: eccentricity
        :type e2: -1<e1<1
        :returns:  function
        :raises: AttributeError, KeyError
        """
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        gamma, q = self._param_bounds(gamma, q)
        theta_E *= q
        x_shift = x - center_x
        y_shift = y - center_y
        E = theta_E / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        #E = phi_E
        eta = -gamma + 3
        xt1 = np.cos(phi_G) * x_shift + np.sin(phi_G) * y_shift
        xt2 = -np.sin(phi_G) * x_shift + np.cos(phi_G) * y_shift
        p2 = xt1**2 + xt2**2 / q**2
        s2 = 0.  # softening
        return 2 * E**2 / eta**2 * ((p2 + s2) / E**2)**(eta / 2)

    def derivatives(self,
                    x,
                    y,
                    theta_E,
                    gamma,
                    e1,
                    e2,
                    center_x=0,
                    center_y=0):

        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        gamma, q = self._param_bounds(gamma, q)
        phi_E_new = theta_E * q
        x_shift = x - center_x
        y_shift = y - center_y
        E = phi_E_new / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        # E = phi_E
        eta = float(-gamma + 3)
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)

        xt1 = cos_phi * x_shift + sin_phi * y_shift
        xt2 = -sin_phi * x_shift + cos_phi * y_shift
        xt2difq2 = xt2 / (q * q)
        P2 = xt1 * xt1 + xt2 * xt2difq2
        if isinstance(P2, int) or isinstance(P2, float):
            a = max(0.000001, P2)
        else:
            a = np.empty_like(P2)
            p2 = P2[P2 > 0]  #in the SIS regime
            a[P2 == 0] = 0.000001
            a[P2 > 0] = p2
        fac = 1. / eta * (a / (E * E))**(eta / 2 - 1) * 2
        f_x_prim = fac * xt1
        f_y_prim = fac * xt2difq2

        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, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        gamma, q = self._param_bounds(gamma, q)
        phi_E_new = theta_E * q
        #x_shift = x - center_x
        #y_shift = y - center_y

        # shift
        x_ = x - center_x
        y_ = y - center_y
        # rotate
        x__, y__ = util.rotate(x_, y_, phi_G)

        E = phi_E_new / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q))
        if E <= 0:
            return np.zeros_like(x), np.zeros_like(x), np.zeros_like(
                x), np.zeros_like(x)
        # E = phi_E
        eta = float(-gamma + 3)
        #xt1 = np.cos(phi_G)*x_shift+np.sin(phi_G)*y_shift
        #xt2 = -np.sin(phi_G)*x_shift+np.cos(phi_G)*y_shift
        xt1, xt2 = x__, y__
        P2 = xt1**2 + xt2**2 / q**2

        if isinstance(P2, int) or isinstance(P2, float):
            a = max(0.000001, P2)
        else:
            a = np.empty_like(P2)
            p2 = P2[P2 > 0]  #in the SIS regime
            a[P2 == 0] = 0.000001
            a[P2 > 0] = p2
        s2 = 0.  # softening

        kappa = 1. / eta * (a / E**2)**(eta / 2 - 1) * (
            (eta - 2) * (xt1**2 + xt2**2 / q**4) / a + (1 + 1 / q**2))
        gamma1_value = 1. / eta * (a / E**2)**(
            eta / 2 - 1) * (1 - 1 / q**2 + (eta / 2 - 1) *
                            (2 * xt1**2 - 2 * xt2**2 / q**4) / a)
        gamma2_value = 4 * xt1 * xt2 / q**2 * (1. / 2 - 1 / eta) * (
            a / E**2)**(eta / 2 - 2) / E**2

        gamma1 = np.cos(2 * phi_G) * gamma1_value - np.sin(
            2 * phi_G) * gamma2_value
        gamma2 = +np.sin(2 * phi_G) * gamma1_value + np.cos(
            2 * phi_G) * gamma2_value

        f_xx = kappa + gamma1
        f_yy = kappa - gamma1
        f_xy = gamma2
        return f_xx, f_xy, f_xy, f_yy

    def mass_3d_lens(self, r, theta_E, gamma, e1=None, e2=None):
        """
        computes the spherical power-law mass enclosed (with SPP routine)

        :param r: radius within the mass is computed
        :param theta_E: Einstein radius
        :param gamma: power-law slope
        :param e1: eccentricity component (not used)
        :param e2: eccentricity component (not used)
        :return: mass enclosed a 3D radius r
        """
        return self.spp.mass_3d_lens(r, theta_E, gamma)

    def density_lens(self, r, theta_E, gamma, e1=None, e2=None):
        """
        computes the density at 3d radius r given lens model parameterization.
        The integral in the LOS projection of this quantity results in the convergence quantity.

        :param r: radius within the mass is computed
        :param theta_E: Einstein radius
        :param gamma: power-law slope
        :param e1: eccentricity component (not used)
        :param e2: eccentricity component (not used)
        :return: mass enclosed a 3D radius r
        """
        return self.spp.density_lens(r, theta_E, gamma)

    @staticmethod
    def _param_bounds(gamma, q):
        """
        bounds parameters

        :param gamma:
        :param q:
        :return:
        """
        if gamma < 1.4:
            gamma = 1.4
        if gamma > 2.9:
            gamma = 2.9
        if q < 0.01:
            q = 0.01
        return float(gamma), q
Beispiel #23
0
 def setup(self):
     self.model = CurvedArc()
     self.spp = SPP()
Beispiel #24
0
    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
Beispiel #25
0
class CurvedArcSPP(LensProfileBase):
    """
    lens model that describes a section of a highly magnified deflector region.
    The parameterization is chosen to describe local observables efficient.

    Observables are:
    - curvature radius (basically bending relative to the center of the profile)
    - radial stretch (plus sign) thickness of arc with parity (more generalized than the power-law slope)
    - tangential stretch (plus sign). Infinity means at critical curve
    - direction of curvature
    - position of arc

    Requirements:
    - Should work with other perturbative models without breaking its meaning (say when adding additional shear terms)
    - Must best reflect the observables in lensing
    - minimal covariances between the parameters, intuitive parameterization.

    """
    param_names = [
        'tangential_stretch', 'radial_stretch', 'curvature', 'direction',
        'center_x', 'center_y'
    ]
    lower_limit_default = {
        'tangential_stretch': -100,
        'radial_stretch': -5,
        'curvature': 0.000001,
        'direction': -np.pi,
        'center_x': -100,
        'center_y': -100
    }
    upper_limit_default = {
        'tangential_stretch': 100,
        'radial_stretch': 5,
        'curvature': 100,
        'direction': np.pi,
        'center_x': 100,
        'center_y': 100
    }

    def __init__(self):
        self._spp = SPP()
        super(CurvedArcSPP, self).__init__()

    @staticmethod
    def stretch2spp(tangential_stretch, radial_stretch, curvature, direction,
                    center_x, center_y):
        """

        :param tangential_stretch: float, stretch of intrinsic source in tangential direction
        :param radial_stretch: float, stretch of intrinsic source in radial direction
        :param curvature: 1/curvature radius
        :param direction: float, angle in radian
        :param center_x: center of source in image plane
        :param center_y: center of source in image plane
        :return: parameters in terms of a spherical power-law profile resulting in the same observables
        """
        center_x_spp, center_y_spp = center_deflector(curvature, direction,
                                                      center_x, center_y)
        r_curvature = 1. / curvature
        gamma = (1. / radial_stretch - 1) / (1 - 1. / tangential_stretch) + 2
        theta_E = abs(1 - 1. / tangential_stretch)**(1. /
                                                     (gamma - 1)) * r_curvature
        return theta_E, gamma, center_x_spp, center_y_spp

    @staticmethod
    def spp2stretch(theta_E, gamma, center_x_spp, center_y_spp, center_x,
                    center_y):
        """
        turn Singular power-law lens model into stretch parameterization at position (center_x, center_y)
        This is the inverse function of stretch2spp()

        :param theta_E: Einstein radius of SPP model
        :param gamma: power-law slope
        :param center_x_spp: center of SPP model
        :param center_y_spp: center of SPP model
        :param center_x: center of curved model definition
        :param center_y: center of curved model definition
        :return: tangential_stretch, radial_stretch, curvature, direction
        """
        r_curvature = np.sqrt((center_x_spp - center_x)**2 +
                              (center_y_spp - center_y)**2)
        direction = np.arctan2(center_y - center_y_spp,
                               center_x - center_x_spp)
        tangential_stretch = 1 / (1 - (theta_E / r_curvature)**(gamma - 1))
        radial_stretch = 1 / (1 + (gamma - 2) *
                              (theta_E / r_curvature)**(gamma - 1))
        curvature = 1. / r_curvature
        return tangential_stretch, radial_stretch, curvature, direction

    def function(self, x, y, tangential_stretch, radial_stretch, curvature,
                 direction, center_x, center_y):
        """
        ATTENTION: there may not be a global lensing potential!

        :param x:
        :param y:
        :param tangential_stretch: float, stretch of intrinsic source in tangential direction
        :param radial_stretch: float, stretch of intrinsic source in radial direction
        :param curvature: 1/curvature radius
        :param direction: float, angle in radian
        :param center_x: center of source in image plane
        :param center_y: center of source in image plane
        :return:
        """
        theta_E, gamma, center_x_spp, center_y_spp = self.stretch2spp(
            tangential_stretch, radial_stretch, curvature, direction, center_x,
            center_y)
        f_ = self._spp.function(x, y, theta_E, gamma, center_x_spp,
                                center_y_spp)
        alpha_x, alpha_y = self._spp.derivatives(center_x, center_y, theta_E,
                                                 gamma, center_x_spp,
                                                 center_y_spp)
        f_0 = alpha_x * (x - center_x) + alpha_y * (y - center_y)
        return f_ - f_0

    def derivatives(self, x, y, tangential_stretch, radial_stretch, curvature,
                    direction, center_x, center_y):
        """

        :param x:
        :param y:
        :param tangential_stretch: float, stretch of intrinsic source in tangential direction
        :param radial_stretch: float, stretch of intrinsic source in radial direction
        :param curvature: 1/curvature radius
        :param direction: float, angle in radian
        :param center_x: center of source in image plane
        :param center_y: center of source in image plane
        :return:
        """
        theta_E, gamma, center_x_spp, center_y_spp = self.stretch2spp(
            tangential_stretch, radial_stretch, curvature, direction, center_x,
            center_y)
        f_x, f_y = self._spp.derivatives(x, y, theta_E, gamma, center_x_spp,
                                         center_y_spp)
        f_x0, f_y0 = self._spp.derivatives(center_x, center_y, theta_E, gamma,
                                           center_x_spp, center_y_spp)
        return f_x - f_x0, f_y - f_y0

    def hessian(self, x, y, tangential_stretch, radial_stretch, curvature,
                direction, center_x, center_y):
        """

        :param x:
        :param y:
        :param tangential_stretch: float, stretch of intrinsic source in tangential direction
        :param radial_stretch: float, stretch of intrinsic source in radial direction
        :param curvature: 1/curvature radius
        :param direction: float, angle in radian
        :param center_x: center of source in image plane
        :param center_y: center of source in image plane
        :return:
        """
        theta_E, gamma, center_x_spp, center_y_spp = self.stretch2spp(
            tangential_stretch, radial_stretch, curvature, direction, center_x,
            center_y)
        return self._spp.hessian(x, y, theta_E, gamma, center_x_spp,
                                 center_y_spp)
Beispiel #26
0
class EPL(LensProfileBase):
    """"
    Elliptical Power Law mass profile

    .. math::
        \\kappa(x, y) = \\frac{3-\\gamma}{2} \\left(\\frac{\\theta_{E}}{\\sqrt{q x^2 + y^2/q}} \\right)^{\\gamma-1}

    with :math:`\\theta_{E}` is the (circularized) Einstein radius,
    :math:`\\gamma` is the negative power-law slope of the 3D mass distributions,
    :math:`q` is the minor/major axis ratio,
    and :math:`x` and :math:`y` are defined in a coordinate sys- tem aligned with the major and minor axis of the lens.

    In terms of eccentricities, this profile is defined as

    .. math::
        \\kappa(r) = \\frac{3-\\gamma}{2} \\left(\\frac{\\theta'_{E}}{r \\sqrt{1 − e*\\cos(2*\\phi)}} \\right)^{\\gamma-1}

    with :math:`\\epsilon` is the ellipticity defined as

    .. math::
        \\epsilon = \\frac{1-q^2}{1+q^2}

    And an Einstein radius :math:`\\theta'_{\\rm E}` related to the definition used is

    .. math::
        \\left(\\frac{\\theta'_{\\rm E}}{\\theta_{\\rm E}}\\right)^{2} = \\frac{2q}{1+q^2}.

    The mathematical form of the calculation is presented by Tessore & Metcalf (2015), https://arxiv.org/abs/1507.01819.
    The current implementation is using hyperbolic functions. The paper presents an iterative calculation scheme,
    converging in few iterations to high precision and accuracy.

    A (faster) implementation of the same model using numba is accessible as 'EPL_NUMBA' with the iterative calculation
    scheme.
    """
    param_names = ['theta_E', 'gamma', 'e1', 'e2', 'center_x', 'center_y']
    lower_limit_default = {
        'theta_E': 0,
        'gamma': 1.5,
        'e1': -0.5,
        'e2': -0.5,
        'center_x': -100,
        'center_y': -100
    }
    upper_limit_default = {
        'theta_E': 100,
        'gamma': 2.5,
        'e1': 0.5,
        'e2': 0.5,
        'center_x': 100,
        'center_y': 100
    }

    def __init__(self):
        self.epl_major_axis = EPLMajorAxis()
        self.spp = SPP()
        super(EPL, self).__init__()

    def param_conv(self, theta_E, gamma, e1, e2):
        """
        converts parameters as defined in this class to the parameters used in the EPLMajorAxis() class

        :param theta_E: Einstein radius as defined in the profile class
        :param gamma: negative power-law slope
        :param e1: eccentricity modulus
        :param e2: eccentricity modulus

        :return: b, t, q, phi_G
        """
        if self._static is True:
            return self._b_static, self._t_static, self._q_static, self._phi_G_static
        return self._param_conv(theta_E, gamma, e1, e2)

    @staticmethod
    def _param_conv(theta_E, gamma, e1, e2):
        """
        convert parameters from :math:`R = \\sqrt{q x^2 + y^2/q}` to
        :math:`R = \\sqrt{q^2 x^2 + y^2}`

        :param gamma: power law slope
        :param theta_E: Einstein radius
        :param e1: eccentricity component
        :param e2: eccentricity component
        :return: critical radius b, slope t, axis ratio q, orientation angle phi_G
        """
        t = gamma - 1
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        b = theta_E * np.sqrt(q)
        return b, t, q, phi_G

    def set_static(self, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """

        :param theta_E: Einstein radius
        :param gamma: power law slope
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: profile center
        :param center_y: profile center
        :return: self variables set
        """
        self._static = True
        self._b_static, self._t_static, self._q_static, self._phi_G_static = self._param_conv(
            theta_E, gamma, e1, e2)

    def set_dynamic(self):
        """

        :return:
        """
        self._static = False
        if hasattr(self, '_b_static'):
            del self._b_static
        if hasattr(self, '_t_static'):
            del self._t_static
        if hasattr(self, '_phi_G_static'):
            del self._phi_G_static
        if hasattr(self, '_q_static'):
            del self._q_static

    def function(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """

        :param x: x-coordinate in image plane
        :param y: y-coordinate in image plane
        :param theta_E: Einstein radius
        :param gamma: power law slope
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: profile center
        :param center_y: profile center
        :return: lensing potential
        """
        b, t, q, phi_G = self.param_conv(theta_E, gamma, e1, e2)
        # shift
        x_ = x - center_x
        y_ = y - center_y
        # rotate
        x__, y__ = util.rotate(x_, y_, phi_G)
        # evaluate
        f_ = self.epl_major_axis.function(x__, y__, b, t, q)
        # rotate back
        return f_

    def derivatives(self,
                    x,
                    y,
                    theta_E,
                    gamma,
                    e1,
                    e2,
                    center_x=0,
                    center_y=0):
        """

        :param x: x-coordinate in image plane
        :param y: y-coordinate in image plane
        :param theta_E: Einstein radius
        :param gamma: power law slope
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: profile center
        :param center_y: profile center
        :return: alpha_x, alpha_y
        """
        b, t, q, phi_G = self.param_conv(theta_E, gamma, e1, e2)
        # shift
        x_ = x - center_x
        y_ = y - center_y
        # rotate
        x__, y__ = util.rotate(x_, y_, phi_G)
        # evaluate
        f__x, f__y = self.epl_major_axis.derivatives(x__, y__, b, t, q)
        # rotate back
        f_x, f_y = util.rotate(f__x, f__y, -phi_G)
        return f_x, f_y

    def hessian(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """

        :param x: x-coordinate in image plane
        :param y: y-coordinate in image plane
        :param theta_E: Einstein radius
        :param gamma: power law slope
        :param e1: eccentricity component
        :param e2: eccentricity component
        :param center_x: profile center
        :param center_y: profile center
        :return: f_xx, f_xy, f_yx, f_yy
        """

        b, t, q, phi_G = self.param_conv(theta_E, gamma, e1, e2)
        # shift
        x_ = x - center_x
        y_ = y - center_y
        # rotate
        x__, y__ = util.rotate(x_, y_, phi_G)
        # evaluate
        f__xx, f__xy, f__yx, f__yy = self.epl_major_axis.hessian(
            x__, y__, b, t, q)
        # rotate back
        kappa = 1. / 2 * (f__xx + f__yy)
        gamma1__ = 1. / 2 * (f__xx - f__yy)
        gamma2__ = f__xy
        gamma1 = np.cos(2 * phi_G) * gamma1__ - np.sin(2 * phi_G) * gamma2__
        gamma2 = +np.sin(2 * phi_G) * gamma1__ + np.cos(2 * phi_G) * gamma2__
        f_xx = kappa + gamma1
        f_yy = kappa - gamma1
        f_xy = gamma2
        return f_xx, f_xy, f_xy, f_yy

    def mass_3d_lens(self, r, theta_E, gamma, e1=None, e2=None):
        """
        computes the spherical power-law mass enclosed (with SPP routine)
        :param r: radius within the mass is computed
        :param theta_E: Einstein radius
        :param gamma: power-law slope
        :param e1: eccentricity component (not used)
        :param e2: eccentricity component (not used)
        :return: mass enclosed a 3D radius r
        """
        return self.spp.mass_3d_lens(r, theta_E, gamma)

    def density_lens(self, r, theta_E, gamma, e1=None, e2=None):
        """
        computes the density at 3d radius r given lens model parameterization.
        The integral in the LOS projection of this quantity results in the convergence quantity.

        :param r: radius within the mass is computed
        :param theta_E: Einstein radius
        :param gamma: power-law slope
        :param e1: eccentricity component (not used)
        :param e2: eccentricity component (not used)
        :return: mass enclosed a 3D radius r
        """
        return self.spp.density_lens(r, theta_E, gamma)
Beispiel #27
0
 def __init__(self):
     self.spp = SPP()
     super(SPEP, self).__init__()
Beispiel #28
0
    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))
    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)
Beispiel #30
0
class TestCurvedArc(object):
    """
    tests the source model routines
    """
    def setup(self):
        self.model = CurvedArc()
        self.spp = SPP()

    def test_spp2stretch(self):
        center_x, center_y = 1, 1
        theta_E = 1
        gamma = 1.9
        center_x_spp, center_y_spp = 0., 0

        tangential_stretch, radial_stretch, curvature, direction = self.model.spp2stretch(
            theta_E, gamma, center_x_spp, center_y_spp, center_x, center_y)
        theta_E_new, gamma_new, center_x_spp_new, center_y_spp_new = self.model.stretch2spp(
            tangential_stretch, radial_stretch, curvature, direction, center_x,
            center_y)
        npt.assert_almost_equal(center_x_spp_new, center_x_spp, decimal=8)
        npt.assert_almost_equal(center_y_spp_new, center_y_spp, decimal=8)
        npt.assert_almost_equal(theta_E_new, theta_E, decimal=8)
        npt.assert_almost_equal(gamma_new, gamma, decimal=8)

        center_x, center_y = -1, 1
        tangential_stretch, radial_stretch, curvature, direction = self.model.spp2stretch(
            theta_E, gamma, center_x_spp, center_y_spp, center_x, center_y)
        theta_E_new, gamma_new, center_x_spp_new, center_y_spp_new = self.model.stretch2spp(
            tangential_stretch, radial_stretch, curvature, direction, center_x,
            center_y)
        npt.assert_almost_equal(center_x_spp_new, center_x_spp, decimal=8)
        npt.assert_almost_equal(center_y_spp_new, center_y_spp, decimal=8)
        npt.assert_almost_equal(theta_E_new, theta_E, decimal=8)
        npt.assert_almost_equal(gamma_new, gamma, decimal=8)

        center_x, center_y = 0, 0.5
        tangential_stretch, radial_stretch, curvature, direction = self.model.spp2stretch(
            theta_E, gamma, center_x_spp, center_y_spp, center_x, center_y)
        theta_E_new, gamma_new, center_x_spp_new, center_y_spp_new = self.model.stretch2spp(
            tangential_stretch, radial_stretch, curvature, direction, center_x,
            center_y)
        npt.assert_almost_equal(center_x_spp_new, center_x_spp, decimal=8)
        npt.assert_almost_equal(center_y_spp_new, center_y_spp, decimal=8)
        npt.assert_almost_equal(theta_E_new, theta_E, decimal=8)
        npt.assert_almost_equal(gamma_new, gamma, decimal=8)

        center_x, center_y = 0, -1.5
        tangential_stretch, radial_stretch, r_curvature, direction = self.model.spp2stretch(
            theta_E, gamma, center_x_spp, center_y_spp, center_x, center_y)
        print(tangential_stretch, radial_stretch, r_curvature, direction)
        theta_E_new, gamma_new, center_x_spp_new, center_y_spp_new = self.model.stretch2spp(
            tangential_stretch, radial_stretch, r_curvature, direction,
            center_x, center_y)
        npt.assert_almost_equal(center_x_spp_new, center_x_spp, decimal=8)
        npt.assert_almost_equal(center_y_spp_new, center_y_spp, decimal=8)
        npt.assert_almost_equal(theta_E_new, theta_E, decimal=8)
        npt.assert_almost_equal(gamma_new, gamma, decimal=8)

    def test_function(self):
        center_x, center_y = 0., 0.
        x, y = 1, 1
        output = self.model.function(x,
                                     y,
                                     tangential_stretch=2,
                                     radial_stretch=1,
                                     curvature=1. / 2,
                                     direction=0,
                                     center_x=0,
                                     center_y=0)
        theta_E, gamma, center_x_spp, center_y_spp = self.model.stretch2spp(
            tangential_stretch=2,
            radial_stretch=1,
            curvature=1. / 2,
            direction=0,
            center_x=0,
            center_y=0)
        out_spp = self.spp.function(1, 1, theta_E, gamma, center_x_spp,
                                    center_y_spp)
        alpha_x, alpha_y = self.spp.derivatives(center_x, center_y, theta_E,
                                                gamma, center_x_spp,
                                                center_y_spp)
        f_0 = alpha_x * (x - center_x) + alpha_y * (y - center_y)

        npt.assert_almost_equal(output, out_spp - f_0, decimal=8)

    def test_derivatives(self):
        tangential_stretch = 5
        radial_stretch = 1
        curvature = 1. / 10
        direction = 0.3
        center_x = 0
        center_y = 0
        x, y = 1, 1
        theta_E, gamma, center_x_spp, center_y_spp = self.model.stretch2spp(
            tangential_stretch, radial_stretch, curvature, direction, center_x,
            center_y)
        f_x, f_y = self.spp.derivatives(x, y, theta_E, gamma, center_x_spp,
                                        center_y_spp)
        f_x0, f_y0 = self.spp.derivatives(center_x, center_y, theta_E, gamma,
                                          center_x_spp, center_y_spp)
        f_x_new, f_y_new = self.model.derivatives(x, y, tangential_stretch,
                                                  radial_stretch, curvature,
                                                  direction, center_x,
                                                  center_y)
        npt.assert_almost_equal(f_x_new, f_x - f_x0, decimal=8)
        npt.assert_almost_equal(f_y_new, f_y - f_y0, decimal=8)

    def test_hessian(self):
        lens = LensModel(lens_model_list=['CURVED_ARC'])
        center_x, center_y = 0, 0
        tangential_stretch = 10
        radial_stretch = 1
        kwargs_lens = [{
            'tangential_stretch': tangential_stretch,
            'radial_stretch': radial_stretch,
            'curvature': 1. / 10.5,
            'direction': 0.,
            'center_x': center_x,
            'center_y': center_y
        }]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag,
                                tangential_stretch * radial_stretch,
                                decimal=8)

        center_x, center_y = 2, 3
        tangential_stretch = 10
        radial_stretch = 1
        kwargs_lens = [{
            'tangential_stretch': tangential_stretch,
            'radial_stretch': radial_stretch,
            'curvature': 1. / 10.5,
            'direction': 0.,
            'center_x': center_x,
            'center_y': center_y
        }]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag,
                                tangential_stretch * radial_stretch,
                                decimal=8)

        center_x, center_y = 0, 0
        tangential_stretch = 3
        radial_stretch = -1
        kwargs_lens = [{
            'tangential_stretch': tangential_stretch,
            'radial_stretch': radial_stretch,
            'curvature': 1. / 10.5,
            'direction': 0.,
            'center_x': center_x,
            'center_y': center_y
        }]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag,
                                tangential_stretch * radial_stretch,
                                decimal=8)

        center_x, center_y = 0, 0
        tangential_stretch = -3
        radial_stretch = -1
        kwargs_lens = [{
            'tangential_stretch': tangential_stretch,
            'radial_stretch': radial_stretch,
            'curvature': 1. / 10.5,
            'direction': 0.,
            'center_x': center_x,
            'center_y': center_y
        }]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag,
                                tangential_stretch * radial_stretch,
                                decimal=8)

        center_x, center_y = 0, 0
        tangential_stretch = 10.4
        radial_stretch = 0.6
        kwargs_lens = [{
            'tangential_stretch': tangential_stretch,
            'radial_stretch': radial_stretch,
            'curvature': 1. / 10.5,
            'direction': 0.,
            'center_x': center_x,
            'center_y': center_y
        }]
        mag = lens.magnification(center_x, center_y, kwargs=kwargs_lens)
        npt.assert_almost_equal(mag,
                                tangential_stretch * radial_stretch,
                                decimal=8)