Exemplo n.º 1
0
    def kinematic_profiles(self,
                           kwargs_lens,
                           kwargs_lens_light,
                           r_eff,
                           MGE_light=False,
                           MGE_mass=False,
                           lens_model_kinematics_bool=None,
                           light_model_kinematics_bool=None,
                           Hernquist_approx=False):
        """
        translates the lenstronomy lens and mass profiles into a (sub) set of profiles that are compatible with the GalKin module to compute the kinematics thereof.

        :param kwargs_lens: lens model parameters
        :param kwargs_lens_light: lens light parameters
        :param r_eff: a rough estimate of the half light radius of the lens light in case of computing the MGE of the
         light profile
        :param MGE_light: bool, if true performs the MGE for the light distribution
        :param MGE_mass: bool, if true performs the MGE for the mass distribution
        :param lens_model_kinematics_bool: bool list of length of the lens model. Only takes a subset of all the models
            as part of the kinematics computation (can be used to ignore substructure, shear etc that do not describe the
            main deflector potential
        :param light_model_kinematics_bool: bool list of length of the light model. Only takes a subset of all the models
            as part of the kinematics computation (can be used to ignore light components that do not describe the main
            deflector
        :param Hernquist_approx: bool, if True, uses a Hernquist light profile matched to the half light radius of the deflector light profile to compute the kinematics
        :return: mass_profile_list, kwargs_profile, light_profile_list, kwargs_light
        """

        mass_profile_list = []
        kwargs_profile = []
        if lens_model_kinematics_bool is None:
            lens_model_kinematics_bool = [True] * len(kwargs_lens)
        for i, lens_model in enumerate(self.kwargs_options['lens_model_list']):
            if lens_model_kinematics_bool[i] is True:
                mass_profile_list.append(lens_model)
                if lens_model in ['INTERPOL', 'INTERPOL_SCLAED']:
                    center_x, center_y = self._lensModelExt.lens_center(
                        kwargs_lens, k=i)
                    kwargs_lens_i = copy.deepcopy(kwargs_lens[i])
                    kwargs_lens_i['grid_interp_x'] -= center_x
                    kwargs_lens_i['grid_interp_y'] -= center_y
                else:
                    kwargs_lens_i = {
                        k: v
                        for k, v in kwargs_lens[i].items()
                        if not k in ['center_x', 'center_y']
                    }
                kwargs_profile.append(kwargs_lens_i)

        if MGE_mass is True:
            lensModel = LensModel(lens_model_list=mass_profile_list)
            massModel = LensModelExtensions(lensModel)
            theta_E = massModel.effective_einstein_radius(kwargs_profile)
            r_array = np.logspace(-4, 2, 200) * theta_E
            mass_r = lensModel.kappa(r_array, np.zeros_like(r_array),
                                     kwargs_profile)
            amps, sigmas, norm = mge.mge_1d(r_array, mass_r, N=20)
            mass_profile_list = ['MULTI_GAUSSIAN_KAPPA']
            kwargs_profile = [{'amp': amps, 'sigma': sigmas}]

        light_profile_list = []
        kwargs_light = []
        if light_model_kinematics_bool is None:
            light_model_kinematics_bool = [True] * len(kwargs_lens_light)
        for i, light_model in enumerate(
                self.kwargs_options['lens_light_model_list']):
            if light_model_kinematics_bool[i]:
                light_profile_list.append(light_model)
                kwargs_lens_light_i = {
                    k: v
                    for k, v in kwargs_lens_light[i].items()
                    if not k in ['center_x', 'center_y']
                }
                if 'e1' in kwargs_lens_light_i:
                    kwargs_lens_light_i['e1'] = 0
                    kwargs_lens_light_i['e2'] = 0
                kwargs_light.append(kwargs_lens_light_i)
        if Hernquist_approx is True:
            light_profile_list = ['HERNQUIST']
            kwargs_light = [{'Rs': r_eff, 'amp': 1.}]
        else:
            if MGE_light is True:
                lightModel = LightModel(light_profile_list)
                r_array = np.logspace(-3, 2, 200) * r_eff * 2
                flux_r = lightModel.surface_brightness(r_array, 0,
                                                       kwargs_light)
                amps, sigmas, norm = mge.mge_1d(r_array, flux_r, N=20)
                light_profile_list = ['MULTI_GAUSSIAN']
                kwargs_light = [{'amp': amps, 'sigma': sigmas}]
        return mass_profile_list, kwargs_profile, light_profile_list, kwargs_light
Exemplo n.º 2
0
class LensAnalysis(object):
    """
    class to compute flux ratio anomalies, inherited from standard MakeImage
    """
    def __init__(self, kwargs_model):
        self.LensLightModel = LightModel(
            kwargs_model.get('lens_light_model_list', []))
        self.SourceModel = LightModel(
            kwargs_model.get('source_light_model_list', []))
        self.LensModel = LensModel(
            lens_model_list=kwargs_model.get('lens_model_list', []),
            z_source=kwargs_model.get('z_source', None),
            redshift_list=kwargs_model.get('redshift_list', None),
            multi_plane=kwargs_model.get('multi_plane', False))
        self._lensModelExtensions = LensModelExtensions(self.LensModel)
        self.PointSource = PointSource(point_source_type_list=kwargs_model.get(
            'point_source_model_list', []))
        self.kwargs_model = kwargs_model
        self.NumLensModel = NumericLens(
            lens_model_list=kwargs_model.get('lens_model_list', []))

    def fermat_potential(self, kwargs_lens, kwargs_ps):
        ra_pos, dec_pos = self.PointSource.image_position(
            kwargs_ps, kwargs_lens)
        ra_pos = ra_pos[0]
        dec_pos = dec_pos[0]
        ra_source, dec_source = self.LensModel.ray_shooting(
            ra_pos, dec_pos, kwargs_lens)
        ra_source = np.mean(ra_source)
        dec_source = np.mean(dec_source)
        fermat_pot = self.LensModel.fermat_potential(ra_pos, dec_pos,
                                                     ra_source, dec_source,
                                                     kwargs_lens)
        return fermat_pot

    def ellipticity_lens_light(self,
                               kwargs_lens_light,
                               center_x=0,
                               center_y=0,
                               model_bool_list=None,
                               deltaPix=None,
                               numPix=None):
        """
        make sure that the window covers all the light, otherwise the moments may give to low answers.

        :param kwargs_lens_light:
        :param center_x:
        :param center_y:
        :param model_bool_list:
        :param deltaPix:
        :param numPix:
        :return:
        """
        if model_bool_list is None:
            model_bool_list = [True] * len(kwargs_lens_light)
        if numPix is None:
            numPix = 100
        if deltaPix is None:
            deltaPix = 0.05
        x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix)
        x_grid += center_x
        y_grid += center_y
        I_xy = self._lens_light_internal(x_grid,
                                         y_grid,
                                         kwargs_lens_light,
                                         model_bool_list=model_bool_list)
        e1, e2 = analysis_util.ellipticities(I_xy, x_grid, y_grid)
        return e1, e2

    def half_light_radius_lens(self,
                               kwargs_lens_light,
                               center_x=0,
                               center_y=0,
                               model_bool_list=None,
                               deltaPix=None,
                               numPix=None):
        """
        computes numerically the half-light-radius of the deflector light and the total photon flux

        :param kwargs_lens_light:
        :return:
        """
        if model_bool_list is None:
            model_bool_list = [True] * len(kwargs_lens_light)
        if numPix is None:
            numPix = 1000
        if deltaPix is None:
            deltaPix = 0.05
        x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix)
        x_grid += center_x
        y_grid += center_y
        lens_light = self._lens_light_internal(x_grid,
                                               y_grid,
                                               kwargs_lens_light,
                                               model_bool_list=model_bool_list)
        R_h = analysis_util.half_light_radius(lens_light, x_grid, y_grid,
                                              center_x, center_y)
        return R_h

    def half_light_radius_source(self,
                                 kwargs_source,
                                 center_x=0,
                                 center_y=0,
                                 deltaPix=None,
                                 numPix=None):
        """
        computes numerically the half-light-radius of the deflector light and the total photon flux

        :param kwargs_source:
        :return:
        """
        if numPix is None:
            numPix = 1000
        if deltaPix is None:
            deltaPix = 0.005
        x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix)
        x_grid += center_x
        y_grid += center_y
        source_light = self.SourceModel.surface_brightness(
            x_grid, y_grid, kwargs_source)
        R_h = analysis_util.half_light_radius(source_light,
                                              x_grid,
                                              y_grid,
                                              center_x=center_x,
                                              center_y=center_y)
        return R_h

    def _lens_light_internal(self,
                             x_grid,
                             y_grid,
                             kwargs_lens_light,
                             model_bool_list=None):
        """
        evaluates only part of the light profiles

        :param x_grid:
        :param y_grid:
        :param kwargs_lens_light:
        :return:
        """
        if model_bool_list is None:
            model_bool_list = [True] * len(kwargs_lens_light)
        lens_light = np.zeros_like(x_grid)
        for i, bool in enumerate(model_bool_list):
            if bool is True:
                lens_light_i = self.LensLightModel.surface_brightness(
                    x_grid, y_grid, kwargs_lens_light, k=i)
                lens_light += lens_light_i
        return lens_light

    def multi_gaussian_lens_light(self,
                                  kwargs_lens_light,
                                  model_bool_list=None,
                                  e1=0,
                                  e2=0,
                                  n_comp=20,
                                  deltaPix=None,
                                  numPix=None):
        """
        multi-gaussian decomposition of the lens light profile (in 1-dimension)

        :param kwargs_lens_light:
        :param n_comp:
        :return:
        """
        if 'center_x' in kwargs_lens_light[0]:
            center_x = kwargs_lens_light[0]['center_x']
            center_y = kwargs_lens_light[0]['center_y']
        else:
            center_x, center_y = 0, 0
        r_h = self.half_light_radius_lens(kwargs_lens_light,
                                          center_x=center_x,
                                          center_y=center_y,
                                          model_bool_list=model_bool_list,
                                          deltaPix=deltaPix,
                                          numPix=numPix)
        r_array = np.logspace(-3, 2, 200) * r_h * 2
        x_coords, y_coords = param_util.transform_e1e2(r_array,
                                                       np.zeros_like(r_array),
                                                       e1=-e1,
                                                       e2=-e2)
        x_coords += center_x
        y_coords += center_y
        #r_array = np.logspace(-2, 1, 50) * r_h
        flux_r = self._lens_light_internal(x_coords,
                                           y_coords,
                                           kwargs_lens_light,
                                           model_bool_list=model_bool_list)
        amplitudes, sigmas, norm = mge.mge_1d(r_array, flux_r, N=n_comp)
        return amplitudes, sigmas, center_x, center_y

    def multi_gaussian_lens(self,
                            kwargs_lens,
                            model_bool_list=None,
                            e1=0,
                            e2=0,
                            n_comp=20):
        """
        multi-gaussian lens model in convergence space

        :param kwargs_lens:
        :param n_comp:
        :return:
        """
        if 'center_x' in kwargs_lens[0]:
            center_x = kwargs_lens[0]['center_x']
            center_y = kwargs_lens[0]['center_y']
        else:
            raise ValueError('no keyword center_x defined!')
        theta_E = self._lensModelExtensions.effective_einstein_radius(
            kwargs_lens)
        r_array = np.logspace(-4, 2, 200) * theta_E
        x_coords, y_coords = param_util.transform_e1e2(r_array,
                                                       np.zeros_like(r_array),
                                                       e1=-e1,
                                                       e2=-e2)
        x_coords += center_x
        y_coords += center_y
        #r_array = np.logspace(-2, 1, 50) * theta_E
        if model_bool_list is None:
            model_bool_list = [True] * len(kwargs_lens)
        kappa_s = np.zeros_like(r_array)
        for i in range(len(kwargs_lens)):
            if model_bool_list[i] is True:
                kappa_s += self.LensModel.kappa(x_coords,
                                                y_coords,
                                                kwargs_lens,
                                                k=i)
        amplitudes, sigmas, norm = mge.mge_1d(r_array, kappa_s, N=n_comp)
        return amplitudes, sigmas, center_x, center_y

    def flux_components(self,
                        kwargs_light,
                        n_grid=400,
                        delta_grid=0.01,
                        deltaPix=0.05,
                        type="lens"):
        """
        computes the total flux in each component of the model

        :param kwargs_light:
        :param n_grid:
        :param delta_grid:
        :return:
        """
        flux_list = []
        R_h_list = []
        x_grid, y_grid = util.make_grid(numPix=n_grid, deltapix=delta_grid)
        kwargs_copy = copy.deepcopy(kwargs_light)
        for k, kwargs in enumerate(kwargs_light):
            if 'center_x' in kwargs_copy[k]:
                kwargs_copy[k]['center_x'] = 0
                kwargs_copy[k]['center_y'] = 0
            if type == 'lens':
                light = self.LensLightModel.surface_brightness(x_grid,
                                                               y_grid,
                                                               kwargs_copy,
                                                               k=k)
            elif type == 'source':
                light = self.SourceModel.surface_brightness(x_grid,
                                                            y_grid,
                                                            kwargs_copy,
                                                            k=k)
            else:
                raise ValueError("type %s not supported!" % type)
            flux = np.sum(light) * delta_grid**2 / deltaPix**2
            R_h = analysis_util.half_light_radius(light, x_grid, y_grid)
            flux_list.append(flux)
            R_h_list.append(R_h)
        return flux_list, R_h_list

    def error_map_source(self, kwargs_source, x_grid, y_grid, cov_param):
        """
        variance of the linear source reconstruction in the source plane coordinates,
        computed by the diagonal elements of the covariance matrix of the source reconstruction as a sum of the errors
        of the basis set.

        :param kwargs_source: keyword arguments of source model
        :param x_grid: x-axis of positions to compute error map
        :param y_grid: y-axis of positions to compute error map
        :param cov_param: covariance matrix of liner inversion parameters
        :return: diagonal covariance errors at the positions (x_grid, y_grid)
        """

        error_map = np.zeros_like(x_grid)
        basis_functions, n_source = self.SourceModel.functions_split(
            x_grid, y_grid, kwargs_source)
        basis_functions = np.array(basis_functions)

        if cov_param is not None:
            for i in range(len(error_map)):
                error_map[i] = basis_functions[:, i].T.dot(
                    cov_param[:n_source, :n_source]).dot(basis_functions[:, i])
        return error_map

    def light2mass_mge(self,
                       kwargs_lens_light,
                       model_bool_list=None,
                       elliptical=False,
                       numPix=100,
                       deltaPix=0.05):
        # estimate center
        if 'center_x' in kwargs_lens_light[0]:
            center_x, center_y = kwargs_lens_light[0][
                'center_x'], kwargs_lens_light[0]['center_y']
        else:
            center_x, center_y = 0, 0
        # estimate half-light radius
        r_h = self.half_light_radius_lens(kwargs_lens_light,
                                          center_x=center_x,
                                          center_y=center_y,
                                          model_bool_list=model_bool_list,
                                          numPix=numPix,
                                          deltaPix=deltaPix)
        # estimate ellipticity at half-light radius
        if elliptical is True:
            e1, e2 = self.ellipticity_lens_light(
                kwargs_lens_light,
                center_x=center_x,
                center_y=center_y,
                model_bool_list=model_bool_list,
                deltaPix=deltaPix * 2,
                numPix=numPix)
        else:
            e1, e2 = 0, 0
        # MGE around major axis
        amplitudes, sigmas, center_x, center_y = self.multi_gaussian_lens_light(
            kwargs_lens_light,
            model_bool_list=model_bool_list,
            e1=e1,
            e2=e2,
            n_comp=20)
        kwargs_mge = {
            'amp': amplitudes,
            'sigma': sigmas,
            'center_x': center_x,
            'center_y': center_y
        }
        if elliptical:
            kwargs_mge['e1'] = e1
            kwargs_mge['e2'] = e2
        # rotate axes and add ellipticity to model kwargs
        return kwargs_mge

    @staticmethod
    def light2mass_interpol(lens_light_model_list,
                            kwargs_lens_light,
                            numPix=100,
                            deltaPix=0.05,
                            subgrid_res=5,
                            center_x=0,
                            center_y=0):
        """
        takes a lens light model and turns it numerically in a lens model
        (with all lensmodel quantities computed on a grid). Then provides an interpolated grid for the quantities.

        :param kwargs_lens_light: lens light keyword argument list
        :param numPix: number of pixels per axis for the return interpolation
        :param deltaPix: interpolation/pixel size
        :param center_x: center of the grid
        :param center_y: center of the grid
        :param subgrid: subgrid for the numerical integrals
        :return:
        """
        # make sugrid
        x_grid_sub, y_grid_sub = util.make_grid(numPix=numPix * 5,
                                                deltapix=deltaPix,
                                                subgrid_res=subgrid_res)
        import lenstronomy.Util.mask as mask_util
        mask = mask_util.mask_sphere(x_grid_sub,
                                     y_grid_sub,
                                     center_x,
                                     center_y,
                                     r=1)
        x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix)
        # compute light on the subgrid
        lightModel = LightModel(light_model_list=lens_light_model_list)
        flux = lightModel.surface_brightness(x_grid_sub, y_grid_sub,
                                             kwargs_lens_light)
        flux_norm = np.sum(flux[mask == 1]) / np.sum(mask)
        flux /= flux_norm
        from lenstronomy.LensModel.numerical_profile_integrals import ConvergenceIntegrals
        integral = ConvergenceIntegrals()

        # compute lensing quantities with subgrid
        convergence_sub = flux
        f_x_sub, f_y_sub = integral.deflection_from_kappa(convergence_sub,
                                                          x_grid_sub,
                                                          y_grid_sub,
                                                          deltaPix=deltaPix /
                                                          float(subgrid_res))
        f_sub = integral.potential_from_kappa(convergence_sub,
                                              x_grid_sub,
                                              y_grid_sub,
                                              deltaPix=deltaPix /
                                              float(subgrid_res))
        # interpolation function on lensing quantities
        x_axes_sub, y_axes_sub = util.get_axes(x_grid_sub, y_grid_sub)
        from lenstronomy.LensModel.Profiles.interpol import Interpol_func
        interp_func = Interpol_func()
        interp_func.do_interp(x_axes_sub, y_axes_sub, f_sub, f_x_sub, f_y_sub)
        # compute lensing quantities on sparser grid
        x_axes, y_axes = util.get_axes(x_grid, y_grid)
        f_ = interp_func.function(x_grid, y_grid)
        f_x, f_y = interp_func.derivatives(x_grid, y_grid)
        # numerical differentials for second order differentials
        from lenstronomy.LensModel.numeric_lens_differentials import NumericLens
        lens_differential = NumericLens(lens_model_list=['INTERPOL'])
        kwargs = [{
            'grid_interp_x': x_axes_sub,
            'grid_interp_y': y_axes_sub,
            'f_': f_sub,
            'f_x': f_x_sub,
            'f_y': f_y_sub
        }]
        f_xx, f_xy, f_yx, f_yy = lens_differential.hessian(
            x_grid, y_grid, kwargs)
        kwargs_interpol = {
            'grid_interp_x': x_axes,
            'grid_interp_y': y_axes,
            'f_': util.array2image(f_),
            'f_x': util.array2image(f_x),
            'f_y': util.array2image(f_y),
            'f_xx': util.array2image(f_xx),
            'f_xy': util.array2image(f_xy),
            'f_yy': util.array2image(f_yy)
        }
        return kwargs_interpol

    def mass_fraction_within_radius(self,
                                    kwargs_lens,
                                    center_x,
                                    center_y,
                                    theta_E,
                                    numPix=100):
        """
        computes the mean convergence of all the different lens model components within a spherical aperture

        :param kwargs_lens: lens model keyword argument list
        :param center_x: center of the aperture
        :param center_y: center of the aperture
        :param theta_E: radius of aperture
        :return: list of average convergences for all the model components
        """
        x_grid, y_grid = util.make_grid(numPix=numPix,
                                        deltapix=2. * theta_E / numPix)
        x_grid += center_x
        y_grid += center_y
        mask = mask_util.mask_sphere(x_grid, y_grid, center_x, center_y,
                                     theta_E)
        kappa_list = []
        for i in range(len(kwargs_lens)):
            kappa = self.LensModel.kappa(x_grid, y_grid, kwargs_lens, k=i)
            kappa_mean = np.sum(kappa * mask) / np.sum(mask)
            kappa_list.append(kappa_mean)
        return kappa_list
Exemplo n.º 3
0
    def velocity_dispersion_numerical(self,
                                      kwargs_lens,
                                      kwargs_lens_light,
                                      kwargs_anisotropy,
                                      kwargs_aperture,
                                      psf_fwhm,
                                      aperture_type,
                                      anisotropy_model,
                                      r_eff=None,
                                      kwargs_numerics={},
                                      MGE_light=False,
                                      MGE_mass=False,
                                      lens_model_kinematics_bool=None,
                                      light_model_kinematics_bool=None,
                                      Hernquist_approx=False):
        """
        Computes the LOS velocity dispersion of the deflector galaxy with arbitrary combinations of light and mass models.
        For a detailed description, visit the description of the Galkin() class.
        Additionaly to executing the Galkin routine, it has an optional Multi-Gaussian-Expansion decomposition of lens
        and light models that do not have a three-dimensional distribution built in, such as Sersic profiles etc.

        The center of all the lens and lens light models that are part of the kinematic estimate must be centered on the
        same point.

        :param kwargs_lens: lens model parameters
        :param kwargs_lens_light: lens light parameters
        :param kwargs_anisotropy: anisotropy parameters (see Galkin module)
        :param kwargs_aperture: aperture parameters (see Galkin module)
        :param psf_fwhm: full width at half maximum of the seeing (Gaussian form)
        :param aperture_type: type of aperture (see Galkin module
        :param anisotropy_model: stellar anisotropy model (see Galkin module)
        :param r_eff: a rough estimate of the half light radius of the lens light in case of computing the MGE of the
         light profile
        :param kwargs_numerics: keyword arguments that contain numerical options (see Galkin module)
        :param MGE_light: bool, if true performs the MGE for the light distribution
        :param MGE_mass: bool, if true performs the MGE for the mass distribution
        :param lens_model_kinematics_bool: bool list of length of the lens model. Only takes a subset of all the models
            as part of the kinematics computation (can be used to ignore substructure, shear etc that do not describe the
            main deflector potential
        :param light_model_kinematics_bool: bool list of length of the light model. Only takes a subset of all the models
            as part of the kinematics computation (can be used to ignore light components that do not describe the main
            deflector
        :return: LOS velocity dispersion [km/s]
        """

        kwargs_cosmo = {
            'D_d': self.lensCosmo.D_d,
            'D_s': self.lensCosmo.D_s,
            'D_ds': self.lensCosmo.D_ds
        }
        mass_profile_list = []
        kwargs_profile = []
        if lens_model_kinematics_bool is None:
            lens_model_kinematics_bool = [True] * len(kwargs_lens)
        for i, lens_model in enumerate(self.kwargs_options['lens_model_list']):
            if lens_model_kinematics_bool[i] is True:
                mass_profile_list.append(lens_model)
                if lens_model in ['INTERPOL', 'INTERPOL_SCLAED']:
                    center_x, center_y = self._lensModelExt.lens_center(
                        kwargs_lens, k=i)
                    kwargs_lens_i = copy.deepcopy(kwargs_lens[i])
                    kwargs_lens_i['grid_interp_x'] -= center_x
                    kwargs_lens_i['grid_interp_y'] -= center_y
                else:
                    kwargs_lens_i = {
                        k: v
                        for k, v in kwargs_lens[i].items()
                        if not k in ['center_x', 'center_y']
                    }
                kwargs_profile.append(kwargs_lens_i)

        if MGE_mass is True:
            lensModel = LensModel(lens_model_list=mass_profile_list)
            massModel = LensModelExtensions(lensModel)
            theta_E = massModel.effective_einstein_radius(kwargs_profile)
            r_array = np.logspace(-4, 2, 200) * theta_E
            mass_r = lensModel.kappa(r_array, np.zeros_like(r_array),
                                     kwargs_profile)
            amps, sigmas, norm = mge.mge_1d(r_array, mass_r, N=20)
            mass_profile_list = ['MULTI_GAUSSIAN_KAPPA']
            kwargs_profile = [{'amp': amps, 'sigma': sigmas}]

        light_profile_list = []
        kwargs_light = []
        if light_model_kinematics_bool is None:
            light_model_kinematics_bool = [True] * len(kwargs_lens_light)
        for i, light_model in enumerate(
                self.kwargs_options['lens_light_model_list']):
            if light_model_kinematics_bool[i]:
                light_profile_list.append(light_model)
                kwargs_lens_light_i = {
                    k: v
                    for k, v in kwargs_lens_light[i].items()
                    if not k in ['center_x', 'center_y']
                }
                if 'q' in kwargs_lens_light_i:
                    kwargs_lens_light_i['q'] = 1
                kwargs_light.append(kwargs_lens_light_i)
        if r_eff is None:
            lensAnalysis = LensAnalysis(
                {'lens_light_model_list': light_profile_list})
            r_eff = lensAnalysis.half_light_radius_lens(
                kwargs_light, model_bool_list=light_model_kinematics_bool)
        if Hernquist_approx is True:
            light_profile_list = ['HERNQUIST']
            kwargs_light = [{'Rs': r_eff, 'amp': 1.}]
        else:
            if MGE_light is True:
                lightModel = LightModel(light_profile_list)
                r_array = np.logspace(-3, 2, 200) * r_eff * 2
                flux_r = lightModel.surface_brightness(r_array, 0,
                                                       kwargs_light)
                amps, sigmas, norm = mge.mge_1d(r_array, flux_r, N=20)
                light_profile_list = ['MULTI_GAUSSIAN']
                kwargs_light = [{'amp': amps, 'sigma': sigmas}]

        galkin = Galkin(mass_profile_list,
                        light_profile_list,
                        aperture_type=aperture_type,
                        anisotropy_model=anisotropy_model,
                        fwhm=psf_fwhm,
                        kwargs_cosmo=kwargs_cosmo,
                        **kwargs_numerics)
        sigma2 = galkin.vel_disp(kwargs_profile, kwargs_light,
                                 kwargs_anisotropy, kwargs_aperture)
        return sigma2
Exemplo n.º 4
0
    def velocity_disperson_numerical(self,
                                     kwargs_lens,
                                     kwargs_lens_light,
                                     kwargs_anisotropy,
                                     kwargs_aperture,
                                     psf_fwhm,
                                     aperture_type,
                                     anisotropy_model,
                                     r_eff=1.,
                                     kwargs_numerics={},
                                     MGE_light=False,
                                     MGE_mass=False):
        """

        :param kwargs_lens:
        :param kwargs_lens_light:
        :param kwargs_anisotropy:
        :param kwargs_aperature:
        :return:
        """
        kwargs_cosmo = {
            'D_d': self.lensCosmo.D_d,
            'D_s': self.lensCosmo.D_s,
            'D_ds': self.lensCosmo.D_ds
        }
        mass_profile_list = []
        kwargs_profile = []
        lens_model_internal_bool = self.kwargs_options.get(
            'lens_model_deflector_bool', [True] * len(kwargs_lens))
        for i, lens_model in enumerate(self.kwargs_options['lens_model_list']):
            if lens_model_internal_bool[i]:
                mass_profile_list.append(lens_model)
                kwargs_lens_i = {
                    k: v
                    for k, v in kwargs_lens[i].items()
                    if not k in ['center_x', 'center_y']
                }
                kwargs_profile.append(kwargs_lens_i)

        if MGE_mass is True:
            massModel = LensModelExtensions(lens_model_list=mass_profile_list)
            theta_E = massModel.effective_einstein_radius(kwargs_lens)
            r_array = np.logspace(-4, 2, 200) * theta_E
            mass_r = massModel.kappa(r_array, 0, kwargs_profile)
            amps, sigmas, norm = mge.mge_1d(r_array, mass_r, N=20)
            mass_profile_list = ['MULTI_GAUSSIAN_KAPPA']
            kwargs_profile = [{'amp': amps, 'sigma': sigmas}]

        light_profile_list = []
        kwargs_light = []
        lens_light_model_internal_bool = self.kwargs_options.get(
            'light_model_deflector_bool', [True] * len(kwargs_lens_light))
        for i, light_model in enumerate(
                self.kwargs_options['lens_light_model_list']):
            if lens_light_model_internal_bool[i]:
                light_profile_list.append(light_model)
                kwargs_Lens_light_i = {
                    k: v
                    for k, v in kwargs_lens_light[i].items()
                    if not k in ['center_x', 'center_y']
                }
                if 'q' in kwargs_Lens_light_i:
                    kwargs_Lens_light_i['q'] = 1
                kwargs_light.append(kwargs_Lens_light_i)

        if MGE_light is True:
            lightModel = LightModel(light_profile_list)
            r_array = np.logspace(-3, 2, 200) * r_eff * 2
            flux_r = lightModel.surface_brightness(r_array, 0, kwargs_light)
            amps, sigmas, norm = mge.mge_1d(r_array, flux_r, N=20)
            light_profile_list = ['MULTI_GAUSSIAN']
            kwargs_light = [{'amp': amps, 'sigma': sigmas}]

        galkin = Galkin(mass_profile_list,
                        light_profile_list,
                        aperture_type=aperture_type,
                        anisotropy_model=anisotropy_model,
                        fwhm=psf_fwhm,
                        kwargs_cosmo=kwargs_cosmo,
                        kwargs_numerics=kwargs_numerics)
        sigma_v = galkin.vel_disp(kwargs_profile,
                                  kwargs_light,
                                  kwargs_anisotropy,
                                  kwargs_aperture,
                                  r_eff=r_eff)
        return sigma_v
Exemplo n.º 5
0
class LensAnalysis(object):
    """
    class to compute flux ratio anomalies, inherited from standard MakeImage
    """
    def __init__(self, kwargs_model):
        self.LensLightModel = LightModel(kwargs_model.get('lens_light_model_list', ['NONE']))
        self.SourceModel = LightModel(kwargs_model.get('source_light_model_list', ['NONE']))
        self.LensModel = LensModelExtensions(lens_model_list=kwargs_model['lens_model_list'])
        self.PointSource = PointSource(point_source_type_list=kwargs_model.get('point_source_model_list', ['NONE']))
        self.kwargs_model = kwargs_model
        self.NumLensModel = NumericLens(lens_model_list=kwargs_model['lens_model_list'])
        self.gaussian = Gaussian()

    def fermat_potential(self, kwargs_lens, kwargs_ps):
        ra_pos, dec_pos = self.PointSource.image_position(kwargs_ps, kwargs_lens)
        ra_pos = ra_pos[0]
        dec_pos = dec_pos[0]
        ra_source, dec_source = self.LensModel.ray_shooting(ra_pos, dec_pos, kwargs_lens)
        ra_source = np.mean(ra_source)
        dec_source = np.mean(dec_source)
        fermat_pot = self.LensModel.fermat_potential(ra_pos, dec_pos, ra_source, dec_source, kwargs_lens)
        return fermat_pot

    def half_light_radius_lens(self, kwargs_lens_light, deltaPix=None, numPix=None):
        """
        computes numerically the half-light-radius of the deflector light and the total photon flux

        :param kwargs_lens_light:
        :return:
        """
        if numPix is None:
            numPix = 1000
        if deltaPix is None:
            deltaPix = 0.05
        x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix)
        lens_light = self._lens_light_internal(x_grid, y_grid, kwargs_lens_light)
        R_h = analysis_util.half_light_radius(lens_light, x_grid, y_grid)
        return R_h

    def half_light_radius_source(self, kwargs_source, deltaPix=None, numPix=None):
        """
        computes numerically the half-light-radius of the deflector light and the total photon flux

        :param kwargs_lens_light:
        :return:
        """
        if numPix is None:
            numPix = 1000
        if deltaPix is None:
            deltaPix = 0.005
        x_grid, y_grid = util.make_grid(numPix=numPix, deltapix=deltaPix)
        source_light = self.SourceModel.surface_brightness(x_grid, y_grid, kwargs_source)
        R_h = analysis_util.half_light_radius(source_light, x_grid, y_grid, center_x=kwargs_source[0]['center_x'], center_y=kwargs_source[0]['center_y'])
        return R_h

    def _lens_light_internal(self, x_grid, y_grid, kwargs_lens_light):
        """

        :param x_grid:
        :param y_grid:
        :param kwargs_lens_light:
        :return:
        """
        kwargs_lens_light_copy = copy.deepcopy(kwargs_lens_light)
        lens_light_model_internal_bool = self.kwargs_model.get('light_model_deflector_bool', [True] * len(kwargs_lens_light))
        lens_light = np.zeros_like(x_grid)
        for i, bool in enumerate(lens_light_model_internal_bool):
            if bool is True:
                kwargs_lens_light_copy[i]['center_x'] = 0
                kwargs_lens_light_copy[i]['center_y'] = 0
                lens_light_i = self.LensLightModel.surface_brightness(x_grid, y_grid, kwargs_lens_light_copy, k=i)
                lens_light += lens_light_i
        return lens_light

    def multi_gaussian_lens_light(self, kwargs_lens_light, n_comp=20):
        """
        multi-gaussian decomposition of the lens light profile (in 1-dimension)

        :param kwargs_lens_light:
        :param n_comp:
        :return:
        """
        r_h = self.half_light_radius_lens(kwargs_lens_light)
        r_array = np.logspace(-3, 2, 200) * r_h * 2
        #r_array = np.logspace(-2, 1, 50) * r_h
        flux_r = self._lens_light_internal(r_array, np.zeros_like(r_array), kwargs_lens_light)
        amplitudes, sigmas, norm = mge.mge_1d(r_array, flux_r, N=n_comp)
        return amplitudes, sigmas

    def multi_gaussian_lens(self, kwargs_lens, n_comp=20):
        """
        multi-gaussian lens model in convergence space

        :param kwargs_lens:
        :param n_comp:
        :return:
        """
        kwargs_lens_copy = copy.deepcopy(kwargs_lens)
        if 'center_x' in kwargs_lens_copy[0]:
            center_x = kwargs_lens_copy[0]['center_x']
            center_y = kwargs_lens_copy[0]['center_y']
        else:
            raise ValueError('no keyword center_x defined!')
        theta_E = self.LensModel.effective_einstein_radius(kwargs_lens)
        r_array = np.logspace(-4, 2, 200) * theta_E
        #r_array = np.logspace(-2, 1, 50) * theta_E
        lens_model_internal_bool = self.kwargs_model.get('lens_model_internal_bool', [True] * len(kwargs_lens))
        kappa_s = np.zeros_like(r_array)
        for i in range(len(kwargs_lens_copy)):
            if lens_model_internal_bool[i]:
                if 'center_x' in kwargs_lens_copy[0]:
                    kwargs_lens_copy[i]['center_x'] -= center_x
                    kwargs_lens_copy[i]['center_y'] -= center_y
                kappa_s += self.LensModel.kappa(r_array, np.zeros_like(r_array), kwargs_lens_copy, k=i)
        amplitudes, sigmas, norm = mge.mge_1d(r_array, kappa_s, N=n_comp)
        return amplitudes, sigmas, center_x, center_y

    def flux_components(self, kwargs_light, n_grid=400, delta_grid=0.01, deltaPix=0.05, type="lens"):
        """
        computes the total flux in each component of the model

        :param kwargs_light:
        :param n_grid:
        :param delta_grid:
        :return:
        """
        flux_list = []
        R_h_list = []
        x_grid, y_grid = util.make_grid(numPix=n_grid, deltapix=delta_grid)
        kwargs_copy = copy.deepcopy(kwargs_light)
        for k, kwargs in enumerate(kwargs_light):
            if 'center_x' in kwargs_copy[k]:
                kwargs_copy[k]['center_x'] = 0
                kwargs_copy[k]['center_y'] = 0
            if type == 'lens':
                light = self.LensLightModel.surface_brightness(x_grid, y_grid, kwargs_copy, k=k)
            elif type == 'source':
                light = self.SourceModel.surface_brightness(x_grid, y_grid, kwargs_copy, k=k)
            else:
                raise ValueError("type %s not supported!" % type)
            flux = np.sum(light)*delta_grid**2/ deltaPix**2
            R_h = analysis_util.half_light_radius(light, x_grid, y_grid)
            flux_list.append(flux)
            R_h_list.append(R_h)
        return flux_list, R_h_list

    @staticmethod
    def buldge_disk_ratio(kwargs_buldge_disk):
        """
        computes the buldge-to-disk ratio of the

        :param kwargs_buldge_disk: kwargs of the buldge2disk function
        :return:
        """
        kwargs_bd = copy.deepcopy(kwargs_buldge_disk)
        kwargs_bd['center_x'] = 0
        kwargs_bd['center_y'] = 0
        deltaPix = 0.05
        numPix = 200
        x_grid, y_grid = util.make_grid(numPix, deltaPix)
        from lenstronomy.LightModel.Profiles.sersic import BuldgeDisk
        bd_class = BuldgeDisk()
        light_grid = bd_class.function(x_grid, y_grid, **kwargs_bd)
        light_tot = np.sum(light_grid)
        kwargs_bd['I0_d'] = 0
        light_grid = bd_class.function(x_grid, y_grid, **kwargs_bd)
        light_buldge = np.sum(light_grid)
        return light_tot, light_buldge

    def error_map_source(self, kwargs_source, x_grid, y_grid, cov_param):
        """
        variance of the linear source reconstruction in the source plane coordinates,
        computed by the diagonal elements of the covariance matrix of the source reconstruction as a sum of the errors
        of the basis set.

        :param kwargs_source: keyword arguments of source model
        :param x_grid: x-axis of positions to compute error map
        :param y_grid: y-axis of positions to compute error map
        :param cov_param: covariance matrix of liner inversion parameters
        :return: diagonal covariance errors at the positions (x_grid, y_grid)
        """

        error_map = np.zeros_like(x_grid)
        basis_functions, n_source = self.SourceModel.functions_split(x_grid, y_grid, kwargs_source)
        basis_functions = np.array(basis_functions)

        if cov_param is not None:
            for i in range(len(error_map)):
                error_map[i] = basis_functions[:, i].T.dot(cov_param[:n_source, :n_source]).dot(basis_functions[:, i])
        return error_map