Source code for lenstronomy.LensModel.MultiPlane.decoupled_multi_plane

__author__ = "dangilman"

from lenstronomy.LensModel.MultiPlane.multi_plane import MultiPlane
from lenstronomy.LensModel.single_plane import SinglePlane
from lenstronomy.Cosmo.background import Background

__all__ = ["MultiPlaneDecoupled"]


[docs] class MultiPlaneDecoupled(MultiPlane):
[docs] def __init__( self, z_source, lens_model_list, lens_redshift_list, cosmo=None, observed_convention_index=None, ignore_observed_positions=False, z_source_convention=None, z_lens_convention=None, cosmo_interp=False, z_interp_stop=None, num_z_interp=100, profile_kwargs_list=None, distance_ratio_sampling=False, cosmology_sampling=False, cosmology_model="FlatLambdaCDM", x0_interp=None, y0_interp=None, alpha_x_interp_foreground=None, alpha_y_interp_foreground=None, alpha_x_interp_background=None, alpha_y_interp_background=None, z_split=None, use_jax=False, ): """A class for multiplane lensing in which the deflection angles at certain coordinates are fixed through user-specified interpolation functions. These functions return fixed deflection angles that effectively decouple deflections by a group of deflectors at redshift Z from deflections produced by halos at redshift< Z. This class breaks the recursive nature of the multi-plane lens equation, and can significantly speed up computations with a large number of line-of-sight halos. :param lens_model_list: list of lens model strings :param lens_redshift_list: list of floats with redshifts of the lens models indicated in lens_model_list :param z_source_convention: float, redshift of a source to define the reduced deflection angles of the lens models. If None, 'z_source' is used. :param cosmo: instance of astropy.cosmology :param profile_kwargs_list: list of dicts, keyword arguments used to initialize profile classes in the same order of the lens_model_list. If any of the profile_kwargs are None, then that profile will be initialized using default settings. :param x0_interp: a function that maps an angular coordinate on the sky to the x coordinate of a physical position [Mpc] at the first lens plane :param y0_interp: same as x0_interp, but returns the y coordinate in Mpc :param alpha_x_interp_list: a list of functions that take as input angular coordinates (x, y) and returns the x-component of the deflection angle at each coorindate :param alpha_y_interp_list: same as alpha_x_interp_list, but returns the y-component of the deflection angle at (x,y) :param z_interp_list: a list of redshifts corresponding to the alpha_x_interp_list and alpha_y_interp_list entries :param use_jax: bool, if True, uses deflector profiles from jaxtronomy. Can also be a list of bools, selecting which models in the lens_model_list to use from jaxtronomy """ self._alphax_interp_foreground = alpha_x_interp_foreground self._alphay_interp_foreground = alpha_y_interp_foreground self._alphax_interp_background = alpha_x_interp_background self._alphay_interp_background = alpha_y_interp_background self._x0_interp = x0_interp self._y0_interp = y0_interp self._z_split = z_split super(MultiPlaneDecoupled, self).__init__( z_source=z_source, lens_model_list=lens_model_list, lens_redshift_list=lens_redshift_list, cosmo=cosmo, observed_convention_index=observed_convention_index, ignore_observed_positions=ignore_observed_positions, z_source_convention=z_source_convention, z_lens_convention=z_lens_convention, cosmo_interp=cosmo_interp, z_interp_stop=z_interp_stop, num_z_interp=num_z_interp, profile_kwargs_list=profile_kwargs_list, distance_ratio_sampling=distance_ratio_sampling, cosmology_sampling=cosmology_sampling, cosmology_model=cosmology_model, ) cosmo_bkg = Background(cosmo) d_xy_source = cosmo_bkg.d_xy(0, z_source) d_xy_lens_source = cosmo_bkg.d_xy(self._z_split, z_source) self._reduced_to_phys = d_xy_source / d_xy_lens_source self._deltaT_zsplit = cosmo_bkg.d_xy(0, self._z_split) self._deltaT_zsplit_zsource = cosmo_bkg.T_xy(self._z_split, z_source) self._Ts = cosmo_bkg.T_xy(0, z_source) self._Td = cosmo_bkg.T_xy(0, z_split) self._Tds = cosmo_bkg.T_xy(self._z_split, z_source) self._main_deflector = SinglePlane( lens_model_list, profile_kwargs_list=profile_kwargs_list, use_jax=use_jax ) # useful to have these saved to access later outside the class self.kwargs_multiplane_model = { "x0_interp": self._x0_interp, "y0_interp": self._y0_interp, "alpha_x_interp_foreground": self._alphax_interp_foreground, "alpha_y_interp_foreground": self._alphay_interp_foreground, "alpha_x_interp_background": self._alphax_interp_background, "alpha_y_interp_background": self._alphay_interp_background, "z_split": self._z_split, }
[docs] def geo_shapiro_delay(*args, **kwargs): raise Exception( "time delays are not yet implemented for the MultiPlaneDecoupled class" )
def ray_shooting_partial_comoving(self, *args, **kwargs): raise Exception("ray_shooting_partial is not well defined for this class")
[docs] def ray_shooting_partial_comoving(self, *args, **kwargs): raise Exception( "ray_shooting_partial_comoving is not well defined for this class" )
[docs] def ray_shooting(self, theta_x, theta_y, kwargs_lens, *args, **kwargs): """Ray-shooting through the lens volume with fixed deflection angles at certain lens planes passed through the alpha_x_interp/alpha_y_interp lists. Starts with (x,y) co-moving distance passed through the x0_interp and y0_interp functions, then starts multi-plane ray-tracing through all subsequent lens planes. :param theta_x: angular coordinate on the sky :param theta_y: angular coordinate on the sky :param kwargs_lens: keyword arguments for the main deflector :return: coordinates on the source plane """ coordinates = (theta_x, theta_y) # here we use an interpolation function to compute the comoving coordinates of the light rays # where they hit the main lens plane at redshift z = z_main x = self._x0_interp(coordinates) y = self._y0_interp(coordinates) theta_x_main = x / self._Td # the angular coordinates of the ray positions theta_y_main = y / self._Td # the angular coordinates of the ray positions # now we compute (via the interpolation functions) the deflection angles from all deflectors at z <= z_main, \ # exlucding the main deflector angle_x_foreground = self._alphax_interp_foreground(coordinates) angle_y_foreground = self._alphay_interp_foreground(coordinates) # compute the deflection angles from the main deflector deflection_x_main, deflection_y_main = self._main_deflector.alpha( theta_x_main, theta_y_main, kwargs_lens ) deflection_x_main *= self._reduced_to_phys deflection_y_main *= self._reduced_to_phys # add the main deflector to the deflection field angle_x = angle_x_foreground - deflection_x_main angle_y = angle_y_foreground - deflection_y_main # now we compute (via the interpolation functions) the deflection angles from all deflectors at z > z_main deflection_x_background = self._alphax_interp_background(coordinates) deflection_y_background = self._alphay_interp_background(coordinates) # combine deflections alpha_background_x = angle_x + deflection_x_background alpha_background_y = angle_y + deflection_y_background # ray propagation to the source plane with the small angle approximation beta_x = x / self._Ts + alpha_background_x * self._Tds / self._Ts beta_y = y / self._Ts + alpha_background_y * self._Tds / self._Ts return beta_x, beta_y