Exemplo n.º 1
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)
Exemplo n.º 2
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)
Exemplo n.º 3
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)
Exemplo n.º 4
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)