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