示例#1
0
文件: galkin.py 项目: sibirrer/galkin
class Galkin(object):
    """
    major class to compute velocity dispersion measurements given light and mass models
    """
    def __init__(self,
                 mass_profile_list,
                 light_profile_list,
                 aperture_type='slit',
                 anisotropy_model='isotropic',
                 fwhm=0.7,
                 kwargs_numerics={},
                 kwargs_cosmo={
                     'D_d': 1000,
                     'D_s': 2000,
                     'D_ds': 500
                 }):
        self.massProfile = MassProfile(mass_profile_list, kwargs_cosmo)
        self.lightProfile = LightProfile(light_profile_list)
        self.aperture = Aperture(aperture_type)
        self.anisotropy = MamonLokasAnisotropy(anisotropy_model)
        self.FWHM = fwhm
        self.cosmo = Cosmo(kwargs_cosmo)
        self._num_sampling = kwargs_numerics.get('sampling_number', 1000)
        self._interp_grid_num = kwargs_numerics.get('interpol_grid_num', 1000)
        self._log_int = kwargs_numerics.get('log_integration', False)
        self._max_integrate = kwargs_numerics.get(
            'max_integrate',
            100)  # maximal integration (and interpolation) in units of arcsecs

    def vel_disp(self,
                 kwargs_mass,
                 kwargs_light,
                 kwargs_anisotropy,
                 kwargs_apertur,
                 r_eff=1.):
        """
        computes the averaged LOS velocity dispersion in the slit (convolved)
        :param gamma:
        :param phi_E:
        :param r_eff:
        :param r_ani:
        :param R_slit:
        :param FWHM:
        :return:
        """
        sigma2_R_sum = 0
        for i in range(0, self._num_sampling):
            sigma2_R = self.draw_one_sigma2(kwargs_mass,
                                            kwargs_light,
                                            kwargs_anisotropy,
                                            kwargs_apertur,
                                            r_eff=r_eff)
            sigma2_R_sum += sigma2_R
        sigma_s2_average = sigma2_R_sum / self._num_sampling
        # apply unit conversion from arc seconds and deflections to physical velocity disperison in (km/s)
        sigma_s2_average *= 2 * const.G  # correcting for integral prefactor
        return np.sqrt(sigma_s2_average /
                       (const.arcsec**2 * self.cosmo.D_d**2 *
                        const.Mpc)) / 1000.  # in units of km/s

    def draw_one_sigma2(self,
                        kwargs_mass,
                        kwargs_light,
                        kwargs_anisotropy,
                        kwargs_aperture,
                        r_eff=1.):
        """

        :param kwargs_mass:
        :param kwargs_light:
        :param kwargs_anisotropy:
        :param kwargs_aperture:
        :return:
        """
        while True:
            R = self.lightProfile.draw_light_2d(kwargs_light,
                                                r_eff=r_eff)  # draw r
            x, y = util.draw_xy(R)  # draw projected R
            x_, y_ = util.displace_PSF(x, y, self.FWHM)  # displace via PSF
            bool = self.aperture.aperture_select(x_, y_, kwargs_aperture)
            if bool is True:
                break
        sigma2_R = self.sigma2_R(R, kwargs_mass, kwargs_light,
                                 kwargs_anisotropy)
        return sigma2_R

    def sigma2_R(self, R, kwargs_mass, kwargs_light, kwargs_anisotropy):
        """
        returns unweighted los velocity dispersion
        :param R:
        :param kwargs_mass:
        :param kwargs_light:
        :param kwargs_anisotropy:
        :return:
        """
        I_R_sigma2 = self.I_R_simga2(R, kwargs_mass, kwargs_light,
                                     kwargs_anisotropy)
        I_R = self.lightProfile.light_2d(R, kwargs_light)
        #I_R = self.lightProfile._integrand_light(R, kwargs_light)
        return I_R_sigma2 / I_R

    def I_R_simga2(self, R, kwargs_mass, kwargs_light, kwargs_anisotropy):
        """
        equation A15 in Mamon&Lokas 2005 as a logarithmic numerical integral
        modulo pre-factor 2*G
        :param R:
        :param kwargs_mass:
        :param kwargs_light:
        :param kwargs_anisotropy:
        :return:
        """
        if self._log_int is True:
            min_log = np.log10(R + 0.0001)
            max_log = np.log10(self._max_integrate)
            r_array = np.logspace(min_log, max_log, self._interp_grid_num)
            dlog_r = (np.log10(r_array[1]) - np.log10(r_array[0])) * np.log(10)
            IR_sigma2_dr = self._integrand_A15(
                r_array, R, kwargs_mass, kwargs_light,
                kwargs_anisotropy) * dlog_r * r_array
        else:
            r_array = np.linspace(R + 0.0001, self._max_integrate,
                                  self._interp_grid_num)
            dr = r_array[1] - r_array[0]
            IR_sigma2_dr = self._integrand_A15(
                r_array, R, kwargs_mass, kwargs_light, kwargs_anisotropy) * dr
        IR_sigma2 = np.sum(IR_sigma2_dr)
        return IR_sigma2

    def _integrand_A15(self, r, R, kwargs_mass, kwargs_light,
                       kwargs_anisotropy):
        """
        integrand of A15 (in log space)
        :param r:
        :param kwargs_mass:
        :param kwargs_light:
        :param kwargs_anisotropy:
        :return:
        """
        k_r = self.anisotropy.K(r, R, kwargs_anisotropy)
        l_r = self.lightProfile.light_3d_interp(r, kwargs_light)
        m_r = self.massProfile.mass_3d_interp(r, kwargs_mass)
        out = k_r * l_r * m_r / r
        return out
示例#2
0
class GalKin_old(object):
    """
    master class for all computations
    """
    def __init__(self,
                 aperture='slit',
                 mass_profile='power_law',
                 light_profile='Hernquist',
                 anisotropy_type='r_ani',
                 psf_fwhm=0.7,
                 kwargs_cosmo={
                     'D_d': 1000,
                     'D_s': 2000,
                     'D_ds': 500
                 }):
        """
        initializes the observation condition and masks
        :param aperture_type: string
        :param psf_fwhm: float
        """
        self._mass_profile = mass_profile
        self._fwhm = psf_fwhm
        self._kwargs_cosmo = kwargs_cosmo
        self.lightProfile = LightProfile_old(light_profile)
        self.aperture = Aperture(aperture)
        self.anisotropy = Anisotropy(anisotropy_type)
        self.FWHM = psf_fwhm
        self.jeans_solver = Jeans_solver(kwargs_cosmo, mass_profile,
                                         light_profile, anisotropy_type)

    def vel_disp(self,
                 kwargs_profile,
                 kwargs_aperture,
                 kwargs_light,
                 kwargs_anisotropy,
                 num=1000):
        """
        computes the averaged LOS velocity dispersion in the slit (convolved)
        :param gamma:
        :param phi_E:
        :param r_eff:
        :param r_ani:
        :param R_slit:
        :param FWHM:
        :return:
        """
        sigma_s2_sum = 0
        for i in range(0, num):
            sigma_s2_draw = self._vel_disp_one(kwargs_profile, kwargs_aperture,
                                               kwargs_light, kwargs_anisotropy)
            sigma_s2_sum += sigma_s2_draw
        sigma_s2_average = sigma_s2_sum / num
        return np.sqrt(sigma_s2_average)

    def _vel_disp_one(self, kwargs_profile, kwargs_aperture, kwargs_light,
                      kwargs_anisotropy):
        """
        computes one realisation of the velocity dispersion realized in the slit
        :param gamma:
        :param rho0_r0_gamma:
        :param r_eff:
        :param r_ani:
        :param R_slit:
        :param dR_slit:
        :param FWHM:
        :return:
        """

        while True:
            r = self.lightProfile.draw_light(kwargs_light)  # draw r
            R, x, y = util.R_r(r)  # draw projected R
            x_, y_ = util.displace_PSF(x, y, self.FWHM)  # displace via PSF
            bool = self.aperture.aperture_select(x_, y_, kwargs_aperture)
            if bool is True:
                break
        sigma_s2 = self.sigma_s2(r, R, kwargs_profile, kwargs_anisotropy,
                                 kwargs_light)
        return sigma_s2

    def sigma_s2(self, r, R, kwargs_profile, kwargs_anisotropy, kwargs_light):
        """
        projected velocity dispersion
        :param r:
        :param R:
        :param r_ani:
        :param a:
        :param gamma:
        :param phi_E:
        :return:
        """
        beta = self.anisotropy.beta_r(r, kwargs_anisotropy)
        return (1 - beta * R**2 / r**2) * self.sigma_r2(
            r, kwargs_profile, kwargs_anisotropy, kwargs_light)

    def sigma_r2(self, r, kwargs_profile, kwargs_anisotropy, kwargs_light):
        """
        computes radial velocity dispersion at radius r (solving the Jeans equation
        :param r:
        :return:
        """
        return self.jeans_solver.sigma_r2(r, kwargs_profile, kwargs_anisotropy,
                                          kwargs_light)