def __init__(self, mass, x, y, r3d, mdef, z, sub_flag, lens_cosmo_instance, args, unique_tag): """ See documentation in base class (Halos/halo_base.py) """ self._prof = SPLCORE() self._lens_cosmo = lens_cosmo_instance super(PowerLawSubhalo, self).__init__(mass, x, y, r3d, mdef, z, sub_flag, lens_cosmo_instance, args, unique_tag)
def setup(self): self.gnfw = GNFW() self.splcore = SPLCORE() self.kwargs_lens = { 'alpha_Rs': 2.1, 'Rs': 1.5, 'gamma_inner': 1.0, 'gamma_outer': 3.0, 'center_x': 0.04, 'center_y': -1.0 }
class PowerLawSubhalo(Halo): """ The base class for a halo modeled as a power law profile """ def __init__(self, mass, x, y, r3d, mdef, z, sub_flag, lens_cosmo_instance, args, unique_tag): """ See documentation in base class (Halos/halo_base.py) """ self._prof = SPLCORE() self._lens_cosmo = lens_cosmo_instance super(PowerLawSubhalo, self).__init__(mass, x, y, r3d, mdef, z, sub_flag, lens_cosmo_instance, args, unique_tag) @property def params_physical(self): """ See documentation in base class (Halos/halo_base.py) """ if not hasattr(self, '_params_physical'): (concentration, gamma, x_core_halo) = self.profile_args rhos, rs, _ = self._lens_cosmo.NFW_params_physical( self.mass, concentration, self.z) kpc_per_arcsec = self._lens_cosmo.cosmo.kpc_proper_per_asec(self.z) if 'x_match' in self._args.keys(): x_match = self._args['x_match'] else: # r_vmax = 2.16 * rs x_match = 2.16 r_match_arcsec = x_match * rs / kpc_per_arcsec fx = np.log(1 + x_match) - x_match / (1 + x_match) m = 4 * np.pi * rs**3 * rhos * fx r_core_arcsec = x_core_halo * r_match_arcsec / x_match sigma_crit_mpc = self._lens_cosmo.get_sigma_crit_lensing( self.z, self._lens_cosmo.z_source) sigma_crit_arcsec = sigma_crit_mpc * (0.001 * kpc_per_arcsec)**2 rho0 = m / self._prof.mass_3d(r_match_arcsec, sigma_crit_arcsec, r_core_arcsec, gamma) # units 1 / arcsec rho0 *= sigma_crit_arcsec * kpc_per_arcsec**-3 self._params_physical = {'rho0': rho0, 'r_core': x_core_halo * rs} return self._params_physical @property def lenstronomy_params(self): """ See documentation in base class (Halos/halo_base.py) """ if not hasattr(self, '_lenstronomy_args'): (concentration, gamma, x_core_halo) = self.profile_args rhos, rs, _ = self._lens_cosmo.NFW_params_physical( self.mass, concentration, self.z) kpc_per_arcsec = self._lens_cosmo.cosmo.kpc_proper_per_asec(self.z) if 'x_match' in self._args.keys(): x_match = self._args['x_match'] else: # r_vmax = 2.16 * rs x_match = 2.16 r_match_arcsec = x_match * rs / kpc_per_arcsec fx = np.log(1 + x_match) - x_match / (1 + x_match) m = 4 * np.pi * rs**3 * rhos * fx r_core_arcsec = x_core_halo * r_match_arcsec / x_match sigma_crit_mpc = self._lens_cosmo.get_sigma_crit_lensing( self.z, self._lens_cosmo.z_source) sigma_crit_arcsec = sigma_crit_mpc * (0.001 * kpc_per_arcsec)**2 rho0 = m / self._prof.mass_3d(r_match_arcsec, sigma_crit_arcsec, r_core_arcsec, gamma) sigma0 = rho0 * r_core_arcsec self._lenstronomy_args = [{ 'sigma0': sigma0, 'gamma': gamma, 'center_x': self.x, 'center_y': self.y, 'r_core': r_core_arcsec }] return self._lenstronomy_args, None @property def lenstronomy_ID(self): """ See documentation in base class (Halos/halo_base.py) """ return ['SPL_CORE'] @property def profile_args(self): """ See documentation in base class (Halos/halo_base.py) """ if not hasattr(self, '_profile_args'): if self._args['evaluate_mc_at_zlens']: z_eval = self.z else: z_eval = self.z_infall concentration = self._lens_cosmo.NFW_concentration( self.mass, z_eval, self._args['mc_model'], self._args['mc_mdef'], self._args['log_mc'], self._args['c_scatter'], self._args['c_scatter_dex'], self._args['kwargs_suppression'], self._args['suppression_model']) gamma = self._args['log_slope_halo'] x_core_halo = self._args['x_core_halo'] self._profile_args = (concentration, gamma, x_core_halo) return self._profile_args
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.profile = SPLCORE()
class TestSPLCORE(object): def setup(self): self.profile = SPLCORE() def test_no_potential(self): npt.assert_raises(Exception, self.profile.function, 0., 0., 0., 0., 0.) def test_origin(self): x = 0. y = 0. sigma0 = 1. r_core = 0.1 gamma = 2.4 alpha_x, alpha_y = self.profile.derivatives(x, y, sigma0, r_core, gamma) npt.assert_almost_equal(alpha_x, 0.) npt.assert_almost_equal(alpha_y, 0.) fxx, fyy, fxy = self.profile.hessian(x, y, sigma0, r_core, gamma) kappa = self.profile.density_2d(x, y, sigma0 / r_core, r_core, gamma) npt.assert_almost_equal(fxx, kappa) npt.assert_almost_equal(fyy, kappa) npt.assert_almost_equal(fxy, 0.) r = 0.01 xmin = 0.001 rmin = self.profile._safe_r_division(r, 1., xmin) npt.assert_equal(rmin, r) r = 1e-9 rmin = self.profile._safe_r_division(r, 1., xmin) npt.assert_equal(rmin, xmin) xmin = 1e-2 r = np.logspace(-3, 0, 100) inds = np.where(r < xmin) rmin = self.profile._safe_r_division(r, 1., xmin) npt.assert_almost_equal(rmin[inds], xmin) def test_g_function(self): gamma = 2.5 rc = 0.01 rho0 = 1. R = 5. args = (rho0, rc, gamma) mass_numerical = quad(self._mass_integrand3d, 0, R, args=args)[0] mass_analytic = self.profile.mass_3d(R, rho0, rc, gamma) npt.assert_almost_equal(mass_analytic, mass_numerical) gamma = 2. args = (rho0, rc, gamma) mass_numerical = quad(self._mass_integrand3d, 0, R, args=args)[0] mass_analytic = self.profile.mass_3d(R, rho0, rc, gamma) npt.assert_almost_equal(mass_analytic, mass_numerical) gamma = 3. args = (rho0, rc, gamma) mass_numerical = quad(self._mass_integrand3d, 0, R, args=args)[0] mass_analytic = self.profile.mass_3d(R, rho0, rc, gamma) npt.assert_almost_equal(mass_analytic, mass_numerical) gamma = 1.4 args = (rho0, rc, gamma) mass_numerical = quad(self._mass_integrand3d, 0, R, args=args)[0] mass_analytic = self.profile.mass_3d(R, rho0, rc, gamma) npt.assert_almost_equal(mass_analytic, mass_numerical) sigma0 = rho0 * rc mass_analytic_from_sigm0 = self.profile.mass_3d_lens( R, sigma0, rc, gamma) npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical) def test_f_function(self): gamma = 2.5 rc = 0.01 rho0 = 1. R = 5. args = (rho0, rc, gamma) mass_numerical = quad(self._mass_integrand2d, 0, R, args=args)[0] mass_analytic = self.profile.mass_2d(R, rho0, rc, gamma) npt.assert_almost_equal(mass_analytic, mass_numerical) sigma0 = rho0 * rc mass_analytic_from_sigm0 = self.profile.mass_2d_lens( R, sigma0, rc, gamma) npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical) gamma = 2. args = (rho0, rc, gamma) mass_numerical = quad(self._mass_integrand2d, 0, R, args=args)[0] mass_analytic = self.profile.mass_2d(R, rho0, rc, gamma) npt.assert_almost_equal(mass_analytic, mass_numerical) sigma0 = rho0 * rc mass_analytic_from_sigm0 = self.profile.mass_2d_lens( R, sigma0, rc, gamma) npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical) gamma = 3. args = (rho0, rc, gamma) mass_numerical = quad(self._mass_integrand2d, 0, R, args=args)[0] mass_analytic = self.profile.mass_2d(R, rho0, rc, gamma) npt.assert_almost_equal(mass_analytic, mass_numerical) sigma0 = rho0 * rc mass_analytic_from_sigm0 = self.profile.mass_2d_lens( R, sigma0, rc, gamma) npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical) gamma = 1.4 args = (rho0, rc, gamma) mass_numerical = quad(self._mass_integrand2d, 0, R, args=args)[0] mass_analytic = self.profile.mass_2d(R, rho0, rc, gamma) npt.assert_almost_equal(mass_analytic, mass_numerical) sigma0 = rho0 * rc mass_analytic_from_sigm0 = self.profile.mass_2d_lens( R, sigma0, rc, gamma) npt.assert_almost_equal(mass_analytic_from_sigm0, mass_numerical) def _mass_integrand3d(self, r, rho0, rc, gamma): return 4 * np.pi * r**2 * rho0 * rc**gamma / (rc**2 + r**2)**(gamma / 2) def _mass_integrand2d(self, r, rho0, rc, gamma): return 2 * np.pi * r * self.profile.density_2d(r, 0, rho0, rc, gamma)
class TestGNFW(object): def setup(self): self.gnfw = GNFW() self.splcore = SPLCORE() self.kwargs_lens = { 'alpha_Rs': 2.1, 'Rs': 1.5, 'gamma_inner': 1.0, 'gamma_outer': 3.0, 'center_x': 0.04, 'center_y': -1.0 } def test_alphaRs(self): alpha_rs = self.gnfw.derivatives(self.kwargs_lens['Rs'], 0.0, self.kwargs_lens['Rs'], self.kwargs_lens['alpha_Rs'], self.kwargs_lens['gamma_inner'], self.kwargs_lens['gamma_outer'])[0] npt.assert_almost_equal(alpha_rs, self.kwargs_lens['alpha_Rs'], 8) def test_alphaRs_rho0_conversion(self): rho0 = self.gnfw.alpha2rho0(self.kwargs_lens['alpha_Rs'], self.kwargs_lens['Rs'], self.kwargs_lens['gamma_inner'], self.kwargs_lens['gamma_outer']) alpha_Rs = self.gnfw.rho02alpha(rho0, self.kwargs_lens['Rs'], self.kwargs_lens['gamma_inner'], self.kwargs_lens['gamma_outer']) npt.assert_almost_equal(alpha_Rs, self.kwargs_lens['alpha_Rs'], 5) def test_lensing_quantities(self): lensmodel = LensModel(['GNFW']) f_x, f_y = self.gnfw.derivatives(1.0, 1.5, **self.kwargs_lens) f_x_, f_y_ = lensmodel.alpha(1.0, 1.5, [self.kwargs_lens]) npt.assert_almost_equal(f_x, f_x_, 5) npt.assert_almost_equal(f_y, f_y_, 5) f_xx, f_xy, f_yx, f_yy = self.gnfw.hessian(1.0, 1.5, **self.kwargs_lens) f_xx_, f_xy_, f_yx_, f_yy_ = lensmodel.hessian(1.0, 1.5, [self.kwargs_lens]) npt.assert_almost_equal(f_xx, f_xx_, 5) npt.assert_almost_equal(f_yy, f_yy_, 5) npt.assert_almost_equal(f_xy, f_xy_, 5) def test_mass2d(self): rho0 = self.gnfw.alpha2rho0(self.kwargs_lens['alpha_Rs'], self.kwargs_lens['Rs'], self.kwargs_lens['gamma_inner'], self.kwargs_lens['gamma_outer']) m2d = self.gnfw.mass_2d(10.0, self.kwargs_lens['Rs'], rho0, self.kwargs_lens['gamma_inner'], self.kwargs_lens['gamma_outer']) integrand = lambda x: 2 * 3.14159265 * x * self.gnfw.density_2d( x, 0.0, self.kwargs_lens['Rs'], rho0, self.kwargs_lens[ 'gamma_inner'], self.kwargs_lens['gamma_outer']) m2d_num = quad(integrand, 0, 10.)[0] npt.assert_almost_equal(m2d_num / m2d, 1.0, 5) def test_spl_core_match(self): rs = 1.5 kwargs_spl = {'sigma0': 1e13, 'gamma': 3.0, 'r_core': 0.00000001} alpha_rs = self.splcore.derivatives(rs, 0.0, **kwargs_spl)[0] kwargs_gnfw = { 'alpha_Rs': alpha_rs, 'Rs': rs, 'gamma_inner': 2.99999, 'gamma_outer': 3.00001 } m3d_gnfw = self.gnfw.mass_3d_lens(5 * rs, **kwargs_gnfw) m3d_splcore = self.splcore.mass_3d_lens(5 * rs, **kwargs_spl) npt.assert_almost_equal(m3d_gnfw / m3d_splcore, 0.935, 3)