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 solve_from_Mz(M, z, cross_section_type, kwargs_cross_section, z_collapse=10., include_c_scatter=False, c_scatter_add_dex=0., **kwargs_solver): """ This routine solves for the SIDM central density given the normalization of an NFW halo rhos, the scale radius rs, and a specific interaction cross section """ try: from pyHalo.Halos.lens_cosmo import LensCosmo from pyHalo.Cosmology.cosmology import Cosmology cosmo = Cosmology() lens_cosmo = LensCosmo() except: raise Exception( 'error importing pyHalo, which is needed to use this routine') c = lens_cosmo.NFW_concentration(M, z, scatter=include_c_scatter) if include_c_scatter is False and c_scatter_add_dex != 0: c = 10**(np.log10(c) + c_scatter_add_dex) rhos, rs, _ = lens_cosmo.NFW_params_physical(M, c, z) halo_age = cosmo.halo_age(z, z_collapse) if halo_age < 0.: raise Exception( 'the halo age is negative, you have probably specified a collapse redshift < halo redshift' ) return solve_from_NFW_params(rhos, rs, halo_age, cross_section_type, kwargs_cross_section, **kwargs_solver)
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 setup(self): kwargs_cosmo = {'Om0': 0.2} self.cosmo = Cosmology(cosmo_kwargs=kwargs_cosmo) zlens, zsource = 0.3, 1.7 self.lens_cosmo = LensCosmo(zlens, zsource, self.cosmo) self.h = self.cosmo.h self.con = Concentration(self.lens_cosmo) self._colossus_nfw = NFWProfile
def test_interp_ray_paths(self): cosmo = Cosmology() x = [1.4, -1.] y = [-0.4, 0.2] lens_model = LensModel(['SIS'], z_source=2., lens_redshift_list=[0.5], multi_plane=True) kwargs_lens = [{'theta_E': 1., 'center_x': 0., 'center_y': 0.}] interpx, interpy = interpolate_ray_paths(x, y, lens_model, kwargs_lens, 2., terminate_at_source=False, source_x=None, source_y=None, evaluate_at_mean=False) zarray = np.linspace(0., 2., 100) dc = [cosmo.D_C_transverse(zi) for zi in zarray] interpx_mean, interpy_mean = interpolate_ray_paths( x, y, lens_model, kwargs_lens, 2., terminate_at_source=False, source_x=None, source_y=None, evaluate_at_mean=True, cosmo=cosmo) for dci in dc: x, y = 0.5 * (interpx[0](dci) + interpx[1] (dci)), 0.5 * (interpy[0](dci) + interpy[1](dci)) npt.assert_almost_equal(x, interpx_mean[0](dci)) npt.assert_almost_equal(y, interpy_mean[0](dci)) x = [1.4, -1.] y = [-0.4, 0.2] source_x, source_y = 0.2, 0.5 interpx, interpy = interpolate_ray_paths(x, y, lens_model, kwargs_lens, 2., terminate_at_source=True, source_x=source_x, source_y=source_y, evaluate_at_mean=True) npt.assert_almost_equal(interpx[0](dc[-1]), source_x) npt.assert_almost_equal(interpy[0](dc[-1]), source_y)
def __init__(self, zlens, zsrc, clean_up=True, temp_folder=None): self.zmain = zlens self.zsrc = zsrc self.cosmo = Cosmology() self.clean_up = clean_up self.paths = paths if temp_folder is None: self.temp_folder = 'temp/' else: self.temp_folder = temp_folder + '/' self.paths.gravlens_input_path_dump = self.paths.gravlens_input_path + self.temp_folder
def setup(self): cosmo = Cosmology() mlow = 10**6 mhigh = 10**10 zlens = 0.5 zsource = 1.5 cone_opening_angle = 6. m_pivot = 10**8 mass_function_model = 'sheth99' use_lookup_table = True geometry_type = 'DOUBLE_CONE' self.lmf_lookup_ShethTormen = LensingMassFunction( cosmo, zlens, zsource, mlow, mhigh, cone_opening_angle, m_pivot, mass_function_model, use_lookup_table, geometry_type) use_lookup_table = False self.lmf_no_lookup_ShethTormen = LensingMassFunction( cosmo, zlens, zsource, mlow, mhigh, cone_opening_angle, m_pivot, mass_function_model, use_lookup_table, geometry_type) self._m = np.logspace(6., 10, 50) self.cosmo = cosmo self.cone_opening_angle = cone_opening_angle
def write_lookup_table(): def write_to_file(fname, pname, values, mode): with open(fname, mode) as f: f.write(pname + ' = [') for j, val in enumerate(values): f.write(str(val)+', ') f.write(']\n') from pyHalo.Cosmology.cosmology import Cosmology l = LensingMassFunction(Cosmology(), 0.1, 4., 10**7., 10**9, 6., use_lookup_table=False) fname = './lookup_tables/lookup_sheth99.py' with open(fname, 'w') as f: f.write('import numpy as np\n') write_to_file(fname, 'norm_z_dV', np.round(l._norm_z_dV, 12), 'a') write_to_file(fname, 'plaw_index_z', np.round(l._plaw_index_z,2), 'a') with open(fname, 'a') as f: f.write('z_range = np.array([') for zi in l._z_range: f.write(str(np.round(zi,2))+', ') f.write('])\n\n') with open(fname, 'a') as f: f.write('delta_z = '+str(np.round(l._delta_z,2))+'\n\n')
def __init__(self, z_lens=None, z_source=None, cosmology=None): if cosmology is None: from pyHalo.Cosmology.cosmology import Cosmology cosmology = Cosmology() self.cosmo = cosmology self.z_lens, self.z_source = z_lens, z_source # critical density of the universe in M_sun h^2 Mpc^-3 rhoc = un.Quantity(self.cosmo.astropy.critical_density(0), unit=un.Msun / un.Mpc**3).value self.rhoc = rhoc / self.cosmo.h**2 if z_lens is not None and z_source is not None: # critical density for lensing in units M_sun * Mpc ^ -2 self.sigma_crit_lensing = self.get_sigma_crit_lensing( z_lens, z_source) # critical density for lensing in units M_sun * kpc ^ -2 self.sigma_crit_lens_kpc = self.sigma_crit_lensing * (0.001)**2 # critical density for lensing in units M_sun * arcsec ^ -2 at lens redshift self.sigmacrit = self.sigma_crit_lensing * ( 0.001)**2 * self.cosmo.kpc_proper_per_asec(z_lens)**2 # lensing distances self.D_d, self.D_s, self.D_ds = self.cosmo.D_A_z( z_lens), self.cosmo.D_A_z(z_source), self.cosmo.D_A( z_lens, z_source) self._concentration = Concentration(self) self._computed_zacc_pdf = False
def __init__(self, halo_mass, x, y, mdef, z, zlens, zsource, r3d=None, subhalo_flag=False, kwargs_halo={}, cosmo=None): """ Useful for generating a realization with a single or a few user-specified halos. :param halo_mass: mass of the halo in M_sun :param x: halo x coordinate in arcsec :param y: halo y coordinate in arcsec :param mdef: halo mass definition :param z: halo redshift :param zlens: main deflector redshift :param zsource: source redshift :param r3d: three dimensional coordinate of halo inside the host in kpc (only relevant for tidally-truncated subhalos, for field halos this can be None) :param subhalo_flag: bool, sets whether or not a halo is a subhalo :param kwargs_halo: keyword arguments for the halo :param cosmo: an instance of Cosmology(); if none is provided a default cosmology will be used """ if cosmo is None: cosmo = Cosmology() lens_cosmo = LensCosmo(zlens, zsource, cosmo) # these are redundant keywords for a single halo, but we need to specify them anyways kwargs_halo.update({'cone_opening_angle': 6., 'log_mlow': 6., 'log_mhigh': 10.}) super(SingleHalo, self).__init__([halo_mass], [x], [y], [r3d], [mdef], [z], [subhalo_flag], lens_cosmo, kwargs_realization=kwargs_halo, mass_sheet_correction=False)
def reset_redshifts(self, zlens, zsource): self.zlens = zlens self.zsource = zsource self.cosmology = Cosmology(**self._cosmology_kwargs) self.halo_mass_function = None self.geometry = None
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 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)
def setup(self): realization = SingleHalo(10**8, 0., 0., 'TNFW', 0.1, 0.5, 1.2, subhalo_flag=False) zlist = np.arange(0.1, 1.2, 0.05) rmax = 0.3 for i, zi in enumerate(zlist): xi, yi = 0., 0. mi = np.random.uniform(7, 8) single_halo = SingleHalo(10**mi, xi, yi, 'TNFW', zi, 0.5, 1.2, subhalo_flag=False) realization = realization.join(single_halo) cosmo = Cosmology() self.realization = realization self.rmax = rmax zlist = np.arange(0.00, 1.2, 0.02) x_image = [0.] * len(zlist) y_image = [0.] * len(zlist) dlist = [cosmo.D_C_transverse(zi) for zi in zlist] self.x_image_interp_list = [interp1d(dlist, x_image)] self.y_image_interp_list = [interp1d(dlist, y_image)]
def setup(self): mass = 10**7. x = 0.5 y = 1. r3d = np.sqrt(1 + 0.5 ** 2 + 70**2) self.r3d = r3d mdef = 'PJAFFE' self.z = 0.25 sub_flag = True 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 cosmo = Cosmology(cosmo_kwargs=cosmo_params) self.lens_cosmo = LensCosmo(self.z, 2., cosmo) kwargs_suppression = {'c_scale': 10.5, 'c_power': -0.2} suppression_model = 'polynomial' profile_args = {'RocheNorm': 1.2, 'RocheNu': 2/3, 'evaluate_mc_at_zlens': True, 'log_mc': 0., 'kwargs_suppression': kwargs_suppression, 'suppression_model': suppression_model, 'c_scatter': False, 'mc_model': 'diemer19', 'LOS_truncation_factor': 40, 'mc_mdef': '200c', 'c_scatter_dex': 0.1} self.profile_args = profile_args self.mass_subhalo = mass self.subhalo = PJaffeSubhalo(mass, x, y, r3d, mdef, self.z, sub_flag, self.lens_cosmo, profile_args, unique_tag=np.random.rand()) mass_field_halo = 10 ** 7. sub_flag = False self.mass_field_halo = mass_field_halo self.field_halo = PJaffeSubhalo(self.mass_field_halo, x, y, r3d, mdef, self.z, sub_flag, self.lens_cosmo, profile_args, unique_tag=np.random.rand()) self._model_lenstronomy = PJaffe()
def setup(self): mass = 10**8. x = 0.5 y = 1. z = 0.9 r3d = np.sqrt(1 + 0.5**2 + 70**2) self.r3d = r3d mdef = 'GAUSSIAN_KAPPA' self.z = z 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 } cosmo = Cosmology(cosmo_kwargs=cosmo_params) self.lens_cosmo = LensCosmo(self.z, 2., cosmo) profile_args = {'amp': 1, 'sigma': 1, 'center_x': 0, 'center_y': 0} sub_flag = False self.halo = Gaussian(mass, x, y, r3d, mdef, z, sub_flag, self.lens_cosmo, profile_args, unique_tag=np.random.rand())
def setup(self): mass = 1e9 x = 0.5 y = 1. r3d = np.sqrt(1 + 0.5 ** 2 + 70**2) self.r3d = r3d self.z = 0.25 sub_flag = True mdef = 'ULDM' 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 cosmo = Cosmology(cosmo_kwargs=cosmo_params) self.lens_cosmo = LensCosmo(self.z, 2., cosmo) kwargs_suppression = {'c_scale': 60., 'c_power': -0.17} suppression_model = 'polynomial' profile_args = {'RocheNorm': 1.2, 'RocheNu': 2/3, 'evaluate_mc_at_zlens': False, 'log_mc': None, 'kwargs_suppression': kwargs_suppression, 'suppression_model': suppression_model, 'c_scatter': False, 'mc_model': 'diemer19', 'LOS_truncation_factor': 40, 'c_scatter_dex': 0.1, 'mc_mdef': '200c', 'log10_m_uldm':-22, 'uldm_plaw':1/3} self.subhalo = ULDMSubhalo(mass, x, y, r3d, mdef, self.z, sub_flag, self.lens_cosmo, profile_args, unique_tag=np.random.rand()) self.fieldhalo = ULDMFieldHalo(mass, x, y, r3d, mdef, self.z, sub_flag, self.lens_cosmo, profile_args, unique_tag=np.random.rand())
def setup(self): mass = 10**8. x = 0.5 y = 1. r3d = np.sqrt(1 + 0.5**2 + 70**2) self.r3d = r3d mdef = 'coreTNFW' self.z = 0.25 sub_flag = True 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 cosmo = Cosmology(cosmo_kwargs=cosmo_params) self.lens_cosmo = LensCosmo(self.z, 2., cosmo) cross_section_type = 'POWER_LAW' self._cross_norm = 5 cross_section_kwargs = { 'norm': self._cross_norm, 'v_dep': 0.5, 'v_ref': 30. } kwargs_suppression = {'c_scale': 10.5, 'c_power': -0.2} suppression_model = 'polynomial' profile_args = { 'RocheNorm': 1.2, 'RocheNu': 2 / 3, 'evaluate_mc_at_zlens': True, 'log_mc': None, 'kwargs_suppression': kwargs_suppression, 'suppression_model': suppression_model, 'c_scatter': False, 'mc_model': 'diemer19', 'LOS_truncation_factor': 40, 'c_scatter_dex': 0.1, 'mc_mdef': '200c', 'cross_section_type': cross_section_type, 'kwargs_cross_section': cross_section_kwargs, 'numerical_deflection_angle_class': self._deflection_function, 'SIDM_rhocentral_function': self._rho_function } self.profile_args = profile_args self.mass = mass self.subhalo = coreTNFWSubhalo(mass, x, y, r3d, mdef, self.z, sub_flag, self.lens_cosmo, profile_args, unique_tag=np.random.rand()) self.field_halo = coreTNFWFieldHalo(mass, x, y, r3d, mdef, self.z, sub_flag, self.lens_cosmo, profile_args, unique_tag=np.random.rand())
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)
class Magnipy: """ This class is used to specify a lens system and solve the lens equation or optimize a lens model """ def __init__(self, zlens, zsrc, clean_up=True, temp_folder=None): self.zmain = zlens self.zsrc = zsrc self.cosmo = Cosmology() self.clean_up = clean_up self.paths = paths if temp_folder is None: self.temp_folder = 'temp/' else: self.temp_folder = temp_folder + '/' self.paths.gravlens_input_path_dump = self.paths.gravlens_input_path + self.temp_folder def lenstronomy_build(self): return LenstronomyWrap(cosmo=self.cosmo.astropy, z_source=self.zsrc) def print_system(self, system_index, component_index=None): system = self.lens_system[system_index] if component_index is not None: system.lens_components[component_index].print_args() else: for component in system.lens_components: component.print_args() def update_system(self, lens_system, newkwargs, method): if lens_system.lens_components[0].other_args['name'] == 'SERSIC_NFW': raise Exception('not yet implemented') else: if method == 'lenstronomy': lens_system.lens_components[0].update(method=method, is_shear=False, **newkwargs[0]) lens_system.lens_components[0].update(method=method, is_shear=True, **newkwargs[1]) elif method == 'lensmodel': for val in [True, False]: lens_system.lens_components[0].update(method=method, is_shear=val, **newkwargs) return lens_system def build_system(self, main=None, realization=None, multiplane=None, LOS_mass_sheet_front=7.7, LOS_mass_sheet_back=8, satellites=None): assert multiplane is not None newsystem = LensSystem(main, satellites=satellites, realization=realization, multiplane=multiplane, LOS_mass_sheet_front=LOS_mass_sheet_front, LOS_mass_sheet_back=LOS_mass_sheet_back) return newsystem def _optimize_4imgs_lenstronomy(self, lens_systems, data2fit=None, tol_source=None, tol_mag=None, tol_centroid=None, centroid_0=None, n_particles=50, n_iterations=400, res=None, source_shape='GAUSSIAN', source_size_kpc=None, polar_grid=None, optimizer_routine=str, verbose=bool, re_optimize=False, particle_swarm=True, restart=1, constrain_params=None, return_ray_path=False, pso_convergence_mean=None, pso_compute_magnification=None, tol_simplex_params=None, tol_simplex_func=None, simplex_n_iter=None, optimizer_kwargs={}, finite_source_magnification=True, chi2_mode='source', tol_image=None, adaptive_grid=None, grid_rmax_scale=1): data, opt_sys = [], [] lenstronomyWrap = LenstronomyWrap(cosmo=self.cosmo.astropy, z_source=self.zsrc) assert len(lens_systems) == 1 for i, system in enumerate(lens_systems): compute_fluxes = True kwargs_lens, [xsrc, ysrc], [ x_opt, y_opt ], optimizer = lenstronomyWrap.run_optimize( system, self.zsrc, data2fit.x, data2fit.y, tol_source, data2fit.m, tol_mag, tol_centroid, centroid_0, optimizer_routine, self.zmain, n_particles, n_iterations, verbose, restart, re_optimize, particle_swarm, constrain_params, pso_convergence_mean=pso_convergence_mean, pso_compute_magnification=pso_compute_magnification, tol_simplex_params=tol_simplex_params, tol_simplex_func=tol_simplex_func, simplex_n_iter=simplex_n_iter, optimizer_kwargs=optimizer_kwargs, chi2_mode=chi2_mode, tol_image=tol_image) if len(x_opt) != len(data2fit.x) or len(y_opt) != len(data2fit.y): print('Warning: optimization found the wrong number of images') x_opt, y_opt = lenstronomyWrap.solve_leq(xsrc, ysrc, optimizer.lensModel, kwargs_lens, brightimg=True, precision_lim=10**-12, nitermax=20) if len(x_opt) != len(data2fit.x) or len(y_opt) != len( data2fit.y): x_opt = data2fit.x y_opt = data2fit.y compute_fluxes = False lensModel = optimizer.lensModel if system.multiplane: optimizer_kwargs = {} if hasattr(optimizer._optimizer, '_mags'): optimizer_kwargs.update( {'magnification_pointsrc': optimizer._optimizer._mags}) else: mags = lensModel.magnification(x_opt, y_opt, kwargs_lens) optimizer_kwargs.update({'magnification_pointsrc': mags}) optimizer_kwargs.update({ 'precomputed_rays': optimizer.lensModel._foreground._rays }) if return_ray_path: xpath, ypath = [], [] for xi, yi in zip(x_opt, y_opt): _x, _y, redshifts, Tzlist = lensModel._full_lensmodel.\ lens_model.ray_shooting_partial_steps(0, 0, xi, yi, 0, self.zsrc, kwargs_lens) xpath.append(_x) ypath.append(_y) nplanes = len(xpath[0]) x_path, y_path = [], [] for ni in range(0, nplanes): arrx = np.array([ xpath[0][ni], xpath[1][ni], xpath[2][ni], xpath[3][ni] ]) arry = np.array([ ypath[0][ni], ypath[1][ni], ypath[2][ni], ypath[3][ni] ]) x_path.append(arrx) y_path.append(arry) optimizer_kwargs.update({'path_x': np.array(x_path)}) optimizer_kwargs.update({'path_y': np.array(y_path)}) optimizer_kwargs.update({'path_Tzlist': Tzlist}) optimizer_kwargs.update({'path_redshifts': redshifts}) else: optimizer_kwargs = None if finite_source_magnification and compute_fluxes: fluxes = self._ray_trace_finite( x_opt, y_opt, xsrc, ysrc, system.multiplane, lensModel, kwargs_lens, res, source_shape, source_size_kpc, polar_grid, adaptive_grid=adaptive_grid, grid_rmax_scale=grid_rmax_scale) elif compute_fluxes: try: fluxes = optimizer_kwargs['magnification_pointsrc'] except: fluxes = np.absolute( lensModel.magnification(x_opt, y_opt, kwargs_lens)) else: fluxes = np.array([np.nan] * 4) optimized_sys = self.update_system(lens_system=system, newkwargs=kwargs_lens, method='lenstronomy') new_data = Data(x_opt, y_opt, fluxes, None, [xsrc, ysrc]) new_data.sort_by_pos(data2fit.x, data2fit.y) data.append(new_data) opt_sys.append(optimized_sys) return data, opt_sys, optimizer_kwargs, { 'kwargs_lens': kwargs_lens, 'lensModel': lensModel, 'source_x': xsrc, 'source_y': ysrc } def _ray_trace_finite(self, ximg, yimg, xsrc, ysrc, multiplane, lensModel, kwargs_lens, resolution, source_shape, source_size_kpc, polar_grid, adaptive_grid, grid_rmax_scale): source_scale = self.cosmo.kpc_per_asec(self.zsrc) source_size = source_size_kpc * source_scale**-1 #img_sep_small = min_img_sep(ximg, yimg) img_seps, theta_img = min_img_sep_ranked(ximg, yimg) raytracing = raytrace.RayTrace(xsrc=xsrc, ysrc=ysrc, multiplane=multiplane, res=resolution, source_shape=source_shape, polar_grid=polar_grid, source_size=source_size, minimum_image_sep=[img_seps, theta_img], adaptive_grid=adaptive_grid, grid_rmax_scale=grid_rmax_scale) fluxes = raytracing.magnification(ximg, yimg, lensModel, kwargs_lens) return fluxes def _solve_4imgs_lenstronomy(self, lens_systems, data2fit=None, method=str, sigmas=None, ray_trace=True, res=None, source_shape='GAUSSIAN', source_size_kpc=None, print_mag=False, raytrace_with=None, polar_grid=True, solver_type=None, N_iter_max=None, brightimg=None, adaptive_grid=False, grid_rmax_scale=1): data, opt_sys = [], [] lenstronomyWrap = LenstronomyWrap(cosmo=self.cosmo.astropy, z_source=self.zsrc) for i, system in enumerate(lens_systems): lensModel, kwargs_lens = lenstronomyWrap.get_lensmodel(system) kwargs_lens, precision = lenstronomyWrap.fit_lensmodel( data2fit.x, data2fit.y, lensModel, solver_type, kwargs_lens) xsrc, ysrc = lensModel.ray_shooting(data2fit.x, data2fit.y, kwargs_lens) xsrc, ysrc = np.mean(xsrc), np.mean(ysrc) x_img, y_img = lenstronomyWrap.solve_leq(xsrc, ysrc, lensModel, solver_type, kwargs_lens, brightimg) if print_mag: print('computing mag # ' + str(i + 1) + ' of ' + str(len(lens_systems))) source_scale = self.cosmo.kpc_per_asec(self.zsrc) source_size = source_size_kpc * source_scale**-1 img_sep_small = min_img_sep(x_img, y_img) raytracing = raytrace.RayTrace(xsrc=xsrc, ysrc=ysrc, multiplane=system.multiplane, source_size=source_size, res=res, source_shape=source_shape, polar_grid=polar_grid, minimum_image_sep=img_sep_small, adaptive_grid=adaptive_grid, grid_rmax_scale=grid_rmax_scale) fluxes = raytracing.magnification(x_img, y_img, lensModel, kwargs_lens) optimized_sys = self.update_system(lens_system=system, newkwargs=kwargs_lens, method='lenstronomy') new_data = Data(x_img, y_img, fluxes, None, [xsrc, ysrc]) new_data.sort_by_pos(data2fit.x, data2fit.y) data.append(new_data) opt_sys.append(optimized_sys) return data, opt_sys def _optimize_4imgs_lensmodel(self, lens_systems=None, data2fit=[], method=str, sigmas=None, identifier='', opt_routine=None, ray_trace=True, return_positions=False, res=0.0005, source_shape='GAUSSIAN', source_size_kpc=float, print_mag=False, raytrace_with=None, polar_grid=False, solver_type=None, shr_coords=1): if sigmas is None: sigmas = [ self.default_pos_sigma, self.default_flux_sigma, self.default_tdelay_sigma ] lenstronomywrap = LenstronomyWrap(cosmo=self.cosmo.astropy, z_source=self.zsrc) d2fit = [data2fit.x, data2fit.y, data2fit.m, data2fit.t] optimized_systems = [] if os.path.exists(self.paths.gravlens_input_path): pass else: create_directory(self.paths.gravlens_input_path) create_directory(self.paths.gravlens_input_path_dump) assert opt_routine is not None solver = GravlensInput(filename=identifier, zlens=self.zmain, zsrc=self.zsrc, pos_sigma=sigmas[0], flux_sigma=sigmas[1], tdelay_sigma=sigmas[2], identifier=identifier, paths=self.paths, cosmology=self.cosmo, shr_coords=shr_coords) for system in lens_systems: full = FullModel(multiplane=system.multiplane) for i, model in enumerate(system.lens_components): full.populate( SingleModel(lensmodel=model, shr_coords=shr_coords)) solver.add_lens_system(full) outputfile = solver.write_all(data=d2fit, zlens=self.zmain, zsrc=self.zsrc, opt_routine=opt_routine, shr_coords=shr_coords) call_lensmodel(inputfile=solver.outfile_path + solver.filename + '.txt', path_2_lensmodel=self.paths.path_2_lensmodel) lensdata = [] for i, name in enumerate(outputfile): xvals, yvals, mag_gravlens, tvals, macrovals, srcvals = read_dat_file( fname=name) lensdata.append( Data(x=xvals, y=yvals, m=mag_gravlens, t=tvals, source=srcvals)) newmacromodel = gravlens_to_kwargs(macrovals, shr_coords=shr_coords) optimized_sys = self.update_system(lens_system=lens_systems[i], newkwargs=newmacromodel, method='lensmodel') optimized_systems.append(optimized_sys) if ray_trace: for i, name in enumerate(outputfile): if print_mag: print('computing mag #: ', i + 1) source_scale = self.cosmo.kpc_per_asec(self.zsrc) source_size = source_size_kpc * source_scale**-1 raytracing = raytrace.RayTrace( xsrc=lensdata[i].srcx, ysrc=lensdata[i].srcy, multiplane=optimized_systems[i].multiplane, source_size=source_size, res=res, source_shape=source_shape, polar_grid=polar_grid) lensModel, kwargs_lens = lenstronomywrap.get_lensmodel( optimized_systems[i]) fluxes = raytracing.magnification(lensdata[i].x, lensdata[i].y, lensModel, kwargs_lens) lensdata[i].set_mag(fluxes) for dataset in lensdata: dataset.sort_by_pos(data2fit.x, data2fit.y) if self.clean_up: delete_dir(self.paths.gravlens_input_path_dump) return lensdata, optimized_systems def _solve_4imgs(self, lens_systems=None, method=str, identifier='', srcx=None, srcy=None, res=0.001, source_shape='GAUSSIAN', ray_trace=True, source_size_kpc=float, print_mag=False, raytrace_with='', polar_grid=True, arrival_time=False, shr_coords=1, brightimg=None, adaptive_grid=False): lenstronomywrap = LenstronomyWrap(cosmo=self.cosmo.astropy, z_source=self.zsrc) if method == 'lensmodel': create_directory(self.paths.gravlens_input_path_dump) data = [] solver = GravlensInput(filename=identifier, zlens=self.zmain, zsrc=self.zsrc, identifier=identifier, paths=self.paths, cosmology=self.cosmo, shr_coords=shr_coords) for i, system in enumerate(lens_systems): full = FullModel(multiplane=system.multiplane) for model in system.lens_components: full.populate( SingleModel(lensmodel=model, shr_coords=shr_coords)) solver.add_lens_system(full) outputfile = solver.write_all(data=None, zlens=self.zmain, zsrc=self.zsrc, srcx=srcx, srcy=srcy, shr_coords=shr_coords) call_lensmodel(inputfile=solver.outfile_path + solver.filename + '.txt', path_2_lensmodel=self.paths.path_2_lensmodel) lens_data = read_gravlens_out(fnames=outputfile) t0 = time() for i, system in enumerate(lens_systems): x, y, m, t, nimg = lens_data[i] data.append(Data(x=x, y=y, m=m, t=t, source=[srcx, srcy])) if ray_trace: if print_mag: print('computing mag #: ', i + 1) source_scale = self.cosmo.kpc_per_asec(self.zsrc) source_size = source_size_kpc * source_scale**-1 min_img_separation = min_img_sep(data[i].x, data[i].y) raytracing = raytrace.RayTrace( xsrc=data[i].srcx, ysrc=data[i].srcy, multiplane=system.multiplane, source_size=source_size, res=res, source_shape=source_shape, polar_grid=polar_grid, minimum_image_sep=min_img_separation, adaptive_grid=adaptive_grid) lensModel, kwargs_lens = lenstronomywrap.get_lensmodel( system) fluxes = raytracing.magnification(data[i].x, data[i].y, lensModel, kwargs_lens) data[i].set_mag(fluxes) if self.clean_up: delete_dir(self.paths.gravlens_input_path_dump) return data elif method == 'lenstronomy': data = [] lenstronomyWrap = LenstronomyWrap(cosmo=self.cosmo.astropy, z_source=self.zsrc) for i, system in enumerate(lens_systems): lensModel, kwargs_lens = lenstronomywrap.get_lensmodel(system) x_image, y_image = lenstronomyWrap.solve_leq( srcx, srcy, lensModel, kwargs_lens, brightimg) source_scale = self.cosmo.kpc_per_asec(self.zsrc) source_size = source_size_kpc * source_scale**-1 min_img_separation = min_img_sep_ranked(x_image, y_image) raytracing = raytrace.RayTrace( xsrc=srcx, ysrc=srcy, multiplane=system.multiplane, source_size=source_size, res=res, source_shape=source_shape, polar_grid=polar_grid, minimum_image_sep=min_img_separation, adaptive_grid=adaptive_grid) fluxes = raytracing.magnification(x_image, y_image, lensModel, kwargs_lens) if arrival_time: if system.multiplane: arrival_times = lensModel.arrival_time( x_image, y_image, kwargs_lens) else: arrival_times = [0, 0, 0, 0] #raise Exception('arrival times not yet implemented for single plane') #fermat_potential = lensModel.fermat_potential(x_image,y_image,x_source=srcx,y_source=srcy,kwargs_lens=lensmodel_params) arrival_times -= np.min(arrival_times) else: arrival_times = [0, 0, 0, 0] data.append( Data(x=x_image, y=y_image, m=fluxes, t=arrival_times, source=[srcx, srcy])) return data
def setup(self): cosmo = Cosmology() self.cosmo = cosmo self.lenscosmo = LensCosmo(0.5, 1.5, cosmo) self.concentration = Concentration(self.lenscosmo)
def compute_comoving_ray_path(x_coordinate, y_coordinate, lens_model, kwargs_lens, zsource, terminate_at_source=False, source_x=None, source_y=None, cosmo=None): """ :param x_coordinate: x coordinates to interpolate (arcsec) (float) :param y_coordinate: y coordinates to interpolate (arcsec) (float) Typically x_coordinates/y_coordinates would be four image positions, or the coordinate of the lens centroid :param lens_model: instance of LensModel (lenstronomy) :param kwargs_lens: keyword arguments for lens model :param zsource: source redshift :param terminate_at_source: fix the final angular coordinate to the source coordinate :param source_x: source x coordinate (arcsec) :param source_y: source y coordinate (arcsec) :return: Instance of interp1d (scipy) that returns the angular coordinate of a ray given a comoving distance """ if cosmo is None: cosmo = Cosmology() redshift_list = lens_model.redshift_list + [zsource] zstep = lenscone_default.default_z_step finely_sampled_redshifts = np.linspace(zstep, zsource - zstep, 50) all_redshifts = np.unique( np.append(redshift_list, finely_sampled_redshifts)) all_redshifts_sorted = all_redshifts[np.argsort(all_redshifts)] comoving_distance_calc = cosmo.D_C_transverse x_start, y_start = 0., 0. z_start = 0. x_list = [0.] y_list = [0.] distances = [0.] alpha_x_start, alpha_y_start = x_coordinate, y_coordinate for zi in all_redshifts_sorted: x_start, y_start, alpha_x_start, alpha_y_start = lens_model.lens_model.ray_shooting_partial( x_start, y_start, alpha_x_start, alpha_y_start, z_start, zi, kwargs_lens) d = float(comoving_distance_calc(zi)) x_list.append(x_start) y_list.append(y_start) distances.append(d) z_start = zi if terminate_at_source: d_src = comoving_distance_calc(zsource) x_list[-1] = source_x * d_src y_list[-1] = source_y * d_src return np.array(x_list), np.array(y_list), np.array(distances)
class TestCosmology(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 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 test_cosmo(self): da_true = self.cosmo.D_A(0, 1.824) da_interp = self.cosmo.D_A_z(1.824) npt.assert_almost_equal(da_true / da_interp, 1, 5) dc_true = self.cosmo.astropy.comoving_transverse_distance(1.4).value dc_interp = self.cosmo.D_C_z(1.4) dc_astropy = self.cosmo.astropy.comoving_distance(1.4).value npt.assert_almost_equal(dc_true / dc_interp, 1) npt.assert_almost_equal(dc_astropy / dc_true, 1) dc_transverse = self.cosmo.D_C_transverse(0.8) dc = self.cosmo.astropy.comoving_transverse_distance(0.8).value npt.assert_almost_equal(dc / dc_transverse, 1) ez = self.cosmo.E_z(0.8) ez_astropy = self.cosmo.astropy.efunc(0.8) npt.assert_almost_equal(ez / ez_astropy, 1) kpc_per_asec = self.cosmo.kpc_proper_per_asec(0.5) kpc_per_arcsec_true = self.cosmo.astropy.kpc_proper_per_arcmin( 0.5).value / 60 npt.assert_almost_equal(kpc_per_asec, kpc_per_arcsec_true, 2) rho_crit_0 = self.cosmo.rho_crit(0) rho_pc = un.Quantity(self.cosmo.astropy.critical_density(0), unit=un.Msun / un.pc**3) rho_Mpc = rho_pc.value * (1e+6)**3 npt.assert_almost_equal(rho_crit_0 / rho_Mpc, 1, 3) rho_crit = self.cosmo.rho_crit(0.6) rho_pc = un.Quantity(self.cosmo.astropy.critical_density(0.6), unit=un.Msun / un.m**3) rho_Mpc = rho_pc.value * self.cosmo.Mpc**3 npt.assert_almost_equal(rho_crit / rho_Mpc, 1, 3) rho_crit_dark_matter = self.cosmo.rho_dark_matter_crit rho_crit_DM_astropy = self.cosmo.astropy.critical_density(0.).value * \ self.cosmo.density_to_MsunperMpc * self.cosmo.astropy.Odm(0.) npt.assert_almost_equal(rho_crit_DM_astropy, rho_crit_dark_matter) rho_crit = self.cosmo.rho_crit(0.3) rho_pc = un.Quantity(self.cosmo.astropy.critical_density(0.3), unit=un.Msun / un.pc**3) rho_Mpc = rho_pc.value * (1e+6)**3 npt.assert_almost_equal(rho_crit / rho_Mpc, 1, 3) colossus = self.cosmo.colossus npt.assert_almost_equal(colossus.Om0, self.omega_DM + self.omega_baryon) npt.assert_almost_equal(colossus.Ob0, self.omega_baryon) npt.assert_almost_equal(colossus.H0, self.H0) npt.assert_almost_equal(colossus.sigma8, self.sigma8) npt.assert_almost_equal(colossus.ns, self.ns) halo_collapse_z = 9. age_today = self.cosmo.astropy.age(0.).value age_z = self.cosmo.astropy.age(halo_collapse_z).value age = age_today - age_z npt.assert_almost_equal(age, self.cosmo.halo_age(0., zform=halo_collapse_z)) npt.assert_almost_equal(self.cosmo.scale_factor(0.7), self.cosmo.astropy.scale_factor(0.7))
def test_collapse_by_mass(self): cosmo = Cosmology() m_list = 10**np.random.uniform(6, 10, 1000) realization = SingleHalo(m_list[0], 0.5, -0.1, 'TNFW', 0.5, 0.5, 1.5, subhalo_flag=True, cosmo=cosmo) for mi in m_list[1:]: single_halo = SingleHalo(mi, 0.5, -0.1, 'TNFW', 0.5, 0.5, 1.5, subhalo_flag=True, cosmo=cosmo) realization = realization.join(single_halo) single_halo = SingleHalo(mi, 0.5, -0.1, 'TNFW', 0.5, 0.5, 1.5, subhalo_flag=False, cosmo=cosmo) realization = realization.join(single_halo) ext = RealizationExtensions(realization) mass_range_subs = [[6, 8], [8, 10]] mass_range_field = [[6, 8], [8, 10]] p_subs = [0.3, 0.9] p_field = [0.8, 0.25] kwargs_halo = {'log_slope_halo': -3, 'x_core_halo': 0.05} inds_collapsed = ext.core_collapse_by_mass(mass_range_subs, mass_range_field, p_subs, p_field) realization_collapsed = ext.add_core_collapsed_halos( inds_collapsed, **kwargs_halo) i_subs_collapsed_1 = 0 i_subs_1 = 0 i_field_collapsed_1 = 0 i_field_1 = 0 i_subs_collapsed_2 = 0 i_subs_2 = 0 i_field_collapsed_2 = 0 i_field_2 = 0 for halo in realization_collapsed.halos: print(halo.mdef) if halo.is_subhalo: if halo.mass < 10**8: i_subs_1 += 1 if halo.mdef == 'SPL_CORE': i_subs_collapsed_1 += 1 else: i_subs_2 += 1 if halo.mdef == 'SPL_CORE': i_subs_collapsed_2 += 1 else: if halo.mass < 10**8: i_field_1 += 1 if halo.mdef == 'SPL_CORE': i_field_collapsed_1 += 1 else: i_field_2 += 1 if halo.mdef == 'SPL_CORE': i_field_collapsed_2 += 1 npt.assert_almost_equal(abs(p_subs[0] - i_subs_collapsed_1 / i_subs_1), 0, 1) npt.assert_almost_equal(abs(p_subs[1] - i_subs_collapsed_2 / i_subs_2), 0, 1) npt.assert_almost_equal( abs(p_field[0] - i_field_collapsed_1 / i_field_1), 0, 1) npt.assert_almost_equal( abs(p_field[1] - i_field_collapsed_2 / i_field_2), 0, 1)
from scipy.stats import gaussian_kde from MagniPy.MassModels.SIE import * import matplotlib.pyplot as plt from MagniPy.LensBuild.defaults import * from MagniPy.Solver.analysis import Analysis from MagniPy.util import min_img_sep, flux_at_edge from MagniPy.paths import * from lenstronomy.Util.param_util import ellipticity2phi_q, shear_polar2cartesian from lenstronomywrapper.LensSystem.macrolensmodel import MacroLensModel from lenstronomywrapper.LensSystem.quad_lens import QuadLensSystem from lenstronomywrapper.LensSystem.LensComponents.powerlawshear import PowerLawShear from lenstronomywrapper.LensSystem.BackgroundSource.quasar import Quasar from lenstronomywrapper.LensSystem.LensSystemExtensions.solver import iterative_rayshooting from lenstronomywrapper.LensData.lensed_quasar import LensedQuasar from time import time cosmo = Cosmology() arcsec = 206265 # arcsec per radian def get_density(): quad_imgsep, quad_vdis, _, quad_zlens, quad_zsrc = np.loadtxt( prefix + '/data/quad_info.txt', unpack=True) data = np.vstack((quad_imgsep, quad_vdis)) data = np.vstack((data, quad_zlens)) data = np.vstack((data, quad_zsrc)) kde = gaussian_kde(data) return kde def get_strides(): return np.loadtxt(prefix + '/data/quad_info.txt', unpack=True)
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 ULDM(z_lens, z_source, log10_m_uldm, log10_fluc_amplitude=-1.5, velocity_scale=200, log_mlow=6., log_mhigh=10., b_uldm=1.1, c_uldm=-2.2, c_scale=15., c_power=-0.3, cone_opening_angle_arcsec=6., sigma_sub=0.025, LOS_normalization=1., log_m_host=13.3, power_law_index=-1.9, r_tidal='0.25Rs', mass_definition='ULDM', uldm_plaw=1 / 3, scale_nfw=False, flucs=True, flucs_shape='aperture', flucs_args={}, einstein_radius=6., n_cut=5e4, **kwargs_other): """ This generates realizations of ultra-light dark matter (ULDM), including the ULDM halo mass function and halo density profiles, as well as density fluctuations in the main deflector halo. Similarly to WDMGeneral, the functional form of the subhalo mass function is the same as the field halo mass function. However, this model differs from WDMGeneral by creating halos which are composite ULDM + NFW density profiles. The ULDM particle mass and core radius-halo mass power law exponent must now be specified. For details regarding ULDM halos, see Schive et al. 2014 (https://arxiv.org/pdf/1407.7762.pdf). Equations (3) and (7) give the soliton density profile and core radius, respectively. The differential halo mass function is described by three parameters, see Schive et al. 2016 (https://arxiv.org/pdf/1508.04621.pdf): 1) log_m0 - the log10 value of the characteristic mass, or the scale where the ULDM mass function begins to deviate from CDM: m0 = (1.6*10**10) * (m22)**(-4/3) [solar masses], where m22 = m_uldm / 10**22 eV. 2) b_uldm - modifies the log slope of the ULDM mass function, analogous to b_wdm (see WDMLovell2020) 3) c_uldm - modifies the log slope of the ULDM mass function, analogous to c_wdm (see WDMLovell2020) The parametrization for the mass function is: n_uldm / n_cdm = (1 + (m / m_0)^b_uldm) ^ c_uldm, where Schive et al. 2016 determined that (m_0, b_uldm, c_uldm) = ( (1.6*10**10) * (m22)**(-4/3), 1.1, 2.2) As for the concentration relative to CDM, Du et al. 2016 (https://arxiv.org/pdf/1608.02575.pdf) found that the same fitting function as Lovell 2020 is a good estimation of the ULDM concentration, i.e. simply c_wdm = c_uldm, with (c_scale, c_power) = (15, -0.3). Furthermore, Schive et al. 2014 (https://arxiv.org/pdf/1407.7762.pdf) found a redshift-dependent minimum ULDM halo mass given by M_min(z) = a^(-3/4) * (Zeta(z)/Zeta(0))^(1/4) * M_min,0 [solar masses] where a is the cosmic scale factor, M_min,0 = 4.4*10^7 * m22^(-3/2) [solar masses] and Zeta(z) = (18*pi^2 + 82(Om(z) - 1) - 39(Om(z) - 1)^2) / Om(z), where Om(z) is the matter density parameter. :param z_lens: the lens redshift :param z_source: the source redshift :param log10_m_uldm: ULDM particle mass in log units, typically 1e-22 eV :param log10_fluc_amplitude: sets the amplitude of the fluctuations in the host dark matter halo. fluctuations are generated from a Guassian distriubtion with mean 0 and variance 10^log10_fluc_amplitude :param velocity_scale: velocity for de Broglie wavelength calculation in km/s :param log_mhigh: log10(maximum halo mass) rendered (mass definition is M200 w.r.t. critical density) :param b_uldm: defines the ULDM mass function (see above) :param c_uldm: defines the ULDM mass function (see above) :param c_scale: scale where concentrations in ULDM deviate from CDM (see WDMLovell2020) :param c_power: modification to logarithmic slope of mass-concentration relation (see WDMLovell2020) :param cone_opening_angle: the opening angle in arcsec of the double cone geometry where halos are added :param sigma_sub: normalization of the subhalo mass function (see description in CDM preset model) :param LOS_normalization: rescaling of the line of sight halo mass function relative to Sheth-Tormen :param log_m_host: log10 host halo mass in M_sun :param power_law_index: logarithmic slope of the subhalo mass function :param r_tidal: subhalos are distributed following a cored NFW profile with a core radius r_tidal. This is intended to account for tidal stripping of halos that pass close to the central galaxy :param mass_definition: mass profile model for halos :param uldm_plaw: ULDM core radius-halo mass power law exponent, typically 1/3 :param scale_nfw: boolean specifiying whether or not to scale the NFW component (can improve mass accuracy) :param flucs: Boolean specifying whether or not to include density fluctuations in the main deflector halo :param flucs_shape: String specifying how to place fluctuations, see docs in realization_extensions.add_ULDM_fluctuations :param fluc_args: Keyword arguments for specifying the fluctuations, see docs in realization_extensions.add_ULDM_fluctuations :param einstein_radius: Einstein radius of main deflector halo in kpc :param n_cut: Number of fluctuations above which to start cancelling :param kwargs_other: any other optional keyword arguments :return: a realization of ULDM halos """ # constants m22 = 10**(log10_m_uldm + 22) log_m0 = np.log10(1.6e10 * m22**(-4 / 3)) M_min0 = 4.4e7 * m22**(-3 / 2) # M_solar a_uldm = 1 # set to unity since Schive et al. 2016 do not have an analogous parameter #compute M_min as described in documentation a = lambda z: (1 + z)**(-1) O_m = lambda z: Cosmology().astropy.Om(z) zeta = lambda z: (18 * np.pi**2 + 82 * (O_m(z) - 1) - 39 * (O_m(z) - 1)**2) / O_m(z) m_min = lambda z: a(z)**(-3 / 4) * (zeta(z) / zeta(0))**(1 / 4) * M_min0 log_m_min = lambda z: np.log10(m_min(z)) if log_m_min(z_lens) >= log_mlow: log_mlow = log_m_min( z_lens ) # only use M_min for minimum halo mass if it is above input 'log_mlow' kwargs_model_field = { 'a_wdm': a_uldm, 'b_wdm': b_uldm, 'c_wdm': c_uldm, 'log_mc': log_m0, 'c_scale': c_scale, 'c_power': c_power, 'log_mlow': log_mlow, 'log_mhigh': log_mhigh, 'cone_opening_angle': cone_opening_angle_arcsec, 'mdef_los': mass_definition, 'mass_func_type': 'POWER_LAW', 'LOS_normalization': LOS_normalization, 'log_m_host': log_m_host } kwargs_model_subhalos = { 'a_wdm': a_uldm, 'b_wdm': b_uldm, 'c_wdm': c_uldm, 'log_mc': log_m0, 'c_scale': c_scale, 'c_power': c_power, 'log_mlow': log_mlow, 'log_mhigh': log_mhigh, 'cone_opening_angle': cone_opening_angle_arcsec, 'sigma_sub': sigma_sub, 'mdef_subs': mass_definition, 'mass_func_type': 'POWER_LAW', 'power_law_index': power_law_index, 'r_tidal': r_tidal } kwargs_uldm = { 'log10_m_uldm': log10_m_uldm, 'uldm_plaw': uldm_plaw, 'scale_nfw': scale_nfw } kwargs_model_field.update(kwargs_uldm) kwargs_model_subhalos.update(kwargs_uldm) kwargs_model_field.update(kwargs_other) kwargs_model_subhalos.update(kwargs_other) # this will use the default cosmology. parameters can be found in defaults.py pyhalo = pyHalo(z_lens, z_source) # Using the render method will result a list of realizations realization_subs = pyhalo.render(['SUBHALOS'], kwargs_model_subhalos, nrealizations=1)[0] realization_line_of_sight = pyhalo.render(['LINE_OF_SIGHT', 'TWO_HALO'], kwargs_model_field, nrealizations=1)[0] uldm_realization = realization_line_of_sight.join( realization_subs, join_rendering_classes=True) if flucs: # add fluctuations to realization ext = RealizationExtensions(uldm_realization) lambda_dB = de_broglie_wavelength( log10_m_uldm, velocity_scale) # de Broglie wavelength in kpc if flucs_args == {}: raise Exception( 'Must specify fluctuation arguments, see realization_extensions.add_ULDM_fluctuations' ) fluctuation_amplitude_norm = 10**log10_fluc_amplitude fluctuation_amplitude = fluctuation_amplitude_norm * ( 10**log10_m_uldm / 1e-22)**-0.5 uldm_realization = ext.add_ULDM_fluctuations( de_Broglie_wavelength=lambda_dB, fluctuation_amplitude_variance=fluctuation_amplitude, fluctuation_size_variance=lambda_dB, shape=flucs_shape, args=flucs_args, n_cut=n_cut) return uldm_realization
def test_add_pbh(self): kwargs_halo = {'c_scatter': False} realization = SingleHalo(10**9, 0., 0., 'TNFW', 0.1, 0.5, 1.5, subhalo_flag=False, kwargs_halo=kwargs_halo) zlist = [0.2, 0.4, 0.6] rmax = 0.3 for i, zi in enumerate(zlist): theta = np.random.uniform(0., 2 * np.pi) r = np.random.uniform(0, rmax**2)**0.5 xi, yi = np.cos(theta) * r, np.sin(theta) * r mi = np.random.uniform(8, 9) single_halo = SingleHalo(10**mi, xi, yi, 'TNFW', zi, 0.5, 1.5, subhalo_flag=False, kwargs_halo=kwargs_halo) realization = realization.join(single_halo) lens_model_list_init, _, kwargs_init, _ = realization.lensing_quantities( ) ext = RealizationExtensions(realization) mass_fraction = 0.1 kwargs_mass_function = { 'mass_function_type': 'DELTA', 'logM': 5., 'mass_fraction': 0.5 } fraction_in_halos = 0.5 zlist = np.arange(0.00, 1.02, 0.02) x_image = [0.] * len(zlist) y_image = [0.] * len(zlist) cosmo = Cosmology() dlist = [cosmo.D_C_transverse(zi) for zi in zlist] x_image_interp_list = [interp1d(dlist, x_image)] y_image_interp_list = [interp1d(dlist, y_image)] pbh_realization = ext.add_primordial_black_holes( mass_fraction, kwargs_mass_function, fraction_in_halos, x_image_interp_list, y_image_interp_list, rmax) lens_model_list, _, kwargs, _ = pbh_realization.lensing_quantities() for i, halo in enumerate(pbh_realization.halos): r2d = np.hypot(halo.x, halo.y) npt.assert_equal(r2d <= np.sqrt(2) * rmax, True) condition1 = 'PT_MASS' == halo.mdef condition2 = 'TNFW' == halo.mdef npt.assert_equal(np.logical_or(condition1, condition2), True)
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
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)