def test_profile_normalization(self): """ Test that the mass enclosed within r200 of the composite profile is correct and check that the ULDM core density is correct. """ profile_args = {'log10_m_uldm': -21, 'uldm_plaw': 1/3, 'scale_nfw':True} mass = 1e10 zl = 0.5 zs = 1.5 single_halo = SingleHalo(mass, 0.5, 0.5, 'ULDM', zl, zl, zs, None, True, profile_args, None) _, _, kwargs_lens, _ = single_halo.lensing_quantities(add_mass_sheet_correction=False) Rs_angle, _ = single_halo.halos[0].lens_cosmo.nfw_physical2angle(mass, single_halo.halos[0].c, zl) sigma_crit = single_halo.halos[0].lens_cosmo.sigmacrit r200 = single_halo.halos[0].c * Rs_angle cnfw_kwargs, uldm_kwargs = kwargs_lens M_nfw = CNFW().mass_3d_lens(r200, cnfw_kwargs['Rs'], cnfw_kwargs['alpha_Rs']*sigma_crit, cnfw_kwargs['r_core']) M_uldm = Uldm().mass_3d_lens(r200, uldm_kwargs['kappa_0']*sigma_crit, uldm_kwargs['theta_c']) npt.assert_almost_equal((M_uldm+M_nfw)/mass,1,decimal=2) # less than 1% error _,theta_c,kappa_0 = single_halo.halos[0].profile_args rho0 = Uldm().density_lens(0,uldm_kwargs['kappa_0'], uldm_kwargs['theta_c']) rhos = CNFW().density_lens(0,cnfw_kwargs['Rs'], cnfw_kwargs['alpha_Rs'], cnfw_kwargs['r_core']) rho_goal = Uldm().density_lens(0,kappa_0,theta_c) npt.assert_array_less(np.array([1-(rho0+rhos)/rho_goal]),np.array([0.03])) # less than 3% error
def _rescaled_cnfw_params(self, cnfw_params, uldm_params): """ :param cnfw_params: cored NFW halo lensing params :param uldm_params: ULDM halo lensing params :return: rescaled cored NFW params to fill up the remainder of the mass budget such that the composite profile has the inputted virial mass. """ r200 = self._c * cnfw_params['Rs'] rho0 = Uldm().density_lens(0, uldm_params['kappa_0'], uldm_params['theta_c']) rhos = CNFW().density_lens(0, cnfw_params['Rs'], cnfw_params['alpha_Rs'], cnfw_params['r_core']) args = (r200, self.mass, cnfw_params['Rs'], cnfw_params['alpha_Rs'], uldm_params['kappa_0'], uldm_params['theta_c'], rho0, rhos) initial_guess = np.array([0.9, 1.1]) bounds = ((0.5, 10), (0.5, 1.5)) method = 'Nelder-Mead' beta, q = minimize(self._function_to_minimize, initial_guess, args, method=method, bounds=bounds, tol=0.1)['x'] if beta < 0: raise ValueError( 'Negative CNFW core radius, tweak your parameters.') elif q < 0: raise ValueError( 'Negative ULDM profile mass, tweak your parameters.') else: pass cnfw_params['r_core'] /= beta uldm_params['kappa_0'] /= q M_nfw = CNFW().mass_3d_lens( r200, cnfw_params['Rs'], cnfw_params['alpha_Rs'] * self._lens_cosmo.sigmacrit, cnfw_params['r_core']) M_uldm = Uldm().mass_3d_lens( r200, uldm_params['kappa_0'] * self._lens_cosmo.sigmacrit, uldm_params['theta_c']) if (self._args['scale_nfw']): # When scale_nfw is True rescale alpha_Rs to improve mass accuracy scale = self.mass / (M_nfw + M_uldm) cnfw_params['alpha_Rs'] *= scale return [cnfw_params, uldm_params]
def _constraint_mass(self, beta, q, r, m_target, rs, alpha_rs, kappa_0, theta_c): """ :param beta: CNFW core radius ('r_core') rescaling parameter :param q: ULDM core density ('kappa_0') rescaling parameter :param r: r200 of CNFW profile :param m_target: halo virial mass :param rs: CNFW scale radius :param alpha_rs: CNFW deflection angle at rs, in absence of core :param kappa_0: ULDM core density :param theta_c: ULDM core radius :return: Evaluated mass constraint equation for CNFW component profile """ r_core = beta * rs sigma_crit = self.lens_cosmo.sigmacrit args_nfw = (r, rs, alpha_rs * sigma_crit, r_core) args_uldm = (r, kappa_0 * sigma_crit, theta_c) m_nfw = CNFW().mass_3d_lens(*args_nfw) / m_target m_uldm = q * Uldm().mass_3d_lens(*args_uldm) / m_target penalty = np.absolute(m_nfw + m_uldm - 1) if np.isnan(penalty): return 1e+12 # penalize if not equal to zero return penalty
def setup(self): prof = CNFW() self.func = prof._F self.rs = 60 self.rmax2d = 40 self.rvir = 350 self.rcore = 10. self.nfw = NFW3DCoreRejectionSampling(self.rs, self.rmax2d, self.rvir, self.rcore)
def __init__(self, rendering_radius, Rs, r_core_host, r200): """ :param rendering_radius: the maximum projected 2D radius where halos are rendered [arcsec] :param Rs: the scale radius of the host dark matter halo [kpc] :param r_core_host: the core radius of the host dark matter halo [kpc] :param r200: the virial radius of the host dark matter halo [kpc] """ self._cnfw_profile = CNFW() self.rmax2d_kpc = rendering_radius self._rs_kpc = Rs self._xmin = 1e-4 self.xmax_2d = rendering_radius / Rs self.xtidal = r_core_host / Rs self.zmax_units_rs = r200 / Rs self._xmin = rendering_radius / 30 / self._rs_kpc self._norm = self._cnfw_profile._F(self._xmin, self.xtidal)
def _import_class(lens_type, custom_class, z_lens=None, z_source=None): """ :param lens_type: string, lens model type :param custom_class: custom class :param z_lens: lens redshift # currently only used in NFW_MC model as this is redshift dependent :param z_source: source redshift # currently only used in NFW_MC model as this is redshift dependent :return: class instance of the lens model type """ if lens_type == 'SHIFT': from lenstronomy.LensModel.Profiles.alpha_shift import Shift return Shift() elif lens_type == 'SHEAR': from lenstronomy.LensModel.Profiles.shear import Shear return Shear() elif lens_type == 'SHEAR_GAMMA_PSI': from lenstronomy.LensModel.Profiles.shear import ShearGammaPsi return ShearGammaPsi() elif lens_type == 'CONVERGENCE': from lenstronomy.LensModel.Profiles.convergence import Convergence return Convergence() elif lens_type == 'FLEXION': from lenstronomy.LensModel.Profiles.flexion import Flexion return Flexion() elif lens_type == 'FLEXIONFG': from lenstronomy.LensModel.Profiles.flexionfg import Flexionfg return Flexionfg() elif lens_type == 'POINT_MASS': from lenstronomy.LensModel.Profiles.point_mass import PointMass return PointMass() elif lens_type == 'SIS': from lenstronomy.LensModel.Profiles.sis import SIS return SIS() elif lens_type == 'SIS_TRUNCATED': from lenstronomy.LensModel.Profiles.sis_truncate import SIS_truncate return SIS_truncate() elif lens_type == 'SIE': from lenstronomy.LensModel.Profiles.sie import SIE return SIE() elif lens_type == 'SPP': from lenstronomy.LensModel.Profiles.spp import SPP return SPP() elif lens_type == 'NIE': from lenstronomy.LensModel.Profiles.nie import NIE return NIE() elif lens_type == 'NIE_SIMPLE': from lenstronomy.LensModel.Profiles.nie import NIEMajorAxis return NIEMajorAxis() elif lens_type == 'CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import Chameleon return Chameleon() elif lens_type == 'DOUBLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import DoubleChameleon return DoubleChameleon() elif lens_type == 'TRIPLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import TripleChameleon return TripleChameleon() elif lens_type == 'SPEP': from lenstronomy.LensModel.Profiles.spep import SPEP return SPEP() elif lens_type == 'SPEMD': from lenstronomy.LensModel.Profiles.spemd import SPEMD return SPEMD() elif lens_type == 'SPEMD_SMOOTH': from lenstronomy.LensModel.Profiles.spemd_smooth import SPEMD_SMOOTH return SPEMD_SMOOTH() elif lens_type == 'NFW': from lenstronomy.LensModel.Profiles.nfw import NFW return NFW() elif lens_type == 'NFW_ELLIPSE': from lenstronomy.LensModel.Profiles.nfw_ellipse import NFW_ELLIPSE return NFW_ELLIPSE() elif lens_type == 'NFW_ELLIPSE_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import NFWEllipseGaussDec return NFWEllipseGaussDec() elif lens_type == 'TNFW': from lenstronomy.LensModel.Profiles.tnfw import TNFW return TNFW() elif lens_type == 'CNFW': from lenstronomy.LensModel.Profiles.cnfw import CNFW return CNFW() elif lens_type == 'CNFW_ELLIPSE': from lenstronomy.LensModel.Profiles.cnfw_ellipse import CNFW_ELLIPSE return CNFW_ELLIPSE() elif lens_type == 'CTNFW_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import CTNFWGaussDec return CTNFWGaussDec() elif lens_type == 'NFW_MC': from lenstronomy.LensModel.Profiles.nfw_mass_concentration import NFWMC return NFWMC(z_lens=z_lens, z_source=z_source) elif lens_type == 'SERSIC': from lenstronomy.LensModel.Profiles.sersic import Sersic return Sersic() elif lens_type == 'SERSIC_ELLIPSE_POTENTIAL': from lenstronomy.LensModel.Profiles.sersic_ellipse_potential import SersicEllipse return SersicEllipse() elif lens_type == 'SERSIC_ELLIPSE_KAPPA': from lenstronomy.LensModel.Profiles.sersic_ellipse_kappa import SersicEllipseKappa return SersicEllipseKappa() elif lens_type == 'SERSIC_ELLIPSE_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition \ import SersicEllipseGaussDec return SersicEllipseGaussDec() elif lens_type == 'PJAFFE': from lenstronomy.LensModel.Profiles.p_jaffe import PJaffe return PJaffe() elif lens_type == 'PJAFFE_ELLIPSE': from lenstronomy.LensModel.Profiles.p_jaffe_ellipse import PJaffe_Ellipse return PJaffe_Ellipse() elif lens_type == 'HERNQUIST': from lenstronomy.LensModel.Profiles.hernquist import Hernquist return Hernquist() elif lens_type == 'HERNQUIST_ELLIPSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse import Hernquist_Ellipse return Hernquist_Ellipse() elif lens_type == 'GAUSSIAN': from lenstronomy.LensModel.Profiles.gaussian_potential import Gaussian return Gaussian() elif lens_type == 'GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_kappa import GaussianKappa return GaussianKappa() elif lens_type == 'GAUSSIAN_ELLIPSE_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_ellipse_kappa import GaussianEllipseKappa return GaussianEllipseKappa() elif lens_type == 'GAUSSIAN_ELLIPSE_POTENTIAL': from lenstronomy.LensModel.Profiles.gaussian_ellipse_potential import GaussianEllipsePotential return GaussianEllipsePotential() elif lens_type == 'MULTI_GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappa return MultiGaussianKappa() elif lens_type == 'MULTI_GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappaEllipse return MultiGaussianKappaEllipse() elif lens_type == 'INTERPOL': from lenstronomy.LensModel.Profiles.interpol import Interpol return Interpol() elif lens_type == 'INTERPOL_SCALED': from lenstronomy.LensModel.Profiles.interpol import InterpolScaled return InterpolScaled() elif lens_type == 'SHAPELETS_POLAR': from lenstronomy.LensModel.Profiles.shapelet_pot_polar import PolarShapelets return PolarShapelets() elif lens_type == 'SHAPELETS_CART': from lenstronomy.LensModel.Profiles.shapelet_pot_cartesian import CartShapelets return CartShapelets() elif lens_type == 'DIPOLE': from lenstronomy.LensModel.Profiles.dipole import Dipole return Dipole() elif lens_type == 'CURVED_ARC': from lenstronomy.LensModel.Profiles.curved_arc import CurvedArc return CurvedArc() elif lens_type == 'ARC_PERT': from lenstronomy.LensModel.Profiles.arc_perturbations import ArcPerturbations return ArcPerturbations() elif lens_type == 'coreBURKERT': from lenstronomy.LensModel.Profiles.coreBurkert import CoreBurkert return CoreBurkert() elif lens_type == 'CORED_DENSITY': from lenstronomy.LensModel.Profiles.cored_density import CoredDensity return CoredDensity() elif lens_type == 'CORED_DENSITY_2': from lenstronomy.LensModel.Profiles.cored_density_2 import CoredDensity2 return CoredDensity2() elif lens_type == 'CORED_DENSITY_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY') elif lens_type == 'CORED_DENSITY_2_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY_2') elif lens_type == 'NumericalAlpha': from lenstronomy.LensModel.Profiles.numerical_deflections import NumericalAlpha return NumericalAlpha(custom_class) else: raise ValueError('%s is not a valid lens model' % lens_type)
def setup(self): self.nfw = CNFW() self.nfw_e = CNFW_ELLIPSE()
class TestCNFWELLIPSE(object): """ tests the Gaussian methods """ def setup(self): self.nfw = CNFW() self.nfw_e = CNFW_ELLIPSE() def test_function(self): x = np.array([1]) y = np.array([2]) Rs = 1. alpha_Rs = 1. q = 1. phi_G = 0 r_core = 0.5 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.nfw.function(x, y, Rs, alpha_Rs, r_core=r_core) values_e = self.nfw_e.function(x, y, Rs, alpha_Rs, r_core, e1, e2) npt.assert_almost_equal(values[0], values_e[0], decimal=5) x = np.array([0]) y = np.array([0]) q = .8 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.nfw_e.function(x, y, Rs, alpha_Rs, r_core, e1, e2) npt.assert_almost_equal(values[0], 0, decimal=4) x = np.array([2, 3, 4]) y = np.array([1, 1, 1]) values = self.nfw_e.function(x, y, Rs, alpha_Rs, r_core, e1, e2) npt.assert_almost_equal(values[0], 1.8550220596738973, decimal=5) npt.assert_almost_equal(values[1], 2.7684470762303537, decimal=5) npt.assert_almost_equal(values[2], 3.7076606717487586, decimal=5) def test_derivatives(self): x = np.array([1]) y = np.array([2]) Rs = 1. alpha_Rs = 1. q = 1. phi_G = 0 r_core = 0.5 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.nfw.derivatives(x, y, Rs, alpha_Rs, r_core) f_x_e, f_y_e = self.nfw_e.derivatives(x, y, Rs, alpha_Rs, r_core, e1, e2) npt.assert_almost_equal(f_x[0], f_x_e[0], decimal=5) npt.assert_almost_equal(f_y[0], f_y_e[0], decimal=5) x = np.array([0]) y = np.array([0]) alpha_Rs = 0 f_x, f_y = self.nfw_e.derivatives(x, y, Rs, alpha_Rs, r_core, e1, e2) npt.assert_almost_equal(f_x[0], 0, decimal=5) npt.assert_almost_equal(f_y[0], 0, decimal=5) x = np.array([1, 3, 4]) y = np.array([2, 1, 1]) alpha_Rs = 1. q = .8 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.nfw_e.derivatives(x, y, Rs, alpha_Rs, r_core, e1, e2) npt.assert_almost_equal(values[0][0], 0.3867896894988756, decimal=5) npt.assert_almost_equal(values[1][0], 1.1603690684966268, decimal=5) npt.assert_almost_equal(values[0][1], 0.9371571936062841, decimal=5) npt.assert_almost_equal(values[1][1], 0.46857859680314207, decimal=5) def test_hessian(self): x = np.array([1]) y = np.array([2]) Rs = 1. alpha_Rs = 1. q = 1. phi_G = 0 r_core = 0.5 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_xx, f_xy, f_yx, f_yy = self.nfw.hessian(x, y, Rs, alpha_Rs, r_core) f_xx_e, f_xy_e, f_yx_e, f_yy_e = self.nfw_e.hessian( x, y, Rs, alpha_Rs, r_core, e1, e2) npt.assert_almost_equal(f_xx[0], f_xx_e[0], decimal=5) npt.assert_almost_equal(f_yy[0], f_yy_e[0], decimal=5) npt.assert_almost_equal(f_xy[0], f_xy_e[0], decimal=5) npt.assert_almost_equal(f_yx[0], f_yx_e[0], decimal=5) x = np.array([1, 3, 4]) y = np.array([2, 1, 1]) q = .8 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.nfw_e.hessian(x, y, Rs, alpha_Rs, r_core, e1, e2) npt.assert_almost_equal(values[0][0], 0.3306510620859626, decimal=5) npt.assert_almost_equal(values[3][0], 0.07493437759187316, decimal=5) npt.assert_almost_equal(values[1][0], -0.1684167189042185, decimal=5) npt.assert_almost_equal(values[0][1], 0.020280774837289073, decimal=5) npt.assert_almost_equal(values[3][1], 0.3955523575349673, decimal=5) npt.assert_almost_equal(values[1][1], -0.14605247788956888, decimal=5) def test_mass_3d(self): Rs = 10. rho0 = 1. r_core = 7. R = np.linspace(0.1 * Rs, 4 * Rs, 1000) alpha_Rs = self.nfw._rho2alpha(rho0, Rs, r_core) m3d = self.nfw.mass_3d(R, Rs, rho0, r_core) m3d_lens = self.nfw_e.mass_3d_lens(R, Rs, alpha_Rs, r_core) npt.assert_almost_equal(m3d, m3d_lens, decimal=8)
def _import_class(self, lens_type, i, custom_class): if lens_type == 'SHIFT': from lenstronomy.LensModel.Profiles.alpha_shift import Shift return Shift() elif lens_type == 'SHEAR': from lenstronomy.LensModel.Profiles.shear import Shear return Shear() elif lens_type == 'CONVERGENCE': from lenstronomy.LensModel.Profiles.convergence import Convergence return Convergence() elif lens_type == 'FLEXION': from lenstronomy.LensModel.Profiles.flexion import Flexion return Flexion() elif lens_type == 'POINT_MASS': from lenstronomy.LensModel.Profiles.point_mass import PointMass return PointMass() elif lens_type == 'SIS': from lenstronomy.LensModel.Profiles.sis import SIS return SIS() elif lens_type == 'SIS_TRUNCATED': from lenstronomy.LensModel.Profiles.sis_truncate import SIS_truncate return SIS_truncate() elif lens_type == 'SIE': from lenstronomy.LensModel.Profiles.sie import SIE return SIE() elif lens_type == 'SPP': from lenstronomy.LensModel.Profiles.spp import SPP return SPP() elif lens_type == 'NIE': from lenstronomy.LensModel.Profiles.nie import NIE return NIE() elif lens_type == 'NIE_SIMPLE': from lenstronomy.LensModel.Profiles.nie import NIE_simple return NIE_simple() elif lens_type == 'CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import Chameleon return Chameleon() elif lens_type == 'DOUBLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import DoubleChameleon return DoubleChameleon() elif lens_type == 'SPEP': from lenstronomy.LensModel.Profiles.spep import SPEP return SPEP() elif lens_type == 'SPEMD': from lenstronomy.LensModel.Profiles.spemd import SPEMD return SPEMD() elif lens_type == 'SPEMD_SMOOTH': from lenstronomy.LensModel.Profiles.spemd_smooth import SPEMD_SMOOTH return SPEMD_SMOOTH() elif lens_type == 'NFW': from lenstronomy.LensModel.Profiles.nfw import NFW return NFW() elif lens_type == 'NFW_ELLIPSE': from lenstronomy.LensModel.Profiles.nfw_ellipse import NFW_ELLIPSE return NFW_ELLIPSE() elif lens_type == 'TNFW': from lenstronomy.LensModel.Profiles.tnfw import TNFW return TNFW() elif lens_type == 'CNFW': from lenstronomy.LensModel.Profiles.cnfw import CNFW return CNFW() elif lens_type == 'SERSIC': from lenstronomy.LensModel.Profiles.sersic import Sersic return Sersic() elif lens_type == 'SERSIC_ELLIPSE': from lenstronomy.LensModel.Profiles.sersic_ellipse import SersicEllipse return SersicEllipse() elif lens_type == 'PJAFFE': from lenstronomy.LensModel.Profiles.p_jaffe import PJaffe return PJaffe() elif lens_type == 'PJAFFE_ELLIPSE': from lenstronomy.LensModel.Profiles.p_jaffe_ellipse import PJaffe_Ellipse return PJaffe_Ellipse() elif lens_type == 'HERNQUIST': from lenstronomy.LensModel.Profiles.hernquist import Hernquist return Hernquist() elif lens_type == 'HERNQUIST_ELLIPSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse import Hernquist_Ellipse return Hernquist_Ellipse() elif lens_type == 'GAUSSIAN': from lenstronomy.LensModel.Profiles.gaussian_potential import Gaussian return Gaussian() elif lens_type == 'GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_kappa import GaussianKappa return GaussianKappa() elif lens_type == 'GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.gaussian_kappa_ellipse import GaussianKappaEllipse return GaussianKappaEllipse() elif lens_type == 'MULTI_GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappa return MultiGaussianKappa() elif lens_type == 'MULTI_GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappaEllipse return MultiGaussianKappaEllipse() elif lens_type == 'INTERPOL': from lenstronomy.LensModel.Profiles.interpol import Interpol return Interpol(grid=False, min_grid_number=100) elif lens_type == 'INTERPOL_SCALED': from lenstronomy.LensModel.Profiles.interpol import InterpolScaled return InterpolScaled() elif lens_type == 'SHAPELETS_POLAR': from lenstronomy.LensModel.Profiles.shapelet_pot_polar import PolarShapelets return PolarShapelets() elif lens_type == 'SHAPELETS_CART': from lenstronomy.LensModel.Profiles.shapelet_pot_cartesian import CartShapelets return CartShapelets() elif lens_type == 'DIPOLE': from lenstronomy.LensModel.Profiles.dipole import Dipole return Dipole() elif lens_type == 'FOREGROUND_SHEAR': from lenstronomy.LensModel.Profiles.shear import Shear self._foreground_shear = True self._foreground_shear_idex = i return Shear() elif lens_type == 'coreBURKERT': from lenstronomy.LensModel.Profiles.coreBurkert import coreBurkert return coreBurkert() elif lens_type == 'NumericalAlpha': from lenstronomy.LensModel.Profiles.numerical_deflections import NumericalAlpha return NumericalAlpha(custom_class[i]) else: raise ValueError('%s is not a valid lens model' % lens_type)
def __init__(self): self.cnfw = CNFW() self._diff = 0.0000000001 super(CNFW_ELLIPSE, self).__init__()
class CNFW_ELLIPSE(LensProfileBase): """ this class contains functions concerning the NFW profile relation are: R_200 = c * Rs """ param_names = [ 'Rs', 'alpha_Rs', 'r_core', 'e1', 'e2', 'center_x', 'center_y' ] lower_limit_default = { 'Rs': 0, 'alpha_Rs': 0, 'r_core': 0, 'e1': -0.5, 'e2': -0.5, 'center_x': -100, 'center_y': -100 } upper_limit_default = { 'Rs': 100, 'alpha_Rs': 10, 'r_core': 100, 'e1': 0.5, 'e2': 0.5, 'center_x': 100, 'center_y': 100 } def __init__(self): self.cnfw = CNFW() self._diff = 0.0000000001 super(CNFW_ELLIPSE, self).__init__() def function(self, x, y, Rs, alpha_Rs, r_core, e1, e2, center_x=0, center_y=0): """ returns double integral of NFW profile """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) x_shift = x - center_x y_shift = y - center_y cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) e = min(abs(1. - q), 0.99) xt1 = (cos_phi * x_shift + sin_phi * y_shift) * np.sqrt(1 - e) xt2 = (-sin_phi * x_shift + cos_phi * y_shift) * np.sqrt(1 + e) R_ = np.sqrt(xt1**2 + xt2**2) f_ = self.cnfw.function(R_, 0, Rs, alpha_Rs, r_core, center_x=0, center_y=0) return f_ def derivatives(self, x, y, Rs, alpha_Rs, r_core, e1, e2, center_x=0, center_y=0): """ returns df/dx and df/dy of the function (integral of NFW) """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) x_shift = x - center_x y_shift = y - center_y cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) e = min(abs(1. - q), 0.99) xt1 = (cos_phi * x_shift + sin_phi * y_shift) * np.sqrt(1 - e) xt2 = (-sin_phi * x_shift + cos_phi * y_shift) * np.sqrt(1 + e) f_x_prim, f_y_prim = self.cnfw.derivatives(xt1, xt2, Rs, alpha_Rs, r_core, center_x=0, center_y=0) f_x_prim *= np.sqrt(1 - e) f_y_prim *= np.sqrt(1 + e) f_x = cos_phi * f_x_prim - sin_phi * f_y_prim f_y = sin_phi * f_x_prim + cos_phi * f_y_prim return f_x, f_y def hessian(self, x, y, Rs, alpha_Rs, r_core, e1, e2, center_x=0, center_y=0): """ returns Hessian matrix of function d^2f/dx^2, d^f/dy^2, d^2/dxdy """ diff = 0.0000001 alpha_ra_dx, alpha_dec_dx = self.derivatives(x + diff, y, Rs, alpha_Rs, r_core, e1, e2, center_x, center_y) alpha_ra_dy, alpha_dec_dy = self.derivatives(x, y + diff, Rs, alpha_Rs, r_core, e1, e2, center_x, center_y) alpha_ra_dx_, alpha_dec_dx_ = self.derivatives(x - diff, y, Rs, alpha_Rs, r_core, e1, e2, center_x, center_y) alpha_ra_dy_, alpha_dec_dy_ = self.derivatives(x, y - diff, Rs, alpha_Rs, r_core, e1, e2, center_x, center_y) dalpha_rara = (alpha_ra_dx - alpha_ra_dx_) / diff / 2 dalpha_radec = (alpha_ra_dy - alpha_ra_dy_) / diff / 2 dalpha_decra = (alpha_dec_dx - alpha_dec_dx_) / diff / 2 dalpha_decdec = (alpha_dec_dy - alpha_dec_dy_) / diff / 2 f_xx = dalpha_rara f_yy = dalpha_decdec f_xy = dalpha_radec f_yx = dalpha_decra return f_xx, f_yy, f_xy def mass_3d_lens(self, R, Rs, alpha_Rs, r_core, e1=0, e2=0): """ mass enclosed a 3d sphere or radius r given a lens parameterization with angular units :return: """ return self.cnfw.mass_3d_lens(R, Rs, alpha_Rs, r_core) def density_lens(self, R, Rs, alpha_Rs, r_core, e1=0, e2=0): """ computes the density at 3d radius r given lens model parameterization. The integral in the LOS projection of this quantity results in the convergence quantity. """ return self.cnfw.density_lens(R, Rs, alpha_Rs, r_core)
class ProjectedNFW(object): """ This class approximates sampling from a full 3D NFW profile by sampling the projected mass of a cored NFW profile in 2D, and then sampling the z coordinate from a cored isothermal profile. This is MUCH faster than sampling from the 3D NFW profile, and is accurate to within a few percent. """ def __init__(self, rendering_radius, Rs, r_core_host, r200): """ :param rendering_radius: the maximum projected 2D radius where halos are rendered [arcsec] :param Rs: the scale radius of the host dark matter halo [kpc] :param r_core_host: the core radius of the host dark matter halo [kpc] :param r200: the virial radius of the host dark matter halo [kpc] """ self._cnfw_profile = CNFW() self.rmax2d_kpc = rendering_radius self._rs_kpc = Rs self._xmin = 1e-4 self.xmax_2d = rendering_radius / Rs self.xtidal = r_core_host / Rs self.zmax_units_rs = r200 / Rs self._xmin = rendering_radius / 30 / self._rs_kpc self._norm = self._cnfw_profile._F(self._xmin, self.xtidal) @classmethod def from_keywords_master(self, keywords_master, lens_cosmo, geometry): keywords = self.keywords(keywords_master, lens_cosmo, geometry) rendering_radius, Rs, r_core_host, r200 = keywords['rendering_radius'], \ keywords['Rs'], \ keywords['r_core'], \ keywords['host_r200'] return ProjectedNFW(rendering_radius, Rs, r_core_host, r200) @staticmethod def keywords(keywords_master, lenscosmo, geometry): args_spatial = {} kpc_per_arcsec_zlens = geometry.kpc_per_arcsec_zlens zlens = lenscosmo.z_lens # EVERYTHING EXPRESSED IN KPC args_spatial['rendering_radius'] = 0.5 * keywords_master[ 'cone_opening_angle'] * kpc_per_arcsec_zlens if 'log_m_host' in keywords_master.keys(): keywords_master['host_m200'] = 10**keywords_master['log_m_host'] if 'host_m200' in keywords_master.keys(): # EVERYTHING EXPRESSED IN KPC if 'host_c' not in keywords_master.keys(): keywords_master['host_c'] = lenscosmo.NFW_concentration( keywords_master['host_m200'], zlens, model='diemer19', mdef='200c', logmhm=keywords_master['log_mc'], scatter=True, scatter_amplitude=keywords_master['c_scatter_dex'], suppression_model=keywords_master['suppression_model'], kwargs_suppresion=keywords_master['kwargs_suppression']) if 'host_Rs' not in keywords_master.keys(): host_Rs = lenscosmo.NFW_params_physical( keywords_master['host_m200'], keywords_master['host_c'], zlens)[1] host_r200 = host_Rs * keywords_master['host_c'] else: host_Rs = keywords_master['host_Rs'] host_r200 = keywords_master['host_Rs'] * keywords_master[ 'host_c'] args_spatial['Rs'] = host_Rs args_spatial['rmax3d'] = host_r200 args_spatial['host_r200'] = host_Rs * keywords_master['host_c'] else: raise Exception( 'Must specify the host halo mass when rendering subhalos') if 'r_tidal' in keywords_master.keys(): if isinstance(keywords_master['r_tidal'], str): if keywords_master['r_tidal'] == 'Rs': args_spatial['r_core'] = args_spatial['Rs'] else: if keywords_master['r_tidal'][-2:] != 'Rs': raise ValueError( 'if specifying the tidal core radius as number*Rs, the last two ' 'letters in the string must be "Rs".') scale = float(keywords_master['r_tidal'][:-2]) args_spatial['r_core'] = scale * args_spatial['Rs'] else: args_spatial['r_core'] = keywords_master['r_tidal'] return args_spatial def cdf(self, u): arg = u * np.arctan(self.zmax_units_rs / self.xtidal) return self.xtidal * np.tan(arg) def _projected_pdf(self, r2d_kpc): x = r2d_kpc / self._rs_kpc if isinstance(x, float) or isinstance(x, int): x = max(x, self._xmin) else: x[np.where(x < self._xmin)] = self._xmin p = self._cnfw_profile._F(x, self.xtidal) / self._norm return p def draw(self, N, rescale=1.0, center_x=0., center_y=0.): if N == 0: return [], [], [], [] n = 0 while True: _x_kpc, _y_kpc, _r2d, _r3d = self._draw_uniform( N, rescale, center_x, center_y) prob = self._projected_pdf(_r2d) u = np.random.uniform(size=len(prob)) keep = np.where(u < prob)[0] if n == 0: x_kpc = _x_kpc[keep] y_kpc = _y_kpc[keep] r3d = _r3d[keep] else: x_kpc = np.append(x_kpc, _x_kpc[keep]) y_kpc = np.append(y_kpc, _y_kpc[keep]) r3d = np.append(r3d, _r3d[keep]) n += len(keep) if n >= N: break return x_kpc[0:N], y_kpc[0:N], r3d[0:N] def _draw_uniform(self, N, rescale=1.0, center_x=0., center_y=0.): if N == 0: return [], [], [], [] angle = np.random.uniform(0, 2 * np.pi, int(N)) rmax = self.xmax_2d * rescale r = np.random.uniform(0, rmax**2, int(N)) x_arcsec = r**.5 * np.cos(angle) y_arcsec = r**.5 * np.sin(angle) x_arcsec += center_x y_arcsec += center_y x_kpc, y_kpc = x_arcsec * self._rs_kpc, y_arcsec * self._rs_kpc u = np.random.uniform(self._xmin, 0.999999, len(x_kpc)) z_units_rs = self.cdf(u) z_kpc = z_units_rs * self._rs_kpc return np.array(x_kpc), np.array(y_kpc), np.hypot( x_kpc, y_kpc), np.sqrt(x_kpc**2 + y_kpc**2 + z_kpc**2)
def _import_class(lens_type, custom_class, kwargs_interp, z_lens=None, z_source=None): """ :param lens_type: string, lens model type :param custom_class: custom class :param z_lens: lens redshift # currently only used in NFW_MC model as this is redshift dependent :param z_source: source redshift # currently only used in NFW_MC model as this is redshift dependent :param kwargs_interp: interpolation keyword arguments specifying the numerics. See description in the Interpolate() class. Only applicable for 'INTERPOL' and 'INTERPOL_SCALED' models. :return: class instance of the lens model type """ if lens_type == 'SHIFT': from lenstronomy.LensModel.Profiles.constant_shift import Shift return Shift() elif lens_type == 'NIE_POTENTIAL': from lenstronomy.LensModel.Profiles.nie_potential import NIE_POTENTIAL return NIE_POTENTIAL() elif lens_type == 'CONST_MAG': from lenstronomy.LensModel.Profiles.const_mag import ConstMag return ConstMag() elif lens_type == 'SHEAR': from lenstronomy.LensModel.Profiles.shear import Shear return Shear() elif lens_type == 'SHEAR_GAMMA_PSI': from lenstronomy.LensModel.Profiles.shear import ShearGammaPsi return ShearGammaPsi() elif lens_type == 'SHEAR_REDUCED': from lenstronomy.LensModel.Profiles.shear import ShearReduced return ShearReduced() elif lens_type == 'CONVERGENCE': from lenstronomy.LensModel.Profiles.convergence import Convergence return Convergence() elif lens_type == 'HESSIAN': from lenstronomy.LensModel.Profiles.hessian import Hessian return Hessian() elif lens_type == 'FLEXION': from lenstronomy.LensModel.Profiles.flexion import Flexion return Flexion() elif lens_type == 'FLEXIONFG': from lenstronomy.LensModel.Profiles.flexionfg import Flexionfg return Flexionfg() elif lens_type == 'POINT_MASS': from lenstronomy.LensModel.Profiles.point_mass import PointMass return PointMass() elif lens_type == 'SIS': from lenstronomy.LensModel.Profiles.sis import SIS return SIS() elif lens_type == 'SIS_TRUNCATED': from lenstronomy.LensModel.Profiles.sis_truncate import SIS_truncate return SIS_truncate() elif lens_type == 'SIE': from lenstronomy.LensModel.Profiles.sie import SIE return SIE() elif lens_type == 'SPP': from lenstronomy.LensModel.Profiles.spp import SPP return SPP() elif lens_type == 'NIE': from lenstronomy.LensModel.Profiles.nie import NIE return NIE() elif lens_type == 'NIE_SIMPLE': from lenstronomy.LensModel.Profiles.nie import NIEMajorAxis return NIEMajorAxis() elif lens_type == 'CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import Chameleon return Chameleon() elif lens_type == 'DOUBLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import DoubleChameleon return DoubleChameleon() elif lens_type == 'TRIPLE_CHAMELEON': from lenstronomy.LensModel.Profiles.chameleon import TripleChameleon return TripleChameleon() elif lens_type == 'SPEP': from lenstronomy.LensModel.Profiles.spep import SPEP return SPEP() elif lens_type == 'PEMD': from lenstronomy.LensModel.Profiles.pemd import PEMD return PEMD() elif lens_type == 'SPEMD': from lenstronomy.LensModel.Profiles.spemd import SPEMD return SPEMD() elif lens_type == 'EPL': from lenstronomy.LensModel.Profiles.epl import EPL return EPL() elif lens_type == 'EPL_NUMBA': from lenstronomy.LensModel.Profiles.epl_numba import EPL_numba return EPL_numba() elif lens_type == 'SPL_CORE': from lenstronomy.LensModel.Profiles.splcore import SPLCORE return SPLCORE() elif lens_type == 'NFW': from lenstronomy.LensModel.Profiles.nfw import NFW return NFW() elif lens_type == 'NFW_ELLIPSE': from lenstronomy.LensModel.Profiles.nfw_ellipse import NFW_ELLIPSE return NFW_ELLIPSE() elif lens_type == 'NFW_ELLIPSE_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import NFWEllipseGaussDec return NFWEllipseGaussDec() elif lens_type == 'NFW_ELLIPSE_CSE': from lenstronomy.LensModel.Profiles.nfw_ellipse_cse import NFW_ELLIPSE_CSE return NFW_ELLIPSE_CSE() elif lens_type == 'TNFW': from lenstronomy.LensModel.Profiles.tnfw import TNFW return TNFW() elif lens_type == 'TNFW_ELLIPSE': from lenstronomy.LensModel.Profiles.tnfw_ellipse import TNFW_ELLIPSE return TNFW_ELLIPSE() elif lens_type == 'CNFW': from lenstronomy.LensModel.Profiles.cnfw import CNFW return CNFW() elif lens_type == 'CNFW_ELLIPSE': from lenstronomy.LensModel.Profiles.cnfw_ellipse import CNFW_ELLIPSE return CNFW_ELLIPSE() elif lens_type == 'CTNFW_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import CTNFWGaussDec return CTNFWGaussDec() elif lens_type == 'NFW_MC': from lenstronomy.LensModel.Profiles.nfw_mass_concentration import NFWMC return NFWMC(z_lens=z_lens, z_source=z_source) elif lens_type == 'SERSIC': from lenstronomy.LensModel.Profiles.sersic import Sersic return Sersic() elif lens_type == 'SERSIC_ELLIPSE_POTENTIAL': from lenstronomy.LensModel.Profiles.sersic_ellipse_potential import SersicEllipse return SersicEllipse() elif lens_type == 'SERSIC_ELLIPSE_KAPPA': from lenstronomy.LensModel.Profiles.sersic_ellipse_kappa import SersicEllipseKappa return SersicEllipseKappa() elif lens_type == 'SERSIC_ELLIPSE_GAUSS_DEC': from lenstronomy.LensModel.Profiles.gauss_decomposition import SersicEllipseGaussDec return SersicEllipseGaussDec() elif lens_type == 'PJAFFE': from lenstronomy.LensModel.Profiles.p_jaffe import PJaffe return PJaffe() elif lens_type == 'PJAFFE_ELLIPSE': from lenstronomy.LensModel.Profiles.p_jaffe_ellipse import PJaffe_Ellipse return PJaffe_Ellipse() elif lens_type == 'HERNQUIST': from lenstronomy.LensModel.Profiles.hernquist import Hernquist return Hernquist() elif lens_type == 'HERNQUIST_ELLIPSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse import Hernquist_Ellipse return Hernquist_Ellipse() elif lens_type == 'HERNQUIST_ELLIPSE_CSE': from lenstronomy.LensModel.Profiles.hernquist_ellipse_cse import HernquistEllipseCSE return HernquistEllipseCSE() elif lens_type == 'GAUSSIAN': from lenstronomy.LensModel.Profiles.gaussian_potential import Gaussian return Gaussian() elif lens_type == 'GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_kappa import GaussianKappa return GaussianKappa() elif lens_type == 'GAUSSIAN_ELLIPSE_KAPPA': from lenstronomy.LensModel.Profiles.gaussian_ellipse_kappa import GaussianEllipseKappa return GaussianEllipseKappa() elif lens_type == 'GAUSSIAN_ELLIPSE_POTENTIAL': from lenstronomy.LensModel.Profiles.gaussian_ellipse_potential import GaussianEllipsePotential return GaussianEllipsePotential() elif lens_type == 'MULTI_GAUSSIAN_KAPPA': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappa return MultiGaussianKappa() elif lens_type == 'MULTI_GAUSSIAN_KAPPA_ELLIPSE': from lenstronomy.LensModel.Profiles.multi_gaussian_kappa import MultiGaussianKappaEllipse return MultiGaussianKappaEllipse() elif lens_type == 'INTERPOL': from lenstronomy.LensModel.Profiles.interpol import Interpol return Interpol(**kwargs_interp) elif lens_type == 'INTERPOL_SCALED': from lenstronomy.LensModel.Profiles.interpol import InterpolScaled return InterpolScaled(**kwargs_interp) elif lens_type == 'SHAPELETS_POLAR': from lenstronomy.LensModel.Profiles.shapelet_pot_polar import PolarShapelets return PolarShapelets() elif lens_type == 'SHAPELETS_CART': from lenstronomy.LensModel.Profiles.shapelet_pot_cartesian import CartShapelets return CartShapelets() elif lens_type == 'DIPOLE': from lenstronomy.LensModel.Profiles.dipole import Dipole return Dipole() elif lens_type == 'CURVED_ARC_CONST': from lenstronomy.LensModel.Profiles.curved_arc_const import CurvedArcConst return CurvedArcConst() elif lens_type == 'CURVED_ARC_CONST_MST': from lenstronomy.LensModel.Profiles.curved_arc_const import CurvedArcConstMST return CurvedArcConstMST() elif lens_type == 'CURVED_ARC_SPP': from lenstronomy.LensModel.Profiles.curved_arc_spp import CurvedArcSPP return CurvedArcSPP() elif lens_type == 'CURVED_ARC_SIS_MST': from lenstronomy.LensModel.Profiles.curved_arc_sis_mst import CurvedArcSISMST return CurvedArcSISMST() elif lens_type == 'CURVED_ARC_SPT': from lenstronomy.LensModel.Profiles.curved_arc_spt import CurvedArcSPT return CurvedArcSPT() elif lens_type == 'CURVED_ARC_TAN_DIFF': from lenstronomy.LensModel.Profiles.curved_arc_tan_diff import CurvedArcTanDiff return CurvedArcTanDiff() elif lens_type == 'ARC_PERT': from lenstronomy.LensModel.Profiles.arc_perturbations import ArcPerturbations return ArcPerturbations() elif lens_type == 'coreBURKERT': from lenstronomy.LensModel.Profiles.coreBurkert import CoreBurkert return CoreBurkert() elif lens_type == 'CORED_DENSITY': from lenstronomy.LensModel.Profiles.cored_density import CoredDensity return CoredDensity() elif lens_type == 'CORED_DENSITY_2': from lenstronomy.LensModel.Profiles.cored_density_2 import CoredDensity2 return CoredDensity2() elif lens_type == 'CORED_DENSITY_EXP': from lenstronomy.LensModel.Profiles.cored_density_exp import CoredDensityExp return CoredDensityExp() elif lens_type == 'CORED_DENSITY_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY') elif lens_type == 'CORED_DENSITY_2_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY_2') elif lens_type == 'CORED_DENSITY_EXP_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY_EXP') elif lens_type == 'NumericalAlpha': from lenstronomy.LensModel.Profiles.numerical_deflections import NumericalAlpha return NumericalAlpha(custom_class) elif lens_type == 'MULTIPOLE': from lenstronomy.LensModel.Profiles.multipole import Multipole return Multipole() elif lens_type == 'CSE': from lenstronomy.LensModel.Profiles.cored_steep_ellipsoid import CSE return CSE() elif lens_type == 'ElliSLICE': from lenstronomy.LensModel.Profiles.elliptical_density_slice import ElliSLICE return ElliSLICE() elif lens_type == 'ULDM': from lenstronomy.LensModel.Profiles.uldm import Uldm return Uldm() elif lens_type == 'CORED_DENSITY_ULDM_MST': from lenstronomy.LensModel.Profiles.cored_density_mst import CoredDensityMST return CoredDensityMST(profile_type='CORED_DENSITY_ULDM') else: raise ValueError( '%s is not a valid lens model. Supported are: %s.' % (lens_type, _SUPPORTED_MODELS))
def setup(self): self.cn = CNFW() self.n = NFW()
class Testcnfw(object): """ tests the Gaussian methods """ def setup(self): self.cn = CNFW() self.n = NFW() def test_pot(self): pot1 = self.cn.function(2, 0, 1, 1, 0.5) pot2 = self.n.function(2, 0, 1, 1) npt.assert_almost_equal(pot1, pot2) def _kappa_integrand(self, x, y, Rs, m0, r_core): return 2 * np.pi * x * self.cn.density_2d(x, y, Rs, m0, r_core) def test_derivatives(self): Rs = 10. rho0 = 1. r_core = 7. R = np.linspace(0.1 * Rs, 4 * Rs, 1000) alpha = self.cn.cnfwAlpha(R, Rs, rho0, r_core, R, 0)[0] alpha_theory = self.cn.mass_2d(R, Rs, rho0, r_core) / np.pi / R theta_Rs = self.cn._rho2alpha(rho0, Rs, r_core) alpha_derivatives = self.cn.derivatives(R, 0, Rs, theta_Rs, r_core)[0] npt.assert_almost_equal(alpha / alpha_theory, 1) npt.assert_almost_equal(alpha / alpha_derivatives, 1) def test_mproj(self): Rs = 10. r_core = 0.7 * Rs Rmax = np.linspace(0.6 * Rs, 1.1 * Rs, 1000) dr = Rmax[1] - Rmax[0] m0 = 1 m2d = self.cn.mass_2d(Rmax, Rs, m0, r_core) integrand = np.gradient(m2d, dr) kappa_integrand = self._kappa_integrand(Rmax, 0, Rs, m0, r_core) mean_diff = np.absolute(kappa_integrand - integrand) * len(Rmax)**-1 npt.assert_almost_equal(mean_diff, 0, decimal=3) def test_GF(self): x_array = np.array([0.5, 0.8, 1.2]) b = 0.7 Garray = self.cn._G(x_array, b) Farray = self.cn._F(x_array, b) for i in range(0, len(x_array)): npt.assert_almost_equal(Farray[i], self.cn._F(x_array[i], b)) npt.assert_almost_equal(Garray[i], self.cn._G(x_array[i], b)) def test_gamma(self): Rs = 10. rho0 = 1. r_core = 0.7 * Rs R = np.array([0.5 * Rs, 0.8 * Rs, 1.1 * Rs]) g1_array, g2_array = self.cn.cnfwGamma(R, Rs, rho0, r_core, R, 0.6 * Rs) for i in range(0, len(R)): g1, g2 = self.cn.cnfwGamma(R[i], Rs, rho0, r_core, R[i], 0.6 * Rs) npt.assert_almost_equal(g1_array[i], g1) npt.assert_almost_equal(g2_array[i], g2) def test_rho_angle_transform(self): Rs = float(10) rho0 = float(1) r_core = float(7) theta_Rs = self.cn._rho2alpha(rho0, Rs, r_core) theta_rs_2 = self.cn.cnfwAlpha(Rs, Rs, rho0, r_core, Rs, 0)[0] npt.assert_almost_equal(theta_Rs * theta_rs_2**-1, 1) rho0_2 = self.cn._alpha2rho0(theta_Rs, Rs, r_core) npt.assert_almost_equal(rho0, rho0_2)
class Testcnfw(object): """ tests the Gaussian methods """ def setup(self): self.cn = CNFW() self.n = NFW() def test_pot(self): # this test requires that the CNFW profile with a very small core results in the potential of the NFW profile pot1 = self.cn.function(x=2, y=0, Rs=1, alpha_Rs=1, r_core=0.001) pot2 = self.n.function(x=2, y=0, Rs=1, alpha_Rs=1) npt.assert_almost_equal(pot1 / pot2, 1, decimal=3) def _kappa_integrand(self, x, y, Rs, m0, r_core): return 2 * np.pi * x * self.cn.density_2d(x, y, Rs, m0, r_core) def test_derivatives(self): Rs = 10. rho0 = 1. r_core = 7. R = np.linspace(0.1 * Rs, 4 * Rs, 1000) alpha_Rs = self.cn._rho2alpha(rho0, Rs, r_core) alpha = self.cn.alpha_r(R, Rs, rho0, r_core) alpha_theory = self.cn.mass_2d(R, Rs, rho0, r_core) / np.pi / R alpha_derivatives = self.cn.derivatives(R, 0, Rs, alpha_Rs, r_core)[0] npt.assert_almost_equal(alpha_derivatives / alpha_theory, 1) npt.assert_almost_equal(alpha / alpha_theory, 1) npt.assert_almost_equal(alpha / alpha_derivatives, 1) def test_mass_3d(self): Rs = 10. rho0 = 1. r_core = 7. R = np.linspace(0.1 * Rs, 4 * Rs, 1000) alpha_Rs = self.cn._rho2alpha(rho0, Rs, r_core) m3d = self.cn.mass_3d(R, Rs, rho0, r_core) m3d_lens = self.cn.mass_3d_lens(R, Rs, alpha_Rs, r_core) npt.assert_almost_equal(m3d, m3d_lens, decimal=8) def test_mproj(self): Rs = 10. r_core = 0.7 * Rs Rmax = np.linspace(0.6 * Rs, 1.1 * Rs, 1000) dr = Rmax[1] - Rmax[0] m0 = 1 m2d = self.cn.mass_2d(Rmax, Rs, m0, r_core) integrand = np.gradient(m2d, dr) kappa_integrand = self._kappa_integrand(Rmax, 0, Rs, m0, r_core) mean_diff = np.absolute(kappa_integrand - integrand) * len(Rmax)**-1 npt.assert_almost_equal(mean_diff, 0, decimal=3) def test_GF(self): x_array = np.array([0.5, 0.8, 1.2]) b = 0.7 Garray = self.cn._G(x_array, b) Farray = self.cn._F(x_array, b) for i in range(0, len(x_array)): npt.assert_almost_equal(Farray[i], self.cn._F(x_array[i], b)) npt.assert_almost_equal(Garray[i], self.cn._G(x_array[i], b)) def test_gamma(self): Rs = 10. rho0 = 1. r_core = 0.7 * Rs R = np.array([0.5 * Rs, 0.8 * Rs, 1.1 * Rs]) g1_array, g2_array = self.cn.cnfwGamma(R, Rs, rho0, r_core, R, 0.6 * Rs) for i in range(0, len(R)): g1, g2 = self.cn.cnfwGamma(R[i], Rs, rho0, r_core, R[i], 0.6 * Rs) npt.assert_almost_equal(g1_array[i], g1) npt.assert_almost_equal(g2_array[i], g2)