Exemplo n.º 1
0
class PowerLawSubhalo(Halo):
    """
    The base class for a halo modeled as a power law profile
    """
    def __init__(self, mass, x, y, r3d, mdef, z, sub_flag, lens_cosmo_instance,
                 args, unique_tag):
        """
        See documentation in base class (Halos/halo_base.py)
        """
        self._prof = SPLCORE()
        self._lens_cosmo = lens_cosmo_instance
        super(PowerLawSubhalo,
              self).__init__(mass, x, y, r3d, mdef, z, sub_flag,
                             lens_cosmo_instance, args, unique_tag)

    @property
    def params_physical(self):
        """
        See documentation in base class (Halos/halo_base.py)
        """

        if not hasattr(self, '_params_physical'):
            (concentration, gamma, x_core_halo) = self.profile_args
            rhos, rs, _ = self._lens_cosmo.NFW_params_physical(
                self.mass, concentration, self.z)
            kpc_per_arcsec = self._lens_cosmo.cosmo.kpc_proper_per_asec(self.z)

            if 'x_match' in self._args.keys():
                x_match = self._args['x_match']
            else:
                # r_vmax = 2.16 * rs
                x_match = 2.16

            r_match_arcsec = x_match * rs / kpc_per_arcsec
            fx = np.log(1 + x_match) - x_match / (1 + x_match)
            m = 4 * np.pi * rs**3 * rhos * fx
            r_core_arcsec = x_core_halo * r_match_arcsec / x_match

            sigma_crit_mpc = self._lens_cosmo.get_sigma_crit_lensing(
                self.z, self._lens_cosmo.z_source)
            sigma_crit_arcsec = sigma_crit_mpc * (0.001 * kpc_per_arcsec)**2

            rho0 = m / self._prof.mass_3d(r_match_arcsec, sigma_crit_arcsec,
                                          r_core_arcsec, gamma)
            # units 1 / arcsec

            rho0 *= sigma_crit_arcsec * kpc_per_arcsec**-3
            self._params_physical = {'rho0': rho0, 'r_core': x_core_halo * rs}

        return self._params_physical

    @property
    def lenstronomy_params(self):
        """
        See documentation in base class (Halos/halo_base.py)
        """
        if not hasattr(self, '_lenstronomy_args'):

            (concentration, gamma, x_core_halo) = self.profile_args
            rhos, rs, _ = self._lens_cosmo.NFW_params_physical(
                self.mass, concentration, self.z)
            kpc_per_arcsec = self._lens_cosmo.cosmo.kpc_proper_per_asec(self.z)

            if 'x_match' in self._args.keys():
                x_match = self._args['x_match']
            else:
                # r_vmax = 2.16 * rs
                x_match = 2.16

            r_match_arcsec = x_match * rs / kpc_per_arcsec
            fx = np.log(1 + x_match) - x_match / (1 + x_match)
            m = 4 * np.pi * rs**3 * rhos * fx
            r_core_arcsec = x_core_halo * r_match_arcsec / x_match

            sigma_crit_mpc = self._lens_cosmo.get_sigma_crit_lensing(
                self.z, self._lens_cosmo.z_source)
            sigma_crit_arcsec = sigma_crit_mpc * (0.001 * kpc_per_arcsec)**2

            rho0 = m / self._prof.mass_3d(r_match_arcsec, sigma_crit_arcsec,
                                          r_core_arcsec, gamma)
            sigma0 = rho0 * r_core_arcsec

            self._lenstronomy_args = [{
                'sigma0': sigma0,
                'gamma': gamma,
                'center_x': self.x,
                'center_y': self.y,
                'r_core': r_core_arcsec
            }]

        return self._lenstronomy_args, None

    @property
    def lenstronomy_ID(self):
        """
        See documentation in base class (Halos/halo_base.py)
        """
        return ['SPL_CORE']

    @property
    def profile_args(self):
        """
        See documentation in base class (Halos/halo_base.py)
        """
        if not hasattr(self, '_profile_args'):

            if self._args['evaluate_mc_at_zlens']:
                z_eval = self.z
            else:
                z_eval = self.z_infall

            concentration = self._lens_cosmo.NFW_concentration(
                self.mass, z_eval, self._args['mc_model'],
                self._args['mc_mdef'], self._args['log_mc'],
                self._args['c_scatter'], self._args['c_scatter_dex'],
                self._args['kwargs_suppression'],
                self._args['suppression_model'])

            gamma = self._args['log_slope_halo']
            x_core_halo = self._args['x_core_halo']
            self._profile_args = (concentration, gamma, x_core_halo)

        return self._profile_args
Exemplo n.º 2
0
class TestSPLCORE(object):
    def setup(self):

        self.profile = SPLCORE()

    def test_no_potential(self):

        npt.assert_raises(Exception, self.profile.function, 0., 0., 0., 0., 0.)

    def test_origin(self):

        x = 0.
        y = 0.
        sigma0 = 1.
        r_core = 0.1
        gamma = 2.4
        alpha_x, alpha_y = self.profile.derivatives(x, y, sigma0, r_core,
                                                    gamma)
        npt.assert_almost_equal(alpha_x, 0.)
        npt.assert_almost_equal(alpha_y, 0.)

        fxx, fyy, fxy = self.profile.hessian(x, y, sigma0, r_core, gamma)
        kappa = self.profile.density_2d(x, y, sigma0 / r_core, r_core, gamma)
        npt.assert_almost_equal(fxx, kappa)
        npt.assert_almost_equal(fyy, kappa)
        npt.assert_almost_equal(fxy, 0.)

        r = 0.01
        xmin = 0.001
        rmin = self.profile._safe_r_division(r, 1., xmin)
        npt.assert_equal(rmin, r)

        r = 1e-9
        rmin = self.profile._safe_r_division(r, 1., xmin)
        npt.assert_equal(rmin, xmin)

        xmin = 1e-2
        r = np.logspace(-3, 0, 100)
        inds = np.where(r < xmin)
        rmin = self.profile._safe_r_division(r, 1., xmin)
        npt.assert_almost_equal(rmin[inds], xmin)

    def test_g_function(self):

        gamma = 2.5
        rc = 0.01
        rho0 = 1.
        R = 5.

        args = (rho0, rc, gamma)
        mass_numerical = quad(self._mass_integrand3d, 0, R, args=args)[0]
        mass_analytic = self.profile.mass_3d(R, rho0, rc, gamma)
        npt.assert_almost_equal(mass_analytic, mass_numerical)

        gamma = 2.
        args = (rho0, rc, gamma)
        mass_numerical = quad(self._mass_integrand3d, 0, R, args=args)[0]
        mass_analytic = self.profile.mass_3d(R, rho0, rc, gamma)
        npt.assert_almost_equal(mass_analytic, mass_numerical)

        gamma = 3.
        args = (rho0, rc, gamma)
        mass_numerical = quad(self._mass_integrand3d, 0, R, args=args)[0]
        mass_analytic = self.profile.mass_3d(R, rho0, rc, gamma)
        npt.assert_almost_equal(mass_analytic, mass_numerical)

        gamma = 1.4
        args = (rho0, rc, gamma)
        mass_numerical = quad(self._mass_integrand3d, 0, R, args=args)[0]
        mass_analytic = self.profile.mass_3d(R, rho0, rc, gamma)
        npt.assert_almost_equal(mass_analytic, mass_numerical)
        sigma0 = rho0 * rc
        mass_analytic_from_sigm0 = self.profile.mass_3d_lens(
            R, sigma0, rc, gamma)
        npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical)

    def test_f_function(self):

        gamma = 2.5
        rc = 0.01
        rho0 = 1.
        R = 5.

        args = (rho0, rc, gamma)
        mass_numerical = quad(self._mass_integrand2d, 0, R, args=args)[0]
        mass_analytic = self.profile.mass_2d(R, rho0, rc, gamma)
        npt.assert_almost_equal(mass_analytic, mass_numerical)
        sigma0 = rho0 * rc
        mass_analytic_from_sigm0 = self.profile.mass_2d_lens(
            R, sigma0, rc, gamma)
        npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical)

        gamma = 2.
        args = (rho0, rc, gamma)
        mass_numerical = quad(self._mass_integrand2d, 0, R, args=args)[0]
        mass_analytic = self.profile.mass_2d(R, rho0, rc, gamma)
        npt.assert_almost_equal(mass_analytic, mass_numerical)
        sigma0 = rho0 * rc
        mass_analytic_from_sigm0 = self.profile.mass_2d_lens(
            R, sigma0, rc, gamma)
        npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical)

        gamma = 3.
        args = (rho0, rc, gamma)
        mass_numerical = quad(self._mass_integrand2d, 0, R, args=args)[0]
        mass_analytic = self.profile.mass_2d(R, rho0, rc, gamma)
        npt.assert_almost_equal(mass_analytic, mass_numerical)
        sigma0 = rho0 * rc
        mass_analytic_from_sigm0 = self.profile.mass_2d_lens(
            R, sigma0, rc, gamma)
        npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical)

        gamma = 1.4
        args = (rho0, rc, gamma)
        mass_numerical = quad(self._mass_integrand2d, 0, R, args=args)[0]
        mass_analytic = self.profile.mass_2d(R, rho0, rc, gamma)
        npt.assert_almost_equal(mass_analytic, mass_numerical)
        sigma0 = rho0 * rc
        mass_analytic_from_sigm0 = self.profile.mass_2d_lens(
            R, sigma0, rc, gamma)
        npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical)

    def _mass_integrand3d(self, r, rho0, rc, gamma):
        return 4 * np.pi * r**2 * rho0 * rc**gamma / (rc**2 + r**2)**(gamma /
                                                                      2)

    def _mass_integrand2d(self, r, rho0, rc, gamma):
        return 2 * np.pi * r * self.profile.density_2d(r, 0, rho0, rc, gamma)