def test_draw_cdm(self):

        n = 1
        mtheory = integrate_power_law_analytic(self.norm, 10**self.log_mlow,
                                               10**self.log_mhigh, n,
                                               self.plaw_index)
        m = self.func_cdm.draw()
        npt.assert_almost_equal(np.sum(m) / mtheory, 1, 2)
Exemple #2
0
    def test_integrate_mass_function(self):
        def _analytic_integral_bound(x, a, b, c, n):

            term1 = x**(a + n + 1) * ((c + x) / c)**(-b) * ((c + x) / x)**b
            term2 = hyp2f1(-b, a - b + n + 1, a - b + n + 2,
                           -x / c) / (a - b + n + 1)
            return term1 * term2

        norm = 1.
        m_low, m_high = 10**6, 10**10
        log_mc = 0.

        a_wdm, b_wdm, c_wdm = 1., 1., -1.3
        plaw_index = -1.8

        for n in [0, 1]:
            integral = integrate_power_law_quad(norm, m_low, m_high, log_mc, n,
                                                plaw_index, a_wdm, b_wdm,
                                                c_wdm)
            integral_analytic = integrate_power_law_analytic(
                norm, m_low, m_high, n, plaw_index)

            analytic_integral = norm * (m_high**(1 + plaw_index + n) - m_low**(
                1 + plaw_index + n)) / (n + 1 + plaw_index)
            npt.assert_almost_equal(integral / analytic_integral, 1, 4)
            npt.assert_almost_equal(integral_analytic / analytic_integral, 1,
                                    5)

        log_mc = 8.
        a_wdm, b_wdm, c_wdm = 1., 1, -1.3
        for n in [0, 1]:
            integral = integrate_power_law_quad(norm, m_low, m_high, log_mc, n,
                                                plaw_index, a_wdm, b_wdm,
                                                c_wdm)

            analytic_integral = _analytic_integral_bound(m_high, plaw_index, c_wdm, 10 ** log_mc, n) - \
                                _analytic_integral_bound(m_low, plaw_index, c_wdm, 10 ** log_mc, n)

            npt.assert_almost_equal(integral / analytic_integral, 1, 4)

        integral_analytic = integrate_power_law_analytic(
            norm, m_low, m_high, 0, -1)
        npt.assert_almost_equal(integral_analytic,
                                norm * np.log(m_high / m_low))
    def test_convergence_correction(self):

        idx = 20
        z = self.lens_plane_redshifts[idx]
        dz = self.delta_zs[idx]
        log_mass_sheet_min = 8.

        # factor of two because the kappa sheets are added at every other lens plane
        norm, slope = self.rendering_class._normalization_slope(z, 2 * dz)

        mtheory = integrate_power_law_analytic(
            norm, 10**self.kwargs_cdm['log_mass_sheet_min'],
            10**self.kwargs_cdm['log_mass_sheet_max'], 1., slope)
        mtheory_2 = integrate_power_law_analytic(
            norm, 10**log_mass_sheet_min,
            10**self.kwargs_cdm['log_mass_sheet_max'], 1., slope)

        area = self.geometry.angle_to_physical_area(
            0.5 * self.kwargs_cdm['cone_opening_angle'], z)
        kappa_theory = mtheory / self.lens_cosmo.sigma_crit_mass(z, area)
        kappa_theory_2 = mtheory_2 / self.lens_cosmo.sigma_crit_mass(z, area)

        kwargs_out, profile_names_out, redshifts = self.rendering_class.convergence_sheet_correction(
        )
        kwargs_out_2, profile_names_out_2, redshifts_2 = self.rendering_class.\
            convergence_sheet_correction({'log_mass_sheet_min': log_mass_sheet_min})

        idx = np.where(redshifts == z)[0][0]
        kw = kwargs_out[idx]
        kw2 = kwargs_out_2[idx]
        name = profile_names_out[idx]

        npt.assert_equal(True, name == 'CONVERGENCE')
        kappa_generated = -kw['kappa']
        kappa_generated_2 = -kw2['kappa']
        npt.assert_almost_equal(kappa_theory, kappa_generated)
        npt.assert_almost_equal(kappa_theory_2, kappa_generated_2)
        npt.assert_equal(True, kw['kappa'] < 0.)
Exemple #4
0
    def __init__(self, log_mlow, log_mhigh, power_law_index, draw_poisson, normalization,
                 log_mc, a_wdm, b_wdm, c_wdm):

        if a_wdm is None:
            assert b_wdm is None, 'If one of a_wdm, b_wdm, or c_wdm is not specified (None), all parameters must be None'
            assert c_wdm is None, 'If one of a_wdm, b_wdm, or c_wdm is not specified (None), all parameters must be None'
        else:
            assert b_wdm is not None, 'Must specify values for all three of a_wdm, b_wdm, c_wdm'
            assert c_wdm is not None, 'Must specify values for all three of a_wdm, b_wdm, c_wdm'
        if b_wdm is None:
            assert a_wdm is None, 'If one of a_wdm, b_wdm, or c_wdm is not specified (None), all parameters must be None'
            assert c_wdm is None, 'If one of a_wdm, b_wdm, or c_wdm is not specified (None), all parameters must be None'
        else:
            assert a_wdm is not None, 'Must specify values for all three of a_wdm, b_wdm, c_wdm'
            assert c_wdm is not None, 'Must specify values for all three of a_wdm, b_wdm, c_wdm'
        if c_wdm is None:
            assert a_wdm is None, 'If one of a_wdm, b_wdm, or c_wdm is not specified (None), all parameters must be None'
            assert b_wdm is None, 'If one of a_wdm, b_wdm, or c_wdm is not specified (None), all parameters must be None'
        else:
            assert a_wdm is not None, 'Must specify values for all three of a_wdm, b_wdm, c_wdm'
            assert b_wdm is not None, 'Must specify values for all three of a_wdm, b_wdm, c_wdm'

        if normalization < 0:
            raise Exception('normalization cannot be < 0.')
        if c_wdm is not None and c_wdm > 0:
            raise ValueError('c_wdm should be a negative number (otherwise mass function gets steeper (unphysical)')
        if a_wdm is not None and a_wdm < 0:
            raise ValueError('a_wdm should be a positive number for suppression factor: '
                             '( 1 + (a_wdm * m/m_c)^b_wdm)^c_wdm')

        if np.any([a_wdm is None, b_wdm is None, c_wdm is None]):
            assert log_mc is None, 'If log_mc is specified, must also specify kwargs for a_wdm, b_wdm, c_wdm.' \
                                   '(See documentation in pyHalo/Rendering/MassFunctions/Powerlaw/broken_powerlaw'

        self._log_mc = log_mc
        self._a_wdm = a_wdm
        self._b_wdm = b_wdm
        self._c_wdm = c_wdm

        self.draw_poisson = draw_poisson
        self._index = power_law_index
        self._mL = 10 ** log_mlow
        self._mH = 10 ** log_mhigh

        self._nhalos_mean_unbroken = integrate_power_law_analytic(normalization, 10 ** log_mlow, 10 ** log_mhigh, 0,
                                                                  power_law_index)
Exemple #5
0
    def test_mass_rendered_line_of_sight(self):

        m_theory = 0
        m_rendered = 0

        for z, dz in zip(self.lens_plane_redshifts, self.delta_zs):

            m_rendered += self.realization_cdm_field.mass_at_z_exact(z)

            slope = self.halo_mass_function.plaw_index_z(
                z) + self.kwargs_cdm['delta_power_law_index']
            norm = self.kwargs_cdm['LOS_normalization'] * \
                   self.halo_mass_function.norm_at_z_density(z, slope, self.kwargs_cdm['m_pivot']) * \
                   self.geometry.volume_element_comoving(z, dz)

            m_theory += integrate_power_law_analytic(
                norm, 10**self.kwargs_cdm['log_mlow'],
                10**self.kwargs_cdm['log_mhigh'], 1, slope)

        ratio = m_theory / m_rendered
        npt.assert_array_less(1 - ratio, 0.05)

        m_theory = 0
        m_rendered = 0

        for z, dz in zip(self.lens_plane_redshifts, self.delta_zs):

            m_rendered += self.realization_wdm_field.mass_at_z_exact(z)
            slope = self.halo_mass_function.plaw_index_z(
                z) + self.kwargs_wdm['delta_power_law_index']
            norm = self.kwargs_cdm['LOS_normalization'] * \
                   self.halo_mass_function.norm_at_z_density(z, slope, self.kwargs_wdm['m_pivot']) * \
                    self.geometry.volume_element_comoving(z, dz)

            m_theory += integrate_power_law_quad(
                norm, 10**self.kwargs_wdm['log_mlow'],
                10**self.kwargs_wdm['log_mhigh'], self.kwargs_wdm['log_mc'], 1,
                slope, self.kwargs_wdm['a_wdm'], self.kwargs_wdm['b_wdm'],
                self.kwargs_wdm['c_wdm'])

        ratio = m_theory / m_rendered
        npt.assert_array_less(1 - ratio, 0.05)
Exemple #6
0
    def test_mass_rendered_subhalos(self):

        plaw_index = self.kwargs_cdm['power_law_index'] + \
                     self.kwargs_cdm['delta_power_law_index'] * self.kwargs_cdm['delta_power_law_index_coupling']

        norm = normalization_sigmasub(self.kwargs_cdm['sigma_sub'],
                                      self.kwargs_cdm['host_m200'],
                                      self.lens_cosmo.z_lens,
                                      self.geometry.kpc_per_arcsec_zlens,
                                      self.kwargs_cdm['cone_opening_angle'],
                                      plaw_index, self.kwargs_cdm['m_pivot'])
        mtheory = integrate_power_law_analytic(
            norm, 10**self.kwargs_cdm['log_mlow'],
            10**self.kwargs_cdm['log_mhigh'], 1., plaw_index)
        m_subs = 0.
        for halo in self.realization_cdm.halos:
            if halo.is_subhalo:
                m_subs += halo.mass
        ratio = mtheory / m_subs
        npt.assert_array_less(1 - ratio, 0.05)

        plaw_index = self.kwargs_wdm['power_law_index'] + \
                     self.kwargs_wdm['delta_power_law_index'] * self.kwargs_wdm['delta_power_law_index_coupling']

        norm = normalization_sigmasub(self.kwargs_wdm['sigma_sub'],
                                      self.kwargs_wdm['host_m200'],
                                      self.lens_cosmo.z_lens,
                                      self.geometry.kpc_per_arcsec_zlens,
                                      self.kwargs_cdm['cone_opening_angle'],
                                      plaw_index, self.kwargs_wdm['m_pivot'])
        mtheory = integrate_power_law_quad(
            norm, 10**self.kwargs_wdm['log_mlow'],
            10**self.kwargs_wdm['log_mhigh'], self.kwargs_wdm['log_mc'], 1.,
            plaw_index, self.kwargs_wdm['a_wdm'], self.kwargs_wdm['b_wdm'],
            self.kwargs_wdm['c_wdm'])
        m_subs = 0.
        for halo in self.realization_wdm_subhalos.halos:
            if halo.is_subhalo:
                m_subs += halo.mass
        ratio = mtheory / m_subs
        npt.assert_array_less(1 - ratio, 0.1)
Exemple #7
0
    def test_convergence_correction(self):

        z = self.lens_cosmo.z_lens

        norm, slope = self.rendering_class_uniform._norm_slope()

        # factor of two because the kappa sheets are added at every other lens plane
        mtheory = integrate_power_law_analytic(
            norm, 10**self.kwargs_cdm['log_mass_sheet_min'],
            10**self.kwargs_cdm['log_mass_sheet_max'], 1., slope)
        area = self.geometry.angle_to_physical_area(
            0.5 * self.kwargs_cdm['cone_opening_angle'], z)
        kappa_theory = mtheory / self.lens_cosmo.sigma_crit_mass(z, area)

        kwargs_out, profile_names_out, redshifts = self.rendering_class_uniform.convergence_sheet_correction(
        )

        kw = kwargs_out[0]
        name = profile_names_out[0]

        npt.assert_equal(True, name == 'CONVERGENCE')
        kappa_generated = -kw['kappa']
        npt.assert_array_less(abs(kappa_theory / kappa_generated - 1), 0.05)
Exemple #8
0
    def convergence_sheet_correction(self, kwargs_mass_sheets=None):

        norm, slope = self._norm_slope()

        kw_mass_sheets = self._convergence_sheet_kwargs
        if kwargs_mass_sheets is not None:
            kwargs_mass_sheets.update(kw_mass_sheets)

        log_mass_sheet_correction_min, log_mass_sheet_correction_max = \
            kw_mass_sheets['log_mass_sheet_min'], kw_mass_sheets['log_mass_sheet_max']
        log_mass_sheet_correction_min, log_mass_sheet_correction_max = self._redshift_dependent_mass_range(
            self._zlens, log_mass_sheet_correction_min,
            log_mass_sheet_correction_max)

        kappa_scale = kw_mass_sheets['subhalo_mass_sheet_scale']

        m_low, m_high = 10**log_mass_sheet_correction_min, 10**log_mass_sheet_correction_max

        delta_power_law_index = self._rendering_kwargs[
            'delta_power_law_index_coupling'] * self._rendering_kwargs[
                'delta_power_law_index']
        power_law_index = self._rendering_kwargs[
            'power_law_index'] + delta_power_law_index

        if self._rendering_kwargs['log_mc'] is not None:
            mass_in_subhalos = integrate_power_law_quad(
                norm, m_low, m_high, self._rendering_kwargs['log_mc'], 1,
                power_law_index, self._rendering_kwargs['a_wdm'],
                self._rendering_kwargs['b_wdm'],
                self._rendering_kwargs['c_wdm'])
        else:
            mass_in_subhalos = integrate_power_law_analytic(
                norm, m_low, m_high, 1, power_law_index)

        if kw_mass_sheets[
                'subhalo_convergence_correction_profile'] == 'UNIFORM':

            area = self.geometry.angle_to_physical_area(
                0.5 * self.geometry.cone_opening_angle, self._zlens)
            kappa = mass_in_subhalos / self.lens_cosmo.sigma_crit_mass(
                self._zlens, area)

            negative_kappa = -1 * kappa_scale * kappa

            kwargs_out = [{'kappa': negative_kappa}]
            profile_name_out = ['CONVERGENCE']
            redshifts_out = [self._zlens]

        elif kw_mass_sheets['subhalo_convergence_correction_profile'] == 'NFW':

            if 'host_m200' not in self._rendering_kwargs.keys():
                raise Exception(
                    'must specify host halo mass when using NFW convergence sheet correction for subhalos'
                )

            Rs_host_kpc = self.spatial_distribution_model._rs_kpc
            rs_mpc = Rs_host_kpc / 1000
            r_tidal_host_kpc = self.spatial_distribution_model.xtidal * Rs_host_kpc

            Rs_angle = Rs_host_kpc / self.geometry.kpc_per_arcsec_zlens
            r_core_angle = r_tidal_host_kpc / self.geometry.kpc_per_arcsec_zlens

            x = self.geometry.cone_opening_angle / Rs_angle / 2

            eps_crit = self.lens_cosmo.get_sigma_crit_lensing(
                self._zlens, self._z_source)
            D_d = self.lens_cosmo.cosmo.D_A_z(self._zlens)
            denom = 4 * np.pi * rs_mpc**3 * (np.log(x / 2) + self._nfw_F(x))
            rho0 = mass_in_subhalos / denom  # solar mass per Mpc^3

            theta_Rs = rho0 * (4 * rs_mpc**2 * (1 + np.log(1. / 2.)))
            theta_Rs *= 1 / (D_d * eps_crit * self.lens_cosmo.cosmo.arcsec)

            kwargs_out = [{
                'alpha_Rs': -kappa_scale * theta_Rs,
                'Rs': Rs_angle,
                'center_x': 0.,
                'center_y': 0.,
                'r_core': r_core_angle
            }]

            profile_name_out = ['CNFW']
            redshifts_out = [self._zlens]

        else:
            raise Exception(
                'subhalo convergence correction profile ' +
                str(kw_mass_sheets['subhalo_convergence_correction_profile']) +
                ' not recognized.')

        return kwargs_out, profile_name_out, redshifts_out