class SersicEllipse(LensProfileBase):
    """
    this class contains functions to evaluate a Sersic mass profile: https://arxiv.org/pdf/astro-ph/0311559.pdf
    """
    param_names = ['k_eff', 'R_sersic', 'n_sersic', 'e1', 'e2', 'center_x', 'center_y']
    lower_limit_default = {'k_eff': 0, 'R_sersic': 0, 'n_sersic': 0.5, 'e1': -0.5, 'e2': -0.5, 'center_x': -100, 'center_y': -100}
    upper_limit_default = {'k_eff': 10, 'R_sersic': 100, 'n_sersic': 8, 'e1': 0.5, 'e2': 0.5, 'center_x': 100, 'center_y': 100}

    def __init__(self):
        self.sersic = Sersic()
        self._diff = 0.000001
        super(SersicEllipse, self).__init__()

    def function(self, x, y, n_sersic, R_sersic, k_eff, e1, e2, center_x=0, center_y=0):
        """
        returns Gaussian
        """
        # phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        x_, y_ = param_util.transform_e1e2_square_average(x, y, e1, e2, center_x, center_y)
        # x_, y_ = self._coord_transf(x, y, q, phi_G, center_x, center_y)
        f_ = self.sersic.function(x_, y_, n_sersic, R_sersic, k_eff)
        return f_

    def derivatives(self, x, y, n_sersic, R_sersic, k_eff, e1, e2, center_x=0, center_y=0):
        """
        returns df/dx and df/dy of the function
        """
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        e = param_util.q2e(q)
        # e = abs(1. - q)
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)
        x_, y_ = param_util.transform_e1e2_square_average(x, y, e1, e2, center_x, center_y)
        # x_, y_ = self._coord_transf(x, y, q, phi_G, center_x, center_y)
        f_x_prim, f_y_prim = self.sersic.derivatives(x_, y_, n_sersic, R_sersic, k_eff)
        f_x_prim *= np.sqrt(1 - e)
        f_y_prim *= np.sqrt(1 + e)
        f_x = cos_phi*f_x_prim-sin_phi*f_y_prim
        f_y = sin_phi*f_x_prim+cos_phi*f_y_prim
        return f_x, f_y

    def hessian(self, x, y, n_sersic, R_sersic, k_eff, e1, e2, center_x=0, center_y=0):
        """
        returns Hessian matrix of function d^2f/dx^2, d^2/dxdy, d^2/dydx, d^f/dy^2
        """
        alpha_ra, alpha_dec = self.derivatives(x, y, n_sersic, R_sersic, k_eff, e1, e2, center_x, center_y)
        diff = self._diff
        alpha_ra_dx, alpha_dec_dx = self.derivatives(x + diff, y, n_sersic, R_sersic, k_eff, e1, e2, center_x, center_y)
        alpha_ra_dy, alpha_dec_dy = self.derivatives(x, y + diff, n_sersic, R_sersic, k_eff, e1, e2, center_x, center_y)

        f_xx = (alpha_ra_dx - alpha_ra)/diff
        f_xy = (alpha_ra_dy - alpha_ra)/diff
        f_yx = (alpha_dec_dx - alpha_dec)/diff
        f_yy = (alpha_dec_dy - alpha_dec)/diff

        return f_xx, f_xy, f_yx, f_yy
Example #2
0
    def test_sersic(self):
        from lenstronomy.LensModel.Profiles.sersic import Sersic
        from lenstronomy.LightModel.Profiles.sersic import Sersic as SersicLight
        sersic_lens = Sersic()
        sersic_light = SersicLight()
        kwargs_light = {
            'n_sersic': 2,
            'R_sersic': 0.5,
            'I0_sersic': 1,
            'center_x': 0,
            'center_y': 0
        }
        kwargs_lens = {
            'n_sersic': 2,
            'R_sersic': 0.5,
            'k_eff': 1,
            'center_x': 0,
            'center_y': 0
        }
        deltaPix = 0.01
        numPix = 1000
        x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix)
        x_grid2d = util.array2image(x_grid)
        y_grid2d = util.array2image(y_grid)

        f_xx, f_yy, _ = sersic_lens.hessian(x_grid, y_grid, **kwargs_lens)
        f_x, f_y = sersic_lens.derivatives(x_grid, y_grid, **kwargs_lens)
        f_x = util.array2image(f_x)
        kappa = util.array2image((f_xx + f_yy) / 2.)
        f_x_num, f_y_num = convergence_integrals.deflection_from_kappa_grid(
            kappa, deltaPix)
        x1, y1 = 500, 550
        x0, y0 = int(numPix / 2.), int(numPix / 2.)
        npt.assert_almost_equal(f_x[x1, y1], f_x_num[x1, y1], decimal=2)
        f_num = convergence_integrals.potential_from_kappa_grid(
            kappa, deltaPix)
        f_ = sersic_lens.function(x_grid2d[x1, y1], y_grid2d[x1, y1],
                                  **kwargs_lens)
        f_00 = sersic_lens.function(x_grid2d[x0, y0], y_grid2d[x0, y0],
                                    **kwargs_lens)
        npt.assert_almost_equal(f_ - f_00,
                                f_num[x1, y1] - f_num[x0, y0],
                                decimal=2)
Example #3
0
class SersicEllipse(object):
    """
    this class contains functions to evaluate a Sersic mass profile: https://arxiv.org/pdf/astro-ph/0311559.pdf
    """
    def __init__(self):
        self.sersic = Sersic()
        self._diff = 0.000001

    def function(self,
                 x,
                 y,
                 n_sersic,
                 r_eff,
                 k_eff,
                 q,
                 phi_G,
                 center_x=0,
                 center_y=0):
        """
        returns Gaussian
        """
        x_, y_ = self._coord_transf(x, y, q, phi_G, center_x, center_y)
        f_ = self.sersic.function(x_, y_, n_sersic, r_eff, k_eff)
        return f_

    def derivatives(self,
                    x,
                    y,
                    n_sersic,
                    r_eff,
                    k_eff,
                    q,
                    phi_G,
                    center_x=0,
                    center_y=0):
        """
        returns df/dx and df/dy of the function
        """
        e = abs(1. - q)
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)
        x_, y_ = self._coord_transf(x, y, q, phi_G, center_x, center_y)
        f_x_prim, f_y_prim = self.sersic.derivatives(x_, y_, n_sersic, r_eff,
                                                     k_eff)
        f_x_prim *= np.sqrt(1 - e)
        f_y_prim *= np.sqrt(1 + e)
        f_x = cos_phi * f_x_prim - sin_phi * f_y_prim
        f_y = sin_phi * f_x_prim + cos_phi * f_y_prim
        return f_x, f_y

    def hessian(self,
                x,
                y,
                n_sersic,
                r_eff,
                k_eff,
                q,
                phi_G,
                center_x=0,
                center_y=0):
        """
        returns Hessian matrix of function d^2f/dx^2, d^f/dy^2, d^2/dxdy
        """
        alpha_ra, alpha_dec = self.derivatives(x, y, n_sersic, r_eff, k_eff, q,
                                               phi_G, center_x, center_y)
        diff = self._diff
        alpha_ra_dx, alpha_dec_dx = self.derivatives(x + diff, y, n_sersic,
                                                     r_eff, k_eff, q, phi_G,
                                                     center_x, center_y)
        alpha_ra_dy, alpha_dec_dy = self.derivatives(x, y + diff, n_sersic,
                                                     r_eff, k_eff, q, phi_G,
                                                     center_x, center_y)

        f_xx = (alpha_ra_dx - alpha_ra) / diff
        f_xy = (alpha_ra_dy - alpha_ra) / diff
        f_yx = (alpha_dec_dx - alpha_dec) / diff
        f_yy = (alpha_dec_dy - alpha_dec) / diff

        return f_xx, f_yy, f_xy

    def _coord_transf(self, x, y, q, phi_G, center_x, center_y):
        """

        :param x:
        :param y:
        :param q:
        :param phi_G:
        :param center_x:
        :param center_y:
        :return:
        """
        x_shift = x - center_x
        y_shift = y - center_y
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)
        e = abs(1 - q)
        x_ = (cos_phi * x_shift + sin_phi * y_shift) * np.sqrt(1 - e)
        y_ = (-sin_phi * x_shift + cos_phi * y_shift) * np.sqrt(1 + e)
        return x_, y_
Example #4
0
class TestSersic(object):
    """
    tests the Gaussian methods
    """
    def setup(self):

        self.sersic_2 = SersicEllipseKappa()
        self.sersic = Sersic()
        self.sersic_light = Sersic_light()

    def test_function(self):

        x = 1
        y = 2
        n_sersic = 2.
        R_sersic = 1.
        k_eff = 0.2
        values = self.sersic.function(x, y, n_sersic, R_sersic, k_eff)
        npt.assert_almost_equal(values, 1.0272982586319199, decimal=10)

        x = np.array([0])
        y = np.array([0])
        values = self.sersic.function(x, y, n_sersic, R_sersic, k_eff)
        npt.assert_almost_equal(values[0], 0., decimal=9)

        x = np.array([2, 3, 4])
        y = np.array([1, 1, 1])
        values = self.sersic.function(x, y, n_sersic, R_sersic, k_eff)

        npt.assert_almost_equal(values[0], 1.0272982586319199, decimal=10)
        npt.assert_almost_equal(values[1], 1.3318743892966658, decimal=10)
        npt.assert_almost_equal(values[2], 1.584299393114988, decimal=10)

    def test_derivatives(self):
        x = np.array([1])
        y = np.array([2])
        n_sersic = 2.
        R_sersic = 1.
        k_eff = 0.2
        f_x, f_y = self.sersic.derivatives(x, y, n_sersic, R_sersic, k_eff)
        f_x2, f_y2 = self.sersic_2.derivatives(x, y, n_sersic, R_sersic, k_eff,
                                               0, 0.00000001)

        assert f_x[0] == 0.16556078301997193
        assert f_y[0] == 0.33112156603994386
        npt.assert_almost_equal(f_x2[0], f_x[0])
        npt.assert_almost_equal(f_y2[0], f_y[0])

        x = np.array([0])
        y = np.array([0])
        f_x, f_y = self.sersic.derivatives(x, y, n_sersic, R_sersic, k_eff)
        f_x2, f_y2 = self.sersic_2.derivatives(x, y, n_sersic, R_sersic, k_eff,
                                               0, 0.00000001)
        assert f_x[0] == 0
        assert f_y[0] == 0
        npt.assert_almost_equal(f_x2[0], f_x[0])
        npt.assert_almost_equal(f_y2[0], f_y[0])

        x = np.array([1, 3, 4])
        y = np.array([2, 1, 1])
        values = self.sersic.derivatives(x, y, n_sersic, R_sersic, k_eff)
        values2 = self.sersic_2.derivatives(x, y, n_sersic, R_sersic, k_eff, 0,
                                            0.00000001)
        assert values[0][0] == 0.16556078301997193
        assert values[1][0] == 0.33112156603994386
        assert values[0][1] == 0.2772992378623737
        assert values[1][1] == 0.092433079287457892
        npt.assert_almost_equal(values2[0][0], values[0][0])
        npt.assert_almost_equal(values2[1][0], values[1][0])
        npt.assert_almost_equal(values2[0][1], values[0][1])
        npt.assert_almost_equal(values2[1][1], values[1][1])

        values2 = self.sersic_2.derivatives(0.3, -0.2, n_sersic, R_sersic,
                                            k_eff, 0, 0.00000001)
        values = self.sersic.derivatives(0.3, -0.2, n_sersic, R_sersic, k_eff,
                                         0, 0.00000001)
        npt.assert_almost_equal(values2[0], values[0])
        npt.assert_almost_equal(values2[1], values[1])

    def test_differentails(self):
        x_, y_ = 1., 1
        n_sersic = 2.
        R_sersic = 1.
        k_eff = 0.2
        r = np.sqrt(x_**2 + y_**2)

        d_alpha_dr = self.sersic.d_alpha_dr(x_, y_, n_sersic, R_sersic, k_eff)
        alpha = self.sersic.alpha_abs(x_, y_, n_sersic, R_sersic, k_eff)

        f_xx_ = d_alpha_dr * calc_util.d_r_dx(
            x_, y_) * x_ / r + alpha * calc_util.d_x_diffr_dx(x_, y_)
        f_yy_ = d_alpha_dr * calc_util.d_r_dy(
            x_, y_) * y_ / r + alpha * calc_util.d_y_diffr_dy(x_, y_)
        f_xy_ = d_alpha_dr * calc_util.d_r_dy(
            x_, y_) * x_ / r + alpha * calc_util.d_x_diffr_dy(x_, y_)

        f_xx = (d_alpha_dr / r - alpha / r**2) * y_**2 / r + alpha / r
        f_yy = (d_alpha_dr / r - alpha / r**2) * x_**2 / r + alpha / r
        f_xy = (d_alpha_dr / r - alpha / r**2) * x_ * y_ / r
        npt.assert_almost_equal(f_xx, f_xx_, decimal=10)
        npt.assert_almost_equal(f_yy, f_yy_, decimal=10)
        npt.assert_almost_equal(f_xy, f_xy_, decimal=10)

    def test_hessian(self):
        x = np.array([1])
        y = np.array([2])
        n_sersic = 2.
        R_sersic = 1.
        k_eff = 0.2
        f_xx, f_xy, f_yx, f_yy = self.sersic.hessian(x, y, n_sersic, R_sersic,
                                                     k_eff)
        assert f_xx[0] == 0.1123170666045793
        npt.assert_almost_equal(f_yy[0], -0.047414082641598576, decimal=10)
        npt.assert_almost_equal(f_xy[0], -0.10648743283078525, decimal=10)
        npt.assert_almost_equal(f_xy, f_yx, decimal=5)
        x = np.array([1, 3, 4])
        y = np.array([2, 1, 1])
        values = self.sersic.hessian(x, y, n_sersic, R_sersic, k_eff)
        assert values[0][0] == 0.1123170666045793
        npt.assert_almost_equal(values[3][0],
                                -0.047414082641598576,
                                decimal=10)
        npt.assert_almost_equal(values[1][0], -0.10648743283078525, decimal=10)
        npt.assert_almost_equal(values[0][1],
                                -0.053273787681591328,
                                decimal=10)
        npt.assert_almost_equal(values[3][1], 0.076243427402007985, decimal=10)
        npt.assert_almost_equal(values[1][1],
                                -0.048568955656349749,
                                decimal=10)

        f_xx2, f_xy2, f_yx2, f_yy2 = self.sersic_2.hessian(
            x, y, n_sersic, R_sersic, k_eff, 0.0000001, 0)
        npt.assert_almost_equal(f_xx2, values[0])
        npt.assert_almost_equal(f_yy2, values[3], decimal=6)
        npt.assert_almost_equal(f_xy2, values[1], decimal=6)
        npt.assert_almost_equal(f_yx2, values[2], decimal=6)

    def test_alpha_abs(self):
        x = 1.
        dr = 0.0000001
        n_sersic = 2.5
        R_sersic = .5
        k_eff = 0.2
        alpha_abs = self.sersic.alpha_abs(x, 0, n_sersic, R_sersic, k_eff)
        f_dr = self.sersic.function(x + dr, 0, n_sersic, R_sersic, k_eff)
        f_ = self.sersic.function(x, 0, n_sersic, R_sersic, k_eff)
        alpha_abs_num = -(f_dr - f_) / dr
        npt.assert_almost_equal(alpha_abs_num, alpha_abs, decimal=3)

    def test_dalpha_dr(self):
        x = 1.
        dr = 0.0000001
        n_sersic = 1.
        R_sersic = .5
        k_eff = 0.2
        d_alpha_dr = self.sersic.d_alpha_dr(x, 0, n_sersic, R_sersic, k_eff)
        alpha_dr = self.sersic.alpha_abs(x + dr, 0, n_sersic, R_sersic, k_eff)
        alpha = self.sersic.alpha_abs(x, 0, n_sersic, R_sersic, k_eff)
        d_alpha_dr_num = (alpha_dr - alpha) / dr
        npt.assert_almost_equal(d_alpha_dr, d_alpha_dr_num, decimal=3)

    def test_mag_sym(self):
        """

        :return:
        """
        r = 2.
        angle1 = 0.
        angle2 = 1.5
        x1 = r * np.cos(angle1)
        y1 = r * np.sin(angle1)

        x2 = r * np.cos(angle2)
        y2 = r * np.sin(angle2)
        n_sersic = 4.5
        R_sersic = 2.5
        k_eff = 0.8
        f_xx1, f_xy1, f_yx1, f_yy1 = self.sersic.hessian(
            x1, y1, n_sersic, R_sersic, k_eff)
        f_xx2, f_xy2, f_yx2, f_yy2 = self.sersic.hessian(
            x2, y2, n_sersic, R_sersic, k_eff)
        kappa_1 = (f_xx1 + f_yy1) / 2
        kappa_2 = (f_xx2 + f_yy2) / 2
        npt.assert_almost_equal(kappa_1, kappa_2, decimal=10)
        A_1 = (1 - f_xx1) * (1 - f_yy1) - f_xy1 * f_yx1
        A_2 = (1 - f_xx2) * (1 - f_yy2) - f_xy2 * f_yx2
        npt.assert_almost_equal(A_1, A_2, decimal=10)

    def test_convergernce(self):
        """
        test the convergence and compares it with the original Sersic profile
        :return:
        """
        x = np.array([0, 0, 0, 0, 0])
        y = np.array([0.5, 1, 1.5, 2, 2.5])
        n_sersic = 4.5
        R_sersic = 2.5
        k_eff = 0.2
        f_xx, f_xy, f_yx, f_yy = self.sersic.hessian(x, y, n_sersic, R_sersic,
                                                     k_eff)
        kappa = (f_xx + f_yy) / 2.
        assert kappa[0] > 0
        flux = self.sersic_light.function(x,
                                          y,
                                          amp=1.,
                                          R_sersic=R_sersic,
                                          n_sersic=n_sersic)
        flux /= flux[0]
        kappa /= kappa[0]
        npt.assert_almost_equal(flux[1], kappa[1], decimal=5)

        xvalues = np.linspace(0.5, 3., 100)

        e1, e2 = 0.4, 0.
        q = ellipticity2phi_q(e1, e2)[1]
        kappa_ellipse = self.sersic_2.projected_mass(xvalues, 0, q, n_sersic,
                                                     R_sersic, k_eff)
        fxx, _, _, fyy = self.sersic_2.hessian(xvalues, 0, n_sersic, R_sersic,
                                               k_eff, e1, e2)

        npt.assert_almost_equal(kappa_ellipse, 0.5 * (fxx + fyy), decimal=5)

    def test_sersic_util(self):
        n = 1.
        Re = 2.
        k, bn = self.sersic.k_bn(n, Re)
        Re_new = self.sersic.k_Re(n, k)
        assert Re == Re_new