Beispiel #1
0
    def setup(self):

        self.arcsec = 2 * np.pi / 360 / 3600
        self.zlens = 1
        self.zsource = 2
        self.angle_diameter = 2 / self.arcsec
        self.angle_radius = 0.5 * self.angle_diameter

        H0 = 70
        omega_baryon = 0.0
        omega_DM = 0.3
        sigma8 = 0.82
        curvature = 'flat'
        ns = 0.9608
        cosmo_params = {
            'H0': H0,
            'Om0': omega_baryon + omega_DM,
            'Ob0': omega_baryon,
            'sigma8': sigma8,
            'ns': ns,
            'curvature': curvature
        }
        self.cosmo = Cosmology(cosmo_kwargs=cosmo_params)

        self._angle_pad = 0.75
        self.geometry_double_cone = Geometry(self.cosmo, self.zlens,
                                             self.zsource, self.angle_diameter,
                                             'DOUBLE_CONE', self._angle_pad)
Beispiel #2
0
    def setup(self):

        cosmo = Cosmology()
        self.geometry = Geometry(cosmo, 0.5, 1.5, 6., 'DOUBLE_CONE')
        self.uni = Uniform(3, self.geometry)

        self.lenscone_uni = LensConeUniform(6., self.geometry)
Beispiel #3
0
    def test_volume(self):

        cone_arcsec = 3
        radius = cone_arcsec * 0.5
        angle_pad = 0.7
        zlens = 1.
        zsrc = 1.8
        geo = Geometry(self.cosmo,
                       zlens,
                       zsrc,
                       cone_arcsec,
                       'DOUBLE_CONE',
                       angle_pad=angle_pad)
        astropy = geo._cosmo.astropy

        delta_z = 1e-3

        dV_pyhalo = geo.volume_element_comoving(0.6, delta_z)
        dV = astropy.differential_comoving_volume(0.6).value

        dV_astropy = dV * delta_z
        steradian = np.pi * (radius * self.arcsec)**2
        npt.assert_almost_equal(dV_astropy * steradian, dV_pyhalo, 5)

        angle_scale = geo.rendering_scale(1.3)
        dV_pyhalo = geo.volume_element_comoving(1.3, delta_z)
        dV = astropy.differential_comoving_volume(1.3).value
        dV_astropy = dV * delta_z
        steradian = np.pi * (radius * angle_scale * self.arcsec)**2
        npt.assert_almost_equal(dV_astropy * steradian, dV_pyhalo, 5)
Beispiel #4
0
class TestUniform(object):

    def setup(self):

        cosmo = Cosmology()
        self.geometry = Geometry(cosmo, 0.5, 1.5, 6., 'DOUBLE_CONE')
        self.uni = Uniform(3, self.geometry)

        self.lenscone_uni = LensConeUniform(6., self.geometry)

    def test_uniform(self):

        x, y = self.uni.draw(1000, 0.3, 1., 0., 0.)
        kpc_per_asec = self.geometry.kpc_per_arcsec(0.3)
        x *= kpc_per_asec ** -1
        y *= kpc_per_asec ** -1
        r2d = np.hypot(x, y)
        npt.assert_equal(True, max(r2d) < 3)

        x, y = self.uni.draw(1000, 0.3, 0.5, 0., 0.)
        x *= kpc_per_asec ** -1
        y *= kpc_per_asec ** -1
        r2d = np.hypot(x, y)
        npt.assert_equal(True, max(r2d) < 1.5)

    def test_lens_cone_uniform(self):

        x, y = self.lenscone_uni.draw(10000, 0.5)
        kpc_per_asec = self.geometry.kpc_per_arcsec(0.5)
        x *= kpc_per_asec ** -1
        y *= kpc_per_asec ** -1
        x2, y2 = self.lenscone_uni.draw(10000, 0.9)
        kpc_per_asec = self.geometry.kpc_per_arcsec(0.9)
        x2 *= kpc_per_asec ** -1
        y2 *= kpc_per_asec ** -1

        scale1 = self.geometry.rendering_scale(0.5)
        scale2 = self.geometry.rendering_scale(0.9)

        max1 = max(np.hypot(x, y))
        max2 = max(np.hypot(x2, y2))
        npt.assert_almost_equal(max1/max2, scale1/scale2, 2)

    def test_distribution(self):

        x, y = self.uni.draw(1000000, 0.2, 1., 0., 0.)
        r2 = np.hypot(x, y)
        rbins = np.arange(1., 3.+0.5, 0.5)
        n = []
        for i in range(0, len(rbins)-1):
            condition = np.logical_and(r2 >= rbins[i], r2<rbins[i+1])
            N = np.sum(condition)
            area = np.pi * (rbins[i+1]**2 - rbins[i]**2)
            n.append(N/area)
        npt.assert_almost_equal(n[0]/n[1], 1, 1)
        npt.assert_almost_equal(n[2]/n[3], 1, 1)
Beispiel #5
0
    def setup(self):

        self.arcsec = 2 * np.pi / 360 / 3600
        self.zlens = 1
        self.zsource = 2
        self.angle_diameter = 2 / self.arcsec
        self.angle_radius = 0.5 * self.angle_diameter

        self.H0 = 70
        self.omega_baryon = 0.03
        self.omega_DM = 0.25
        self.sigma8 = 0.82
        curvature = 'flat'
        self.ns = 0.9608
        cosmo_params = {
            'H0': self.H0,
            'Om0': self.omega_baryon + self.omega_DM,
            'Ob0': self.omega_baryon,
            'sigma8': self.sigma8,
            'ns': self.ns,
            'curvature': curvature
        }
        self._dm, self._bar = self.omega_DM, self.omega_baryon
        self.cosmo = Cosmology(cosmo_kwargs=cosmo_params)
        self.geometry = Geometry(self.cosmo, self.zlens, self.zsource,
                                 self.angle_diameter, 'DOUBLE_CONE')
    def __init__(self, kwargs_rendering, realization, r_max_arcsec):
        """

        :param kwargs_rendering: keyword arguments that specify the mass function model
        :param realization: an instance of Realization used to compute the convergence at each lens plane
        :param r_max_arcsec: the radius of area at which the halos are rendered
        """

        self.kwargs_rendering = kwargs_rendering
        self._realization = realization
        self.cylinder_geometry = Geometry(
            self._realization.lens_cosmo.cosmo,
            self._realization.lens_cosmo.z_lens,
            self._realization.lens_cosmo.z_source, 2 * r_max_arcsec,
            'DOUBLE_CONE')

        self.spatial_distribution_model = Correlated2D(self.cylinder_geometry)
        self._rmax = r_max_arcsec
Beispiel #7
0
    def test_total_volume(self):

        cone_arcsec = 4
        radius_radians = cone_arcsec * 0.5 * self.cosmo.arcsec
        geo = Geometry(self.cosmo,
                       0.5,
                       1.5,
                       cone_arcsec,
                       'DOUBLE_CONE',
                       angle_pad=1.)
        volume_pyhalo = 0
        z = np.linspace(0.0, 1.5, 200)
        for i in range(0, len(z) - 1):
            delta_z = z[i + 1] - z[i]
            volume_pyhalo += geo.volume_element_comoving(z[i], delta_z)

        ds = self.cosmo.D_C_z(1.5)
        dz = self.cosmo.D_C_z(0.5)
        volume_true = 1. / 3 * np.pi * radius_radians**2 * dz**2 * ds
        npt.assert_almost_equal(volume_true, volume_pyhalo, 3)
Beispiel #8
0
    def setup(self):

        zlens, zsource = 0.5, 1.5
        self.rs = 60
        self.rmax2d = 40
        self.rvir = 350
        self.rcore = 10.
        self.nfw = ProjectedNFW(self.rmax2d, self.rs, self.rcore, self.rvir)

        cosmo = Cosmology()
        self.geometry = Geometry(cosmo, 0.5, 1.5, 6., 'DOUBLE_CONE')
        self.lens_cosmo = LensCosmo(zlens, zsource, cosmo)
Beispiel #9
0
    def setup(self):

        zlens, zsource = 0.5, 2.
        zmin = 0.01
        zmax = 1.98
        log_mlow = 6.
        log_mhigh = 9.
        host_m200 = 10**13
        LOS_normalization = 1.
        draw_poisson = False
        log_mass_sheet_min = 7.
        log_mass_sheet_max = 10.
        kappa_scale = 1.
        delta_power_law_index = -0.17
        delta_power_law_index_coupling = 0.5
        cone_opening_angle = 6.
        m_pivot = 10**8
        sigma_sub = 0.1
        power_law_index = -1.9
        subhalo_spatial_distribution = 'HOST_NFW'
        kwargs_suppression = {'c_scale': 10.5, 'c_power': -0.2}
        suppression_model = 'polynomial'
        kwargs_cdm = {
            'zmin': zmin,
            'zmax': zmax,
            'log_mc': None,
            'log_mlow': log_mlow,
            'sigma_sub': sigma_sub,
            'kwargs_suppression': kwargs_suppression,
            'suppression_model': suppression_model,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'c_scatter_dex': 0.2,
            'log_mhigh': log_mhigh,
            'host_m200': host_m200,
            'LOS_normalization': LOS_normalization,
            'draw_poisson': draw_poisson,
            'subhalo_spatial_distribution': subhalo_spatial_distribution,
            'log_mass_sheet_min': log_mass_sheet_min,
            'log_mass_sheet_max': log_mass_sheet_max,
            'kappa_scale': kappa_scale,
            'power_law_index': power_law_index,
            'delta_power_law_index': delta_power_law_index,
            'delta_power_law_index_coupling': delta_power_law_index_coupling,
            'm_pivot': m_pivot,
            'cone_opening_angle': cone_opening_angle,
            'subhalo_mass_sheet_scale': 1.,
            'subhalo_convergence_correction_profile': 'NFW',
            'r_tidal': '0.5Rs',
            'mass_function_LOS_type': 'POWER_LAW'
        }

        kwargs_wdm = deepcopy(kwargs_cdm)

        log_mc = 7.3
        a_wdm = 0.8
        b_wdm = 1.1
        c_wdm = -1.2
        kwargs_wdm['log_mc'] = log_mc
        kwargs_wdm['a_wdm'] = a_wdm
        kwargs_wdm['b_wdm'] = b_wdm
        kwargs_wdm['c_wdm'] = c_wdm
        kwargs_wdm['kwargs_suppression'] = kwargs_suppression
        kwargs_wdm['suppression_model'] = suppression_model

        kwargs_no_sheet = deepcopy(kwargs_cdm)
        kwargs_no_sheet['mass_function_LOS_type'] = 'DELTA'
        kwargs_no_sheet['mass_fraction'] = 0.1
        kwargs_no_sheet['logM'] = 6.

        lens_plane_redshifts = np.append(np.arange(0.01, 0.5, 0.02),
                                         np.arange(0.5, 1.5, 0.02))
        delta_zs = []
        for i in range(0, len(lens_plane_redshifts) - 1):
            delta_zs.append(lens_plane_redshifts[i + 1] -
                            lens_plane_redshifts[i])
        delta_zs.append(1.5 - lens_plane_redshifts[-1])

        cosmo = Cosmology()
        self.lens_plane_redshifts = lens_plane_redshifts
        self.delta_zs = delta_zs
        self.halo_mass_function = LensingMassFunction(
            cosmo,
            0.5,
            1.5,
            kwargs_cdm['log_mlow'],
            kwargs_cdm['log_mhigh'],
            6.,
            m_pivot=kwargs_cdm['m_pivot'],
            geometry_type='DOUBLE_CONE')
        self.geometry = Geometry(cosmo, 0.5, 1.5, 6., 'DOUBLE_CONE')
        self.lens_cosmo = LensCosmo(zlens, zsource, cosmo)

        self.kwargs_cdm = kwargs_cdm
        self.kwargs_wdm = kwargs_wdm
        self.kwargs_no_sheet = kwargs_no_sheet
Beispiel #10
0
class TestSubhalos(object):
    def setup(self):
        zlens, zsource = 0.5, 2.
        zmin = 0.01
        zmax = 1.98
        log_mlow = 6.
        log_mhigh = 9.
        host_m200 = 10**13.5
        LOS_normalization = 1.
        draw_poisson = False
        log_mass_sheet_min = 7.
        log_mass_sheet_max = 10.
        kappa_scale = 1.
        delta_power_law_index = -0.1
        delta_power_law_index_coupling = 0.5
        cone_opening_angle = 6.
        m_pivot = 10**8
        sigma_sub = 0.1
        power_law_index = -1.9
        subhalo_spatial_distribution = 'HOST_NFW'

        kwargs_cdm_uniform = {
            'zmin': zmin,
            'zmax': zmax,
            'log_mc': None,
            'log_mlow': log_mlow,
            'sigma_sub': sigma_sub,
            'c_scale': None,
            'c_power': None,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'c_scatter_dex': 0.2,
            'log_mhigh': log_mhigh,
            'mdef_subs': 'TNFW',
            'log_m_host': np.log10(host_m200),
            'LOS_normalization': LOS_normalization,
            'draw_poisson': draw_poisson,
            'subhalo_spatial_distribution': subhalo_spatial_distribution,
            'log_mass_sheet_min': log_mass_sheet_min,
            'log_mass_sheet_max': log_mass_sheet_max,
            'kappa_scale': kappa_scale,
            'power_law_index': power_law_index,
            'delta_power_law_index': delta_power_law_index,
            'delta_power_law_index_coupling': delta_power_law_index_coupling,
            'm_pivot': m_pivot,
            'cone_opening_angle': cone_opening_angle,
            'subhalo_mass_sheet_scale': 1.,
            'subhalo_convergence_correction_profile': 'UNIFORM',
            'r_tidal': '0.5Rs'
        }
        kwargs_cdm_nfw = deepcopy(kwargs_cdm_uniform)
        kwargs_cdm_nfw['subhalo_convergence_correction_profile'] = 'NFW'

        pyhalo = pyHalo(zlens, zsource)
        self.realization_cdm = pyhalo.render(['SUBHALOS'],
                                             kwargs_cdm_uniform)[0]
        self.realization_cdm_nfw = pyhalo.render(['SUBHALOS'],
                                                 kwargs_cdm_nfw)[0]

        lens_plane_redshifts, delta_zs = pyhalo.lens_plane_redshifts(
            kwargs_cdm_uniform)

        cosmo = Cosmology()
        self.lens_plane_redshifts = lens_plane_redshifts
        self.delta_zs = delta_zs
        self.halo_mass_function = LensingMassFunction(
            cosmo,
            zlens,
            zsource,
            kwargs_cdm_uniform['log_mlow'],
            kwargs_cdm_uniform['log_mhigh'],
            kwargs_cdm_uniform['cone_opening_angle'],
            m_pivot=kwargs_cdm_uniform['m_pivot'],
            geometry_type='DOUBLE_CONE')
        self.geometry = Geometry(cosmo, zlens, zsource,
                                 kwargs_cdm_uniform['cone_opening_angle'],
                                 'DOUBLE_CONE')
        self.lens_cosmo = LensCosmo(zlens, zsource, cosmo)

        self.kwargs_cdm = kwargs_cdm_uniform

        self.rendering_class_uniform = Subhalos(kwargs_cdm_uniform,
                                                self.geometry, self.lens_cosmo)
        self.rendering_class_nfw = Subhalos(kwargs_cdm_nfw, self.geometry,
                                            self.lens_cosmo)

    def test_normalization(self):

        norm = normalization_sigmasub(
            self.kwargs_cdm['sigma_sub'], 10**self.kwargs_cdm['log_m_host'],
            self.lens_cosmo.z_lens, self.geometry.kpc_per_arcsec_zlens,
            self.kwargs_cdm['cone_opening_angle'],
            self.kwargs_cdm['power_law_index'] +
            self.kwargs_cdm['delta_power_law_index'] *
            self.kwargs_cdm['delta_power_law_index_coupling'],
            self.kwargs_cdm['m_pivot'])

        k1, k2 = 0.88, 1.7
        slope = self.kwargs_cdm['power_law_index'] + self.kwargs_cdm['delta_power_law_index'] * \
                     self.kwargs_cdm['delta_power_law_index_coupling']
        mhalo = 10**self.kwargs_cdm['log_m_host']
        scale = k1 * np.log10(
            mhalo / 10**13) + k2 * np.log10(self.lens_cosmo.z_lens + 0.5)
        host_scaling = 10**scale

        norm_theory = self.kwargs_cdm['sigma_sub'] * host_scaling

        kpc_per_arcsec_zlens = self.geometry.kpc_per_arcsec(
            self.lens_cosmo.z_lens)
        norm_theory *= np.pi * (0.5 * self.kwargs_cdm['cone_opening_angle'] *
                                kpc_per_arcsec_zlens)**2
        norm_theory *= self.kwargs_cdm['m_pivot']**-(slope + 1)

        npt.assert_almost_equal(norm, norm_theory)

        _norm, _slope = self.rendering_class_uniform._norm_slope()
        npt.assert_almost_equal(_norm, norm)
        npt.assert_almost_equal(_slope, slope)

    def test_rendering(self):

        m = self.rendering_class_uniform.render_masses_at_z()
        npt.assert_equal(True, len(m) > 0)
        x, y, r3 = self.rendering_class_uniform.render_positions_at_z(10000)
        rmax = np.max(np.hypot(x, y))
        rmax_theory = 0.5 * self.kwargs_cdm[
            'cone_opening_angle'] * self.geometry.rendering_scale(
                self.lens_cosmo.z_lens)
        npt.assert_array_less(rmax, rmax_theory)

        x, y, r3 = self.rendering_class_uniform.render_positions_at_z(0)
        npt.assert_equal(True, len(x) == 0)

        m, x, y, r3, redshifts, flag = self.rendering_class_uniform.render()
        npt.assert_equal(len(m), len(x))
        npt.assert_equal(len(y), len(r3))

        n = 0
        for z in np.unique(redshifts):
            n += np.sum(redshifts == z)
        npt.assert_equal(True, n == len(m))

        npt.assert_equal(True, len(self.realization_cdm.halos) == len(m))

    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)

    def test_keys_convergence_sheets(self):

        keywords_out = self.rendering_class_uniform.keys_convergence_sheets(
            self.kwargs_cdm)
        required_keys = [
            'log_mass_sheet_min', 'log_mass_sheet_max',
            'subhalo_mass_sheet_scale',
            'subhalo_convergence_correction_profile', 'r_tidal',
            'delta_power_law_index', 'delta_power_law_index_coupling'
        ]

        for x in required_keys:
            npt.assert_equal(x in keywords_out.keys(), True)

    def test_keys_rendering(self):

        keywords_out = self.rendering_class_uniform.keyword_parse_render(
            self.kwargs_cdm)
        required_keys = [
            'power_law_index', 'log_mlow', 'log_mhigh', 'log_mc', 'sigma_sub',
            'a_wdm', 'b_wdm', 'c_wdm', 'log_mass_sheet_min',
            'log_mass_sheet_max', 'subhalo_mass_sheet_scale', 'draw_poisson',
            'host_m200', 'subhalo_convergence_correction_profile', 'r_tidal',
            'delta_power_law_index', 'm_pivot',
            'delta_power_law_index_coupling', 'cone_opening_angle'
        ]

        for x in required_keys:
            npt.assert_equal(x in keywords_out.keys(), True)

        kw_cdm = deepcopy(self.kwargs_cdm)
        kw_cdm['log_mc'] = None

        keywords_out = self.rendering_class_uniform.keyword_parse_render(
            kw_cdm)
        npt.assert_equal(keywords_out['a_wdm'] is None, True)
        npt.assert_equal(keywords_out['b_wdm'] is None, True)
        npt.assert_equal(keywords_out['c_wdm'] is None, True)
Beispiel #11
0
class TestConeGeometry(object):
    def setup(self):

        self.arcsec = 2 * np.pi / 360 / 3600
        self.zlens = 1
        self.zsource = 2
        self.angle_diameter = 2 / self.arcsec
        self.angle_radius = 0.5 * self.angle_diameter

        H0 = 70
        omega_baryon = 0.0
        omega_DM = 0.3
        sigma8 = 0.82
        curvature = 'flat'
        ns = 0.9608
        cosmo_params = {
            'H0': H0,
            'Om0': omega_baryon + omega_DM,
            'Ob0': omega_baryon,
            'sigma8': sigma8,
            'ns': ns,
            'curvature': curvature
        }
        self.cosmo = Cosmology(cosmo_kwargs=cosmo_params)

        self.geometry_cylinder = Geometry(self.cosmo, self.zlens, self.zsource,
                                          self.angle_diameter, 'CYLINDER')

    def test_angle_scale(self):

        scale = self.geometry_cylinder.rendering_scale(self.zlens)
        npt.assert_almost_equal(scale, 1.)

        scale = self.geometry_cylinder.rendering_scale(self.zlens + 0.35)
        dratio = self.geometry_cylinder._cosmo.D_C_z(
            self.zlens) / self.geometry_cylinder._cosmo.D_C_z(self.zlens +
                                                              0.35)
        val = 0.5 * self.geometry_cylinder.cone_opening_angle * self.arcsec * dratio
        npt.assert_almost_equal(scale, val, 3)

        dratio = self.geometry_cylinder._cosmo.D_C_z(
            self.zlens) / self.geometry_cylinder._cosmo.D_C_z(self.zsource)
        val = 0.5 * self.geometry_cylinder.cone_opening_angle * self.arcsec * dratio
        npt.assert_almost_equal(
            self.geometry_cylinder.rendering_scale(self.zsource), val)

    def test_distances_lensing(self):

        z = 0.3
        radius_physical = self.geometry_cylinder.angle_to_physicalradius(
            self.angle_radius, z)
        dratio = self.geometry_cylinder._cosmo.D_C_z(
            self.zlens) / self.geometry_cylinder._cosmo.D_C_z(z)
        radius = self.geometry_cylinder._cosmo.D_A_z(
            z) * self.angle_radius * self.arcsec * dratio
        npt.assert_almost_equal(radius_physical, radius, 0)

        comoving_radius = self.geometry_cylinder.angle_to_comovingradius(
            self.angle_radius, z)
        npt.assert_almost_equal(comoving_radius, radius_physical * (1 + z), 3)

        z = 1
        radius_physical = self.geometry_cylinder.angle_to_physicalradius(
            self.angle_radius, z)
        dratio = self.geometry_cylinder._cosmo.D_C_z(
            self.zlens) / self.geometry_cylinder._cosmo.D_C_z(z)
        radius = self.geometry_cylinder._cosmo.D_A_z(
            z) * self.angle_radius * self.arcsec * dratio
        npt.assert_almost_equal(radius_physical, radius, 0)

        comoving_radius = self.geometry_cylinder.angle_to_comovingradius(
            self.angle_radius, z)
        npt.assert_almost_equal(comoving_radius, radius_physical * (1 + z), 3)

        z = 1.25
        radius_physical = self.geometry_cylinder.angle_to_physicalradius(
            self.angle_radius, z)
        dratio = self.geometry_cylinder._cosmo.D_C_z(
            self.zlens) / self.geometry_cylinder._cosmo.D_C_z(z)
        radius = self.geometry_cylinder._cosmo.D_A_z(
            z) * self.angle_radius * self.arcsec * dratio
        npt.assert_almost_equal(radius_physical, radius, 0)

        comoving_radius = self.geometry_cylinder.angle_to_comovingradius(
            self.angle_radius, z)
        npt.assert_almost_equal(comoving_radius, radius_physical * (1 + z), 3)

    def test_total_volume(self):

        delta_z = 0.001
        volume_pyhalo = 0
        for zi in np.arange(0, self.zsource + delta_z, delta_z):
            dV_pyhalo = self.geometry_cylinder.volume_element_comoving(
                zi, delta_z)
            volume_pyhalo += dV_pyhalo

        r = self.geometry_cylinder._cosmo.D_C_z(
            self.zlens
        ) * self.geometry_cylinder.cone_opening_angle * 0.5 * self.arcsec
        d = self.geometry_cylinder._cosmo.D_C_z(self.zsource)
        volume = np.pi * r**2 * d
        npt.assert_almost_equal(volume / volume_pyhalo, 1, 3)
Beispiel #12
0
class TestLOS(object):
    def setup(self):
        zlens, zsource = 0.5, 2.
        zmin = 0.01
        zmax = 1.98
        log_mlow = 6.
        log_mhigh = 9.
        host_m200 = 10**13
        LOS_normalization = 1.
        draw_poisson = False
        log_mass_sheet_min = 7.
        log_mass_sheet_max = 10.
        kappa_scale = 1.
        delta_power_law_index = -0.1
        delta_power_law_index_coupling = 0.5
        cone_opening_angle = 6.
        m_pivot = 10**8
        sigma_sub = 0.1
        power_law_index = -1.9
        subhalo_spatial_distribution = 'HOST_NFW'

        kwargs_cdm = {
            'zmin': zmin,
            'zmax': zmax,
            'log_mc': None,
            'log_mlow': log_mlow,
            'sigma_sub': sigma_sub,
            'c_scale': None,
            'c_power': None,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'c_scatter_dex': 0.2,
            'log_mhigh': log_mhigh,
            'mdef_los': 'TNFW',
            'host_m200': host_m200,
            'LOS_normalization': LOS_normalization,
            'draw_poisson': draw_poisson,
            'subhalo_spatial_distribution': subhalo_spatial_distribution,
            'log_mass_sheet_min': log_mass_sheet_min,
            'log_mass_sheet_max': log_mass_sheet_max,
            'kappa_scale': kappa_scale,
            'power_law_index': power_law_index,
            'delta_power_law_index': delta_power_law_index,
            'delta_power_law_index_coupling': delta_power_law_index_coupling,
            'm_pivot': m_pivot,
            'cone_opening_angle': cone_opening_angle,
            'subhalo_mass_sheet_scale': 1.,
            'subhalo_convergence_correction_profile': 'NFW',
            'r_tidal': '0.5Rs'
        }

        pyhalo = pyHalo(zlens, zsource)
        self.realization_cdm = pyhalo.render(['LINE_OF_SIGHT'], kwargs_cdm)[0]

        lens_plane_redshifts, delta_zs = pyhalo.lens_plane_redshifts(
            kwargs_cdm)

        cosmo = Cosmology()
        self.lens_plane_redshifts = lens_plane_redshifts
        self.delta_zs = delta_zs
        self.halo_mass_function = LensingMassFunction(
            cosmo,
            zlens,
            zsource,
            kwargs_cdm['log_mlow'],
            kwargs_cdm['log_mhigh'],
            kwargs_cdm['cone_opening_angle'],
            m_pivot=kwargs_cdm['m_pivot'],
            geometry_type='DOUBLE_CONE')
        self.geometry = Geometry(cosmo, zlens, zsource,
                                 kwargs_cdm['cone_opening_angle'],
                                 'DOUBLE_CONE')
        self.lens_cosmo = LensCosmo(zlens, zsource, cosmo)

        self.kwargs_cdm = kwargs_cdm

        self.rendering_class = LineOfSight(kwargs_cdm, self.halo_mass_function,
                                           self.geometry, self.lens_cosmo,
                                           self.lens_plane_redshifts,
                                           self.delta_zs)

        self.logdelta_mass = 5.
        kwargs_delta = {
            'zmin': zmin,
            'zmax': zmax,
            'log_mc': None,
            'log_mlow': log_mlow,
            'sigma_sub': sigma_sub,
            'c_scale': None,
            'c_power': None,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'c_scatter_dex': 0.2,
            'log_mhigh': log_mhigh,
            'mdef_los': 'TNFW',
            'host_m200': host_m200,
            'LOS_normalization': LOS_normalization,
            'draw_poisson': draw_poisson,
            'subhalo_spatial_distribution': subhalo_spatial_distribution,
            'log_mass_sheet_min': log_mass_sheet_min,
            'log_mass_sheet_max': log_mass_sheet_max,
            'kappa_scale': kappa_scale,
            'power_law_index': power_law_index,
            'delta_power_law_index': delta_power_law_index,
            'delta_power_law_index_coupling': delta_power_law_index_coupling,
            'm_pivot': m_pivot,
            'logM': self.logdelta_mass,
            'mass_fraction': 0.1,
            'cone_opening_angle': cone_opening_angle,
            'subhalo_mass_sheet_scale': 1.,
            'subhalo_convergence_correction_profile': 'NFW',
            'r_tidal': '0.5Rs',
            'mass_function_LOS_type': 'DELTA'
        }

        self.rendering_class_delta = LineOfSight(
            kwargs_delta, self.halo_mass_function, self.geometry,
            self.lens_cosmo, self.lens_plane_redshifts, self.delta_zs)

    def test_norm_slope(self):

        test_index = [10, 20]
        for i in test_index:
            z = self.lens_plane_redshifts[i]
            dz = self.delta_zs[i]
            norm, slope = self.rendering_class._normalization_slope(z, dz)

            slope_theory = self.halo_mass_function.plaw_index_z(
                z) + self.kwargs_cdm['delta_power_law_index']
            norm_theory = self.halo_mass_function.norm_at_z_density(
                z, slope_theory, self.kwargs_cdm['m_pivot'])
            dv = self.geometry.volume_element_comoving(z, dz)
            norm_theory *= self.kwargs_cdm['LOS_normalization'] * dv

            npt.assert_almost_equal(slope, slope_theory)
            npt.assert_almost_equal(norm_theory, norm)

    def test_rendering(self):

        m = self.rendering_class.render_masses_at_z(0.7, 0.02)
        npt.assert_equal(True, len(m) > 0)
        x, y = self.rendering_class.render_positions_at_z(0.9, 10000)
        rmax = np.max(np.hypot(x, y))
        rmax_theory = 0.5 * self.kwargs_cdm[
            'cone_opening_angle'] * self.geometry.rendering_scale(0.9)
        npt.assert_array_less(rmax, rmax_theory)

        x, y = self.rendering_class.render_positions_at_z(0.2, 0)
        npt.assert_equal(True, len(x) == 0)

        m, x, y, r3, redshifts, flag = self.rendering_class.render()
        npt.assert_equal(len(m), len(x))
        npt.assert_equal(len(y), len(r3))

        n = 0
        for z in np.unique(redshifts):
            n += np.sum(redshifts == z)
        npt.assert_equal(True, n == len(m))

        npt.assert_equal(True, len(self.realization_cdm.halos) == len(m))

    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.)

    def test_keys_convergence_sheets(self):

        keywords_out = self.rendering_class.keys_convergence_sheets(
            self.kwargs_cdm)
        required_keys = [
            'log_mass_sheet_min', 'log_mass_sheet_max', 'kappa_scale', 'zmin',
            'zmax', 'delta_power_law_index'
        ]

        for x in required_keys:
            npt.assert_equal(x in keywords_out.keys(), True)

    def test_keys_rendering(self):

        keywords_out = self.rendering_class.keyword_parse_render(
            self.kwargs_cdm)
        required_keys = [
            'zmin', 'zmax', 'log_mc', 'log_mlow', 'log_mhigh', 'host_m200',
            'LOS_normalization', 'draw_poisson', 'log_mass_sheet_min',
            'log_mass_sheet_max', 'kappa_scale', 'a_wdm', 'b_wdm', 'c_wdm',
            'delta_power_law_index', 'm_pivot'
        ]

        for x in required_keys:
            npt.assert_equal(x in keywords_out.keys(), True)

        kw_cdm = deepcopy(self.kwargs_cdm)
        kw_cdm['log_mc'] = None
        keywords_out = self.rendering_class.keyword_parse_render(kw_cdm)
        npt.assert_equal(keywords_out['a_wdm'] is None, True)
        npt.assert_equal(keywords_out['b_wdm'] is None, True)
        npt.assert_equal(keywords_out['c_wdm'] is None, True)

    def test_delta_function_rendering(self):

        m = self.rendering_class_delta.render_masses_at_z(0.5, 0.01)
        for mi in m:
            npt.assert_equal(np.log10(mi), self.logdelta_mass)
Beispiel #13
0
class TestConeGeometry(object):
    def setup(self):

        self.arcsec = 2 * np.pi / 360 / 3600
        self.zlens = 1
        self.zsource = 2
        self.angle_diameter = 2 / self.arcsec
        self.angle_radius = 0.5 * self.angle_diameter

        H0 = 70
        omega_baryon = 0.0
        omega_DM = 0.3
        sigma8 = 0.82
        curvature = 'flat'
        ns = 0.9608
        cosmo_params = {
            'H0': H0,
            'Om0': omega_baryon + omega_DM,
            'Ob0': omega_baryon,
            'sigma8': sigma8,
            'ns': ns,
            'curvature': curvature
        }
        self.cosmo = Cosmology(cosmo_kwargs=cosmo_params)

        self._angle_pad = 0.75
        self.geometry_double_cone = Geometry(self.cosmo, self.zlens,
                                             self.zsource, self.angle_diameter,
                                             'DOUBLE_CONE', self._angle_pad)

    def test_angle_scale(self):

        reduced_to_phys = self.geometry_double_cone._cosmo.D_A(0, self.zsource) / \
                          self.geometry_double_cone._cosmo.D_A(self.zlens, self.zsource)

        ratio_double_cone = reduced_to_phys * \
                            self.cosmo.D_A(self.zlens, self.zsource)/self.cosmo.D_A_z(self.zsource)
        angle_scale_zsource = 1 - self._angle_pad * ratio_double_cone

        npt.assert_almost_equal(
            self.geometry_double_cone.rendering_scale(self.zlens), 1.)
        npt.assert_almost_equal(
            self.geometry_double_cone.rendering_scale(self.zsource),
            angle_scale_zsource)

        npt.assert_almost_equal(
            self.geometry_double_cone.rendering_scale(self.zlens), 1)

    def test_distances_lensing(self):

        z = 0.3
        radius_physical = self.geometry_double_cone.angle_to_physicalradius(
            self.angle_radius, z)
        radius = self.geometry_double_cone._cosmo.D_A(
            0., z) * self.angle_radius * self.arcsec
        npt.assert_almost_equal(radius_physical, radius, 0)

        comoving_radius = self.geometry_double_cone.angle_to_comovingradius(
            self.angle_radius, z)
        npt.assert_almost_equal(comoving_radius, radius_physical * (1 + z), 3)

        z = 1
        radius_physical = self.geometry_double_cone.angle_to_physicalradius(
            self.angle_radius, z)
        radius = self.geometry_double_cone._cosmo.D_A(
            0., z) * self.angle_radius * self.arcsec
        npt.assert_almost_equal(radius_physical, radius, 0)

        comoving_radius = self.geometry_double_cone.angle_to_comovingradius(
            self.angle_radius, z)
        npt.assert_almost_equal(comoving_radius, radius_physical * (1 + z), 3)

        z = 1.25
        radius_physical = self.geometry_double_cone.angle_to_physicalradius(
            self.angle_radius, z)
        D_dz = self.geometry_double_cone._cosmo.D_A(self.zlens, z)
        D_s = self.geometry_double_cone._cosmo.D_A(0, self.zsource)
        D_z = self.geometry_double_cone._cosmo.D_A(0, z)
        D_ds = self.geometry_double_cone._cosmo.D_A(self.zlens, self.zsource)

        rescale = 1 - self._angle_pad * D_dz * D_s / (D_z * D_ds)
        radius = self.geometry_double_cone._cosmo.D_A(
            0., z) * self.angle_radius * self.arcsec * rescale

        npt.assert_almost_equal(radius_physical, radius, 0)

        comoving_radius = self.geometry_double_cone.angle_to_comovingradius(
            self.angle_radius, z)
        npt.assert_almost_equal(comoving_radius, radius_physical * (1 + z), 3)

    def test_volume(self):

        cone_arcsec = 3
        radius = cone_arcsec * 0.5
        angle_pad = 0.7
        zlens = 1.
        zsrc = 1.8
        geo = Geometry(self.cosmo,
                       zlens,
                       zsrc,
                       cone_arcsec,
                       'DOUBLE_CONE',
                       angle_pad=angle_pad)
        astropy = geo._cosmo.astropy

        delta_z = 1e-3

        dV_pyhalo = geo.volume_element_comoving(0.6, delta_z)
        dV = astropy.differential_comoving_volume(0.6).value

        dV_astropy = dV * delta_z
        steradian = np.pi * (radius * self.arcsec)**2
        npt.assert_almost_equal(dV_astropy * steradian, dV_pyhalo, 5)

        angle_scale = geo.rendering_scale(1.3)
        dV_pyhalo = geo.volume_element_comoving(1.3, delta_z)
        dV = astropy.differential_comoving_volume(1.3).value
        dV_astropy = dV * delta_z
        steradian = np.pi * (radius * angle_scale * self.arcsec)**2
        npt.assert_almost_equal(dV_astropy * steradian, dV_pyhalo, 5)

    def test_total_volume(self):

        cone_arcsec = 4
        radius_radians = cone_arcsec * 0.5 * self.cosmo.arcsec
        geo = Geometry(self.cosmo,
                       0.5,
                       1.5,
                       cone_arcsec,
                       'DOUBLE_CONE',
                       angle_pad=1.)
        volume_pyhalo = 0
        z = np.linspace(0.0, 1.5, 200)
        for i in range(0, len(z) - 1):
            delta_z = z[i + 1] - z[i]
            volume_pyhalo += geo.volume_element_comoving(z[i], delta_z)

        ds = self.cosmo.D_C_z(1.5)
        dz = self.cosmo.D_C_z(0.5)
        volume_true = 1. / 3 * np.pi * radius_radians**2 * dz**2 * ds
        npt.assert_almost_equal(volume_true, volume_pyhalo, 3)
Beispiel #14
0
    def setup(self):

        zlens, zsource = 0.4, 2.

        masses = [10**9.04, 10**8.2, 10**7.345, 10**7, 10**6.05, 10**7, 10**7]
        x = [0.5, 0.1, -0.9, -1.4, 1.2, 0., -1.]
        y = [0., 0.9, -1.4, -1., -0.4, 1., 0.9]
        redshifts = [0.1, 0.2, 0.3, zlens, zlens, 0.94, 0.94]
        subflags = [False, False, False, True, True, False, False]
        r3d = [100] * len(masses)
        mdefs_TNFW = ['TNFW'] * len(masses)
        #
        self.x = x
        self.y = y
        self.masses = masses
        self.redshifts = redshifts
        self.subflags = subflags
        self.r3d = r3d
        self.mdefs = mdefs_TNFW

        masses2 = [10**6.34, 10**9.2, 10**8.36]
        x2 = [1.5, 0.15, -1.9]
        y2 = [0.2, 0.3, -0.44]
        redshifts2 = [zlens, 0.4, 1.9]
        subflags2 = [True, False, False]
        r3d2 = [100] * len(masses2)

        profile_args_TNFW = {
            'mc_model': 'diemer19',
            'c_scatter': False,
            'c_scatter_dex': 0.1
        }
        cosmo = Cosmology()
        halo_mass_function = LensingMassFunction(cosmo,
                                                 zlens,
                                                 zsource,
                                                 10**6,
                                                 10**9,
                                                 6.,
                                                 m_pivot=10**8)
        self.halo_mass_function = halo_mass_function

        kwargs_cdm = {
            'zmin': 0.01,
            'zmax': 1.98,
            'log_mc': None,
            'log_mlow': 6.,
            'log_mhigh': 9.,
            'host_m200': 10**13,
            'LOS_normalization': 2000.,
            'LOS_normalization_mass_sheet': 1.,
            'draw_poisson': False,
            'log_mass_sheet_min': 7.,
            'log_mass_sheet_max': 10.,
            'kappa_scale': 1.,
            'delta_power_law_index': 0.,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'm_pivot': 10**8,
            'cone_opening_angle': 6.,
            'mass_function_LOS_type': 'POWER_LAW'
        }
        kwargs_cdm_2 = {
            'zmin': 0.01,
            'zmax': 1.98,
            'log_mc': None,
            'log_mlow': 6.,
            'log_mhigh': 9.,
            'host_m200': 10**13,
            'LOS_normalization': 2000.,
            'LOS_normalization_mass_sheet': 1.,
            'draw_poisson': False,
            'log_mass_sheet_min': 7.,
            'log_mass_sheet_max': 10.,
            'kappa_scale': 1.,
            'delta_power_law_index': 0.,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'm_pivot': 10**8,
            'cone_opening_angle': 6.,
            'subtract_exact_mass_sheets': True,
            'mass_function_LOS_type': 'POWER_LAW'
        }

        kwargs_cdm.update(profile_args_TNFW)
        self.kwargs_cdm = kwargs_cdm
        self.kwargs_cdm_2 = kwargs_cdm_2

        lens_plane_redshifts = np.append(np.arange(0.01, 0.5, 0.02),
                                         np.arange(0.5, 1.5, 0.02))
        delta_zs = []
        for i in range(0, len(lens_plane_redshifts) - 1):
            delta_zs.append(lens_plane_redshifts[i + 1] -
                            lens_plane_redshifts[i])
        delta_zs.append(1.5 - lens_plane_redshifts[-1])

        geometry = Geometry(cosmo, 0.5, 1.5, 6., 'DOUBLE_CONE')
        lens_cosmo = LensCosmo(zlens, zsource, cosmo)
        self.lens_cosmo = lens_cosmo
        halo_population = HaloPopulation(['LINE_OF_SIGHT'], self.kwargs_cdm,
                                         lens_cosmo, geometry,
                                         halo_mass_function,
                                         lens_plane_redshifts, delta_zs)

        self.rendering_classes = halo_population.rendering_classes

        mdef = ['NFW'] * len(masses)
        self.realization_cdm = Realization(
            masses,
            x,
            y,
            r3d,
            mdef,
            redshifts,
            subflags,
            lens_cosmo,
            halos=None,
            kwargs_realization=self.kwargs_cdm_2,
            mass_sheet_correction=True,
            rendering_classes=self.rendering_classes,
            geometry=geometry)

        mdef = ['PT_MASS'] * len(masses)
        self.realization_cdm2 = Realization(
            masses2,
            x2,
            y2,
            r3d2,
            mdef,
            redshifts2,
            subflags2,
            lens_cosmo,
            halos=None,
            kwargs_realization=self.kwargs_cdm,
            mass_sheet_correction=True,
            rendering_classes=self.rendering_classes,
            geometry=geometry)

        mdef = ['PJAFFE'] * len(masses)
        self.realization_cdm3 = Realization(
            masses2,
            x2,
            y2,
            r3d2,
            mdef,
            redshifts2,
            subflags2,
            lens_cosmo,
            halos=None,
            kwargs_realization=self.kwargs_cdm,
            mass_sheet_correction=True,
            rendering_classes=self.rendering_classes,
            geometry=geometry)

        self.halos_cdm = self.realization_cdm.halos

        halo_tags = []
        for halo in self.realization_cdm.halos:
            halo_tags.append(halo.unique_tag)
        self.halo_tags = halo_tags
        halo_tags = []
        for halo in self.realization_cdm2.halos:
            halo_tags.append(halo.unique_tag)
        self.halo_tags2 = halo_tags
        self.real_1_data = [x, y, masses, redshifts, subflags, redshifts]
        self.real_2_data = [x2, y2, masses2, redshifts2, subflags2, redshifts2]
Beispiel #15
0
    def setup(self):
        zlens, zsource = 0.5, 2.
        zmin = 0.01
        zmax = 1.98
        log_mlow = 6.
        log_mhigh = 9.
        host_m200 = 10**13
        LOS_normalization = 1.
        draw_poisson = False
        log_mass_sheet_min = 7.
        log_mass_sheet_max = 10.
        kappa_scale = 1.
        delta_power_law_index = -0.1
        delta_power_law_index_coupling = 0.5
        cone_opening_angle = 6.
        m_pivot = 10**8
        sigma_sub = 0.1
        power_law_index = -1.9
        subhalo_spatial_distribution = 'HOST_NFW'

        kwargs_cdm = {
            'zmin': zmin,
            'zmax': zmax,
            'log_mc': None,
            'log_mlow': log_mlow,
            'sigma_sub': sigma_sub,
            'c_scale': None,
            'c_power': None,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'c_scatter_dex': 0.2,
            'log_mhigh': log_mhigh,
            'mdef_los': 'TNFW',
            'host_m200': host_m200,
            'LOS_normalization': LOS_normalization,
            'draw_poisson': draw_poisson,
            'subhalo_spatial_distribution': subhalo_spatial_distribution,
            'log_mass_sheet_min': log_mass_sheet_min,
            'log_mass_sheet_max': log_mass_sheet_max,
            'kappa_scale': kappa_scale,
            'power_law_index': power_law_index,
            'delta_power_law_index': delta_power_law_index,
            'delta_power_law_index_coupling': delta_power_law_index_coupling,
            'm_pivot': m_pivot,
            'cone_opening_angle': cone_opening_angle,
            'subhalo_mass_sheet_scale': 1.,
            'subhalo_convergence_correction_profile': 'NFW',
            'r_tidal': '0.5Rs'
        }

        pyhalo = pyHalo(zlens, zsource)
        self.realization_cdm = pyhalo.render(['TWO_HALO'], kwargs_cdm)[0]

        lens_plane_redshifts, delta_zs = pyhalo.lens_plane_redshifts(
            kwargs_cdm)

        cosmo = Cosmology()
        self.lens_plane_redshifts = lens_plane_redshifts
        self.delta_zs = delta_zs
        self.halo_mass_function = LensingMassFunction(
            cosmo,
            zlens,
            zsource,
            kwargs_cdm['log_mlow'],
            kwargs_cdm['log_mhigh'],
            kwargs_cdm['cone_opening_angle'],
            m_pivot=kwargs_cdm['m_pivot'],
            geometry_type='DOUBLE_CONE')
        self.geometry = Geometry(cosmo, zlens, zsource,
                                 kwargs_cdm['cone_opening_angle'],
                                 'DOUBLE_CONE')
        self.lens_cosmo = LensCosmo(zlens, zsource, cosmo)

        self.kwargs_cdm = kwargs_cdm

        self.rendering_class = TwoHaloContribution(
            kwargs_cdm, self.halo_mass_function, self.geometry,
            self.lens_cosmo, self.lens_plane_redshifts, self.delta_zs)
    def add_primordial_black_holes(self, pbh_mass_fraction, kwargs_pbh_mass_function, mass_fraction_in_halos,
                                   x_image_interp_list, y_image_interp_list, r_max_arcsec, arcsec_per_pixel=0.005):

        """
        This routine renders populations of primordial black holes modeled as point masses along the line of sight.
        The population of objects includes a smoothly distributed component, and a component that is clustered according
        to the population of halos generated in the instance of Realization used to instantiate the class.

        :param pbh_mass_fraction: the mass fraction of dark matter contained in primordial black holes
        :param kwargs_pbh_mass_function: keyword arguments for the PBH mass function
        :param mass_fraction_in_halos: the fraction of dark matter mass contained in halos in the mass range
        used to generate the instance of realization used to instantiate the class
        :param x_image_interp_list: a list of interp1d functions that return the angular x coordinate of a light ray
        given a comoving distance
        :param y_image_interp_list: a list of interp1d functions that return the angular y coordinate of a light ray
        given a comoving distance
        :param r_max_arcsec: the radius of the rendering region in arcsec
        :param arcsec_per_pixel: the resolution of the grid used to compute the population of PBH whose spatial
        distribution tracks the dark matter density along the LOS specific by the instance of Realization used to
        instantiate the class
        :return: a new instance of Realization that contains primordial black holes modeled as point masses
        """
        mass_definition = 'PT_MASS'
        plane_redshifts = self._realization.unique_redshifts
        delta_z = []
        for i, zi in enumerate(plane_redshifts[0:-1]):
            delta_z.append(plane_redshifts[i + 1] - plane_redshifts[i])
        delta_z.append(self._realization.lens_cosmo.z_source - plane_redshifts[-1])

        geometry = Geometry(self._realization.lens_cosmo.cosmo,
                                                     self._realization.lens_cosmo.z_lens,
                                                     self._realization.lens_cosmo.z_source,
                                                     2 * r_max_arcsec,
                                                     'DOUBLE_CONE')

        mass_fraction_smooth = (1 - mass_fraction_in_halos) * pbh_mass_fraction
        mass_fraction_clumpy = pbh_mass_fraction * mass_fraction_in_halos

        masses = np.array([])
        xcoords = np.array([])
        ycoords = np.array([])
        redshifts = np.array([])

        for x_image_interp, y_image_interp in zip(x_image_interp_list, y_image_interp_list):
            for zi, delta_zi in zip(plane_redshifts, delta_z):

                d = geometry._cosmo.D_C_transverse(zi)
                angle_x, angle_y = x_image_interp(d), y_image_interp(d)
                rendering_radius = r_max_arcsec * geometry.rendering_scale(zi)
                spatial_distribution_model_smooth = Uniform(rendering_radius, geometry)

                if kwargs_pbh_mass_function['mass_function_type'] == 'DELTA':
                    rho_smooth = mass_fraction_smooth * self._realization.lens_cosmo.cosmo.rho_dark_matter_crit
                    volume = geometry.volume_element_comoving(zi, delta_zi)
                    mass_function_smooth = DeltaFunction(10 ** kwargs_pbh_mass_function['logM'],
                                                         volume, rho_smooth)
                else:
                    raise Exception('no mass function type for PBH currently implemented besides DELTA')

                m_smooth = mass_function_smooth.draw()
                if len(m_smooth) > 0:
                    kpc_per_asec = geometry.kpc_per_arcsec(zi)
                    x_kpc, y_kpc = spatial_distribution_model_smooth.draw(len(m_smooth), zi,
                                                                          center_x=angle_x, center_y=angle_y)
                    x_arcsec, y_arcsec = x_kpc / kpc_per_asec, y_kpc / kpc_per_asec
                    masses = np.append(masses, m_smooth)
                    xcoords = np.append(xcoords, x_arcsec)
                    ycoords = np.append(ycoords, y_arcsec)
                    redshifts = np.append(redshifts, np.array([zi] * len(m_smooth)))

        mdefs = [mass_definition] * len(masses)
        r3d = np.array([None] * len(masses))
        subhalo_flag = [False] * len(masses)
        realization_smooth = Realization(masses, xcoords, ycoords, r3d, mdefs, redshifts, subhalo_flag,
                                          self._realization.lens_cosmo, kwargs_realization=self._realization._prof_params)

        kwargs_pbh_mass_function['mass_fraction'] = mass_fraction_clumpy
        realization_with_clustering = self.add_correlated_structure(kwargs_pbh_mass_function, mass_definition, x_image_interp_list, y_image_interp_list,
                                                        r_max_arcsec, arcsec_per_pixel)

        return realization_with_clustering.join(realization_smooth)
Beispiel #17
0
class TestRenderedPopulations(object):
    def setup(self):

        zlens, zsource = 0.5, 2.
        zmin = 0.01
        zmax = 1.98
        log_mlow = 6.
        log_mhigh = 9.
        host_m200 = 10**13
        LOS_normalization = 100.
        draw_poisson = False
        log_mass_sheet_min = 7.
        log_mass_sheet_max = 10.
        kappa_scale = 1.
        delta_power_law_index = -0.17
        delta_power_law_index_coupling = 0.7
        cone_opening_angle = 6.
        m_pivot = 10**8
        sigma_sub = 0.6
        power_law_index = -1.8
        subhalo_spatial_distribution = 'HOST_NFW'

        kwargs_cdm = {
            'zmin': zmin,
            'zmax': zmax,
            'log_mc': None,
            'log_mlow': log_mlow,
            'sigma_sub': sigma_sub,
            'c_scale': None,
            'c_power': None,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'c_scatter_dex': 0.2,
            'log_mhigh': log_mhigh,
            'host_m200': host_m200,
            'LOS_normalization': LOS_normalization,
            'draw_poisson': draw_poisson,
            'subhalo_spatial_distribution': subhalo_spatial_distribution,
            'log_mass_sheet_min': log_mass_sheet_min,
            'log_mass_sheet_max': log_mass_sheet_max,
            'kappa_scale': kappa_scale,
            'power_law_index': power_law_index,
            'delta_power_law_index': delta_power_law_index,
            'delta_power_law_index_coupling': delta_power_law_index_coupling,
            'm_pivot': m_pivot,
            'cone_opening_angle': cone_opening_angle,
            'subhalo_mass_sheet_scale': 1.,
            'subhalo_convergence_correction_profile': 'NFW',
            'r_tidal': '0.5Rs',
            'mdef_subs': 'TNFW',
            'mdef_los': 'TNFW'
        }

        kwargs_wdm = deepcopy(kwargs_cdm)

        log_mc = 7.1
        a_wdm = 1.
        b_wdm = 0.8
        c_wdm = -1.3
        kwargs_wdm['log_mc'] = log_mc
        kwargs_wdm['a_wdm'] = a_wdm
        kwargs_wdm['b_wdm'] = b_wdm
        kwargs_wdm['c_wdm'] = c_wdm
        kwargs_wdm['c_scale'] = 60.
        kwargs_wdm['c_power'] = -0.17

        pyhalo = pyHalo(zlens, zsource)
        lens_plane_redshifts, delta_zs = pyhalo.lens_plane_redshifts(
            kwargs_cdm)
        cosmo = Cosmology()
        self.lens_plane_redshifts = lens_plane_redshifts
        self.delta_zs = delta_zs
        self.halo_mass_function = LensingMassFunction(
            cosmo,
            zlens,
            zsource,
            kwargs_cdm['log_mlow'],
            kwargs_cdm['log_mhigh'],
            kwargs_cdm['cone_opening_angle'],
            m_pivot=kwargs_cdm['m_pivot'],
            geometry_type='DOUBLE_CONE',
            use_lookup_table=True)
        self.geometry = Geometry(cosmo, zlens, zsource,
                                 kwargs_cdm['cone_opening_angle'],
                                 'DOUBLE_CONE')
        self.lens_cosmo = LensCosmo(zlens, zsource, cosmo)

        self.kwargs_cdm = kwargs_cdm
        self.kwargs_wdm = kwargs_wdm

        pyhalo = pyHalo(zlens, zsource)
        model_list_field = ['LINE_OF_SIGHT']
        model_list_sub = ['SUBHALOS']

        self.realization_cdm = pyhalo.render(model_list_sub + model_list_field,
                                             kwargs_cdm)[0]
        self.realization_cdm_field = pyhalo.render(model_list_field,
                                                   kwargs_cdm)[0]
        self.realization_wdm_field = pyhalo.render(model_list_field,
                                                   kwargs_wdm)[0]
        self.realization_wdm_subhalos = pyhalo.render(model_list_sub,
                                                      kwargs_wdm)[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)

    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)

    def test_wdm_mass_function(self):

        mass_bins = np.linspace(6, 9, 20)
        halo_masses_wdm = [
            halo.mass for halo in self.realization_wdm_field.halos
        ]
        log_halo_mass = np.log10(halo_masses_wdm)
        h_wdm, logM = np.histogram(log_halo_mass, bins=mass_bins)
        logmstep = (logM[1] - logM[0]) / 2
        logM = logM[0:-1] + logmstep

        mass_bins = np.linspace(6, 9, 20)
        halo_masses_cdm = [
            halo.mass for halo in self.realization_cdm_field.halos
        ]
        log_halo_mass = np.log10(halo_masses_cdm)
        h_cdm, _ = np.histogram(log_halo_mass, bins=mass_bins)

        suppression_factor = WDM_suppression(
            10**logM,
            10**self.kwargs_wdm['log_mc'],
            self.kwargs_wdm['a_wdm'],
            self.kwargs_wdm['b_wdm'],
            self.kwargs_wdm['c_wdm'],
        )

        for i in range(0, 10):
            ratio = h_wdm[i] / h_cdm[i]
            npt.assert_almost_equal(ratio, suppression_factor[i], 1)

    def test_cdm_mass_function(self):

        mass_bins = np.linspace(6, 9., 20)
        halo_masses_sub = []
        halo_masses_field = []
        for halo in self.realization_cdm.halos:
            if halo.is_subhalo:
                halo_masses_sub.append(halo.mass)
            else:
                halo_masses_field.append(halo.mass)

        log_halo_mass_sub = np.log10(halo_masses_sub)
        log_halo_mass_field = np.log10(halo_masses_field)
        h_sub, logM_sub = np.histogram(log_halo_mass_sub, bins=mass_bins)
        h_field, logM_field = np.histogram(log_halo_mass_field, bins=mass_bins)

        logN_sub = np.log10(h_sub)
        logN_field = np.log10(h_field)

        slope_theory = -0.9 + self.kwargs_cdm['delta_power_law_index']
        slope = np.polyfit(logM_field[0:-1], logN_field, 1)[0]
        npt.assert_array_less(abs(1 - slope / slope_theory), 0.05, 2)

        slope_theory = (1+self.kwargs_cdm['power_law_index']) + self.kwargs_cdm['delta_power_law_index'] * \
                       self.kwargs_cdm['delta_power_law_index_coupling']
        slope = np.polyfit(logM_sub[0:-1], logN_sub, 1)[0]
        npt.assert_array_less(abs(1 - slope / slope_theory), 0.05, 2)
Beispiel #18
0
    def setup(self):

        zlens, zsource = 0.5, 2.
        zmin = 0.01
        zmax = 1.98
        log_mlow = 6.
        log_mhigh = 9.
        host_m200 = 10**13
        LOS_normalization = 100.
        draw_poisson = False
        log_mass_sheet_min = 7.
        log_mass_sheet_max = 10.
        kappa_scale = 1.
        delta_power_law_index = -0.17
        delta_power_law_index_coupling = 0.7
        cone_opening_angle = 6.
        m_pivot = 10**8
        sigma_sub = 0.6
        power_law_index = -1.8
        subhalo_spatial_distribution = 'HOST_NFW'

        kwargs_cdm = {
            'zmin': zmin,
            'zmax': zmax,
            'log_mc': None,
            'log_mlow': log_mlow,
            'sigma_sub': sigma_sub,
            'c_scale': None,
            'c_power': None,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'c_scatter_dex': 0.2,
            'log_mhigh': log_mhigh,
            'host_m200': host_m200,
            'LOS_normalization': LOS_normalization,
            'draw_poisson': draw_poisson,
            'subhalo_spatial_distribution': subhalo_spatial_distribution,
            'log_mass_sheet_min': log_mass_sheet_min,
            'log_mass_sheet_max': log_mass_sheet_max,
            'kappa_scale': kappa_scale,
            'power_law_index': power_law_index,
            'delta_power_law_index': delta_power_law_index,
            'delta_power_law_index_coupling': delta_power_law_index_coupling,
            'm_pivot': m_pivot,
            'cone_opening_angle': cone_opening_angle,
            'subhalo_mass_sheet_scale': 1.,
            'subhalo_convergence_correction_profile': 'NFW',
            'r_tidal': '0.5Rs',
            'mdef_subs': 'TNFW',
            'mdef_los': 'TNFW'
        }

        kwargs_wdm = deepcopy(kwargs_cdm)

        log_mc = 7.1
        a_wdm = 1.
        b_wdm = 0.8
        c_wdm = -1.3
        kwargs_wdm['log_mc'] = log_mc
        kwargs_wdm['a_wdm'] = a_wdm
        kwargs_wdm['b_wdm'] = b_wdm
        kwargs_wdm['c_wdm'] = c_wdm
        kwargs_wdm['c_scale'] = 60.
        kwargs_wdm['c_power'] = -0.17

        pyhalo = pyHalo(zlens, zsource)
        lens_plane_redshifts, delta_zs = pyhalo.lens_plane_redshifts(
            kwargs_cdm)
        cosmo = Cosmology()
        self.lens_plane_redshifts = lens_plane_redshifts
        self.delta_zs = delta_zs
        self.halo_mass_function = LensingMassFunction(
            cosmo,
            zlens,
            zsource,
            kwargs_cdm['log_mlow'],
            kwargs_cdm['log_mhigh'],
            kwargs_cdm['cone_opening_angle'],
            m_pivot=kwargs_cdm['m_pivot'],
            geometry_type='DOUBLE_CONE',
            use_lookup_table=True)
        self.geometry = Geometry(cosmo, zlens, zsource,
                                 kwargs_cdm['cone_opening_angle'],
                                 'DOUBLE_CONE')
        self.lens_cosmo = LensCosmo(zlens, zsource, cosmo)

        self.kwargs_cdm = kwargs_cdm
        self.kwargs_wdm = kwargs_wdm

        pyhalo = pyHalo(zlens, zsource)
        model_list_field = ['LINE_OF_SIGHT']
        model_list_sub = ['SUBHALOS']

        self.realization_cdm = pyhalo.render(model_list_sub + model_list_field,
                                             kwargs_cdm)[0]
        self.realization_cdm_field = pyhalo.render(model_list_field,
                                                   kwargs_cdm)[0]
        self.realization_wdm_field = pyhalo.render(model_list_field,
                                                   kwargs_wdm)[0]
        self.realization_wdm_subhalos = pyhalo.render(model_list_sub,
                                                      kwargs_wdm)[0]
class CorrelatedStructure(RenderingClassBase):
    """
    This class generates a population of halos with a spatial distribution that tracks the dark matter density in halos
    at each lens plane
    """
    def __init__(self, kwargs_rendering, realization, r_max_arcsec):
        """

        :param kwargs_rendering: keyword arguments that specify the mass function model
        :param realization: an instance of Realization used to compute the convergence at each lens plane
        :param r_max_arcsec: the radius of area at which the halos are rendered
        """

        self.kwargs_rendering = kwargs_rendering
        self._realization = realization
        self.cylinder_geometry = Geometry(
            self._realization.lens_cosmo.cosmo,
            self._realization.lens_cosmo.z_lens,
            self._realization.lens_cosmo.z_source, 2 * r_max_arcsec,
            'DOUBLE_CONE')

        self.spatial_distribution_model = Correlated2D(self.cylinder_geometry)
        self._rmax = r_max_arcsec

    def render(self, x_center_interp_list, y_center_interp_list,
               arcsec_per_pixel):
        """
        Generates halo masses and positions for correlated structure along the line of sight around
        the angular coordinate of each light ray

        :param x_center_interp_list: a list of interp1d functions that return the x angular position of a
        ray given a comoving distance
        :param y_center_interp_list: a list of interp1d functions that return the y angular position of a
        ray given a comoving distance
        :param arcsec_per_pixel: sets the spatial resolution for the rendering of correlated structure
        :return: mass (in Msun), x (arcsec), y (arcsec), r3d (kpc), redshift
        """

        masses = np.array([])
        x = np.array([])
        y = np.array([])
        redshifts = np.array([])

        plane_redshifts = self._realization.unique_redshifts
        delta_z = []
        rescale_inds = []
        rescale_factor = 1.

        for i, zi in enumerate(plane_redshifts[0:-1]):
            delta_z.append(plane_redshifts[i + 1] - plane_redshifts[i])
        delta_z.append(self._realization.lens_cosmo.z_source -
                       plane_redshifts[-1])

        for i, zi in enumerate(plane_redshifts[0:-1]):
            delta_z.append(plane_redshifts[i + 1] - plane_redshifts[i])
        delta_z.append(self._realization.lens_cosmo.z_source -
                       plane_redshifts[-1])

        for x_image_interp, y_image_interp in zip(x_center_interp_list,
                                                  y_center_interp_list):

            for z, dz in zip(plane_redshifts, delta_z):

                if dz > 0.2:
                    print(
                        'WARNING: redshift spacing is possibly too large due to the few number of halos '
                        'in the lens model!')

                rendering_radius = self._rmax * self.cylinder_geometry.rendering_scale(
                    z)
                d = self.cylinder_geometry._cosmo.D_C_transverse(z)
                x_angle = x_image_interp(d)
                y_angle = y_image_interp(d)
                _m, _x, _y, halo_inds, rescale_factor = self.render_at_z(
                    z, x_angle, y_angle, rendering_radius, arcsec_per_pixel)

                if len(_m) > 0:
                    _z = np.array([z] * len(_x))
                    masses = np.append(masses, _m)
                    x = np.append(x, _x)
                    y = np.append(y, _y)
                    redshifts = np.append(redshifts, _z)
                    rescale_inds += halo_inds

        subhalo_flag = [False] * len(masses)
        r3d = np.array([None] * len(masses))

        return masses, x, y, r3d, redshifts, subhalo_flag, rescale_inds, rescale_factor

    def render_at_z(self, z, angular_coordinate_x, angular_coordinate_y,
                    rendering_radius, arcsec_per_pixel):
        """

        :param n: number of objects to render
        :param z: redshift
        :param angular_coordinate_x: the angular coordinate in arcsec of a light ray at redshift z
        :param angular_coordinate_y: the angular coordinate in arcsec of a light ray at redshift z
        :param rendering_radius: the angular radius inside which to render objects
        :param arcsec_per_pixel: sets the spatial resolution for the rendering of correlated structure
        :return: the positions in arcsec of the rendered objects
        """

        kpc_per_asec = self.cylinder_geometry.kpc_per_arcsec(z)
        pdf, mass_in_area, halo_indexes = self._kappa_at_lens_plane(
            z, angular_coordinate_x, angular_coordinate_y, rendering_radius,
            arcsec_per_pixel)

        if np.sum(pdf) == 0:
            return np.array([]), np.array([]), np.array([]), [], 1.

        m, rescale_factor = self.render_masses_at_z(mass_in_area)
        n_halos = len(m)
        if n_halos > 0:
            x_kpc, y_kpc = self.spatial_distribution_model.draw(
                n_halos, rendering_radius, pdf, z, angular_coordinate_x,
                angular_coordinate_y)

            x_arcsec = x_kpc / kpc_per_asec
            y_arcsec = y_kpc / kpc_per_asec
            return m, x_arcsec, y_arcsec, halo_indexes, rescale_factor
        else:
            return np.array([]), np.array([]), np.array([]), [], 1.

    def render_masses_at_z(self, mass_in_area):
        """
        :param z: redshift at which to render masses
        :param delta_z: thickness of the redshift slice
        :return: halo masses at the desired redshift in units Msun
        """

        if self.kwargs_rendering['mass_function_type'] == 'DELTA':

            rescale_factor = 1. - self.kwargs_rendering['mass_fraction']
            rho = self.kwargs_rendering['mass_fraction'] * mass_in_area
            volume = 1.
            mass = 10**self.kwargs_rendering['logM']
            mass_function = DeltaFunction(mass, volume, rho)

        else:
            raise Exception(
                'no other mass function for correlated structure currently implemented'
            )

        return mass_function.draw(), rescale_factor

    def _kappa_at_lens_plane(self, z, angular_coordinate_x,
                             angular_coordinate_y, rendering_radius,
                             arcsec_per_pixel):

        realization_at_plane, halo_indexes = realization_at_z(
            self._realization,
            z,
            angular_coordinate_x,
            angular_coordinate_y,
            2 * rendering_radius,
            mass_sheet_correction=False)

        lens_model_list, _, kwargs_lens, numerical_interp = realization_at_plane.lensing_quantities(
            add_mass_sheet_correction=False)

        if len(lens_model_list) == 0:
            return np.array([]), np.array([]), []

        lens_model = LensModel(lens_model_list,
                               numerical_alpha_class=numerical_interp)
        npix = int(2 * rendering_radius / arcsec_per_pixel)
        _r = np.linspace(-rendering_radius, rendering_radius, npix)
        xx, yy = np.meshgrid(_r, _r)
        shape0 = xx.shape
        xx, yy = xx.ravel(), yy.ravel()
        rr = np.sqrt(xx**2 + yy**2)
        inds_zero = np.where(rr > rendering_radius)[0].ravel()

        pdf = lens_model.kappa(xx + angular_coordinate_x,
                               yy + angular_coordinate_y, kwargs_lens)
        pdf[inds_zero] = 0.
        inds_nan = np.where(np.isnan(pdf))
        pdf[inds_nan] = 0.
        npixels = len(inds_zero)

        rendering_radius_mpc = rendering_radius * (
            0.001 * self.cylinder_geometry.kpc_per_arcsec(z))
        effective_area = np.pi * rendering_radius_mpc**2 / npixels
        mass_in_area = self._mass_in_area(pdf, z, effective_area)
        return pdf.reshape(shape0), mass_in_area, halo_indexes

    def _mass_in_area(self, kappa_pdf, z, area):

        sigma_crit = self._realization.lens_cosmo.get_sigma_crit_lensing(
            z, self._realization.lens_cosmo.z_source)

        mass_in_area = np.sum(kappa_pdf * sigma_crit) * area

        return mass_in_area

    @staticmethod
    def keys_convergence_sheets(keywords_master):
        return {}

    def convergence_sheet_correction(self, kwargs_mass_sheets=None):

        return [{}], [], []

    @staticmethod
    def keyword_parse_render(keywords_master):

        return {}
Beispiel #20
0
class TestLOS(object):
    def setup(self):
        zlens, zsource = 0.5, 2.
        zmin = 0.01
        zmax = 1.98
        log_mlow = 6.
        log_mhigh = 9.
        host_m200 = 10**13
        LOS_normalization = 1.
        draw_poisson = False
        log_mass_sheet_min = 7.
        log_mass_sheet_max = 10.
        kappa_scale = 1.
        delta_power_law_index = -0.1
        delta_power_law_index_coupling = 0.5
        cone_opening_angle = 6.
        m_pivot = 10**8
        sigma_sub = 0.1
        power_law_index = -1.9
        subhalo_spatial_distribution = 'HOST_NFW'

        kwargs_cdm = {
            'zmin': zmin,
            'zmax': zmax,
            'log_mc': None,
            'log_mlow': log_mlow,
            'sigma_sub': sigma_sub,
            'c_scale': None,
            'c_power': None,
            'a_wdm': None,
            'b_wdm': None,
            'c_wdm': None,
            'c_scatter_dex': 0.2,
            'log_mhigh': log_mhigh,
            'mdef_los': 'TNFW',
            'host_m200': host_m200,
            'LOS_normalization': LOS_normalization,
            'draw_poisson': draw_poisson,
            'subhalo_spatial_distribution': subhalo_spatial_distribution,
            'log_mass_sheet_min': log_mass_sheet_min,
            'log_mass_sheet_max': log_mass_sheet_max,
            'kappa_scale': kappa_scale,
            'power_law_index': power_law_index,
            'delta_power_law_index': delta_power_law_index,
            'delta_power_law_index_coupling': delta_power_law_index_coupling,
            'm_pivot': m_pivot,
            'cone_opening_angle': cone_opening_angle,
            'subhalo_mass_sheet_scale': 1.,
            'subhalo_convergence_correction_profile': 'NFW',
            'r_tidal': '0.5Rs'
        }

        pyhalo = pyHalo(zlens, zsource)
        self.realization_cdm = pyhalo.render(['TWO_HALO'], kwargs_cdm)[0]

        lens_plane_redshifts, delta_zs = pyhalo.lens_plane_redshifts(
            kwargs_cdm)

        cosmo = Cosmology()
        self.lens_plane_redshifts = lens_plane_redshifts
        self.delta_zs = delta_zs
        self.halo_mass_function = LensingMassFunction(
            cosmo,
            zlens,
            zsource,
            kwargs_cdm['log_mlow'],
            kwargs_cdm['log_mhigh'],
            kwargs_cdm['cone_opening_angle'],
            m_pivot=kwargs_cdm['m_pivot'],
            geometry_type='DOUBLE_CONE')
        self.geometry = Geometry(cosmo, zlens, zsource,
                                 kwargs_cdm['cone_opening_angle'],
                                 'DOUBLE_CONE')
        self.lens_cosmo = LensCosmo(zlens, zsource, cosmo)

        self.kwargs_cdm = kwargs_cdm

        self.rendering_class = TwoHaloContribution(
            kwargs_cdm, self.halo_mass_function, self.geometry,
            self.lens_cosmo, self.lens_plane_redshifts, self.delta_zs)

    def test_norm_slope(self):

        delta_z = self.delta_zs[1]
        norm, slope = self.rendering_class._norm_slope(self.lens_cosmo.z_lens,
                                                       delta_z)
        slope_theory = self.halo_mass_function.plaw_index_z(
            self.lens_cosmo.z_lens) + self.kwargs_cdm['delta_power_law_index']
        npt.assert_almost_equal(slope, slope_theory)
        norm_theory_background = self.halo_mass_function.norm_at_z_density(
            self.lens_cosmo.z_lens, slope, self.kwargs_cdm['m_pivot'])
        norm_theory_background *= self.geometry.volume_element_comoving(
            self.lens_cosmo.z_lens, delta_z)
        rmax = self.lens_cosmo.cosmo.D_C_transverse(self.lens_cosmo.z_lens + delta_z) - \
               self.lens_cosmo.cosmo.D_C_transverse(self.lens_cosmo.z_lens)
        boost = self.halo_mass_function.two_halo_boost(
            self.kwargs_cdm['host_m200'], self.lens_cosmo.z_lens, rmax=rmax)
        norm_theory = (boost - 1) * norm_theory_background
        npt.assert_almost_equal(norm_theory, norm)

    def test_rendering(self):

        m = self.rendering_class.render_masses_at_z(self.lens_cosmo.z_lens,
                                                    0.02)
        npt.assert_equal(True, len(m) > 0)

        npt.assert_raises(Exception, self.rendering_class.render_masses_at_z,
                          0.9, 0.02)

        x, y = self.rendering_class.render_positions_at_z(
            self.lens_cosmo.z_lens, 10000)
        rmax = np.max(np.hypot(x, y))
        rmax_theory = 0.5 * self.kwargs_cdm[
            'cone_opening_angle'] * self.geometry.rendering_scale(
                self.lens_cosmo.z_lens)
        npt.assert_array_less(rmax, rmax_theory)

        x, y = self.rendering_class.render_positions_at_z(
            self.lens_cosmo.z_lens, 0)
        npt.assert_equal(True, len(x) == 0)

        m, x, y, r3, redshifts, flag = self.rendering_class.render()
        npt.assert_equal(len(m), len(x))
        npt.assert_equal(len(y), len(r3))

        n = 0
        for z in np.unique(redshifts):
            n += np.sum(redshifts == z)
        npt.assert_equal(True, n == len(m))

        npt.assert_equal(True, len(self.realization_cdm.halos) == len(m))

    def test_convergence_correction(self):

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

        npt.assert_equal(0, len(kwargs_out))
        npt.assert_equal(0, len(profile_names_out))
        npt.assert_equal(0, len(redshifts))

    def test_keys_convergence_sheets(self):

        keywords_out = self.rendering_class.keys_convergence_sheets()
        npt.assert_equal(len(keywords_out), 0)

    def test_keys_rendering(self):

        keywords_out = self.rendering_class.keyword_parse_render(
            self.kwargs_cdm)
        required_keys = [
            'log_mlow', 'log_mhigh', 'host_m200', 'LOS_normalization',
            'draw_poisson', 'delta_power_law_index', 'm_pivot', 'log_mc',
            'a_wdm', 'b_wdm', 'c_wdm'
        ]

        for x in required_keys:
            npt.assert_equal(x in keywords_out.keys(), True)

        kw_cdm = deepcopy(self.kwargs_cdm)
        kw_cdm['log_mc'] = None
        keywords_out = self.rendering_class.keyword_parse_render(kw_cdm)
        npt.assert_equal(keywords_out['a_wdm'] is None, True)
        npt.assert_equal(keywords_out['b_wdm'] is None, True)
        npt.assert_equal(keywords_out['c_wdm'] is None, True)