class TestEPLvsPEMD(object): """ Test EPL model vs PEMD with FASTELL This tests get only executed if fastell is installed """ def setup(self): try: import fastell4py self._fastell4py_bool = True except: print("Warning: fastell4py not available, tests will be trivially fulfilled without giving the right answer!") self._fastell4py_bool = False from lenstronomy.LensModel.Profiles.epl import EPL self.epl = EPL() from lenstronomy.LensModel.Profiles.pemd import PEMD self.pemd = PEMD(suppress_fastell=True) def test_epl_pemd_convention(self): """ tests convention of EPL and PEMD model on the deflection angle basis """ if self._fastell4py_bool is False: return 0 x, y = util.make_grid(numPix=10, deltapix=0.2) theta_E_list = [0.5, 1, 2] gamma_list = [1.8, 2., 2.2] e1_list = [-0.2, 0., 0.2] e2_list = [-0.2, 0., 0.2] for gamma in gamma_list: for e1 in e1_list: for e2 in e2_list: for theta_E in theta_E_list: kwargs = {'theta_E': theta_E, 'gamma': gamma, 'e1': e1, 'e2': e2, 'center_x': 0, 'center_y': 0} f_x, f_y = self.epl.derivatives(x, y, **kwargs) f_x_pemd, f_y_pemd = self.pemd.derivatives(x, y, **kwargs) npt.assert_almost_equal(f_x, f_x_pemd, decimal=4) npt.assert_almost_equal(f_y, f_y_pemd, decimal=4)
class TestSPEMD(object): """ tests the Gaussian methods """ def setup(self): from lenstronomy.LensModel.Profiles.pemd import PEMD from lenstronomy.LensModel.Profiles.spep import SPEP self.PEMD = PEMD(suppress_fastell=True) self.SPEP = SPEP() def test_function(self): phi_E = 1. gamma = 1.9 q = 0.9 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1.]) y = np.array([2]) a = np.zeros_like(x) values = self.PEMD.function(x, y, phi_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(values[0], 2.1571106351401803, decimal=5) else: assert values == 0 a += values x = np.array(1.) y = np.array(2.) a = np.zeros_like(x) values = self.PEMD.function(x, y, phi_E, gamma, e1, e2) print(x, values) a += values if fastell4py_bool: npt.assert_almost_equal(values, 2.1571106351401803, decimal=5) else: assert values == 0 assert type(x) == type(values) x = np.array([2, 3, 4]) y = np.array([1, 1, 1]) values = self.PEMD.function(x, y, phi_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(values[0], 2.180188584782964, decimal=7) npt.assert_almost_equal(values[1], 3.2097137160951874, decimal=7) npt.assert_almost_equal(values[2], 4.3109976673748, decimal=7) else: npt.assert_almost_equal(values[0], 0, decimal=7) npt.assert_almost_equal(values[1], 0, decimal=7) npt.assert_almost_equal(values[2], 0, decimal=7) def test_derivatives(self): x = np.array([1]) y = np.array([2]) phi_E = 1. gamma = 1.9 q = 0.9 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.PEMD.derivatives(x, y, phi_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(f_x[0], 0.46664118422711387, decimal=7) npt.assert_almost_equal(f_y[0], 0.9530892465981603, decimal=7) else: npt.assert_almost_equal(f_x[0], 0, decimal=7) npt.assert_almost_equal(f_y[0], 0, decimal=7) x = np.array([1., 3, 4]) y = np.array([2., 1, 1]) a = np.zeros_like(x) values = self.PEMD.derivatives(x, y, phi_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(values[0][0], 0.46664118422711387, decimal=7) npt.assert_almost_equal(values[1][0], 0.9530892465981603, decimal=7) npt.assert_almost_equal(values[0][1], 1.0722265330847958, decimal=7) npt.assert_almost_equal(values[1][1], 0.3140067377020791, decimal=7) else: npt.assert_almost_equal(values[0][0], 0, decimal=7) npt.assert_almost_equal(values[1][0], 0, decimal=7) npt.assert_almost_equal(values[0][1], 0, decimal=7) npt.assert_almost_equal(values[1][1], 0, decimal=7) a += values[0] x = 1. y = 2. phi_E = 1. gamma = 1.9 q = 0.9 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.PEMD.derivatives(x, y, phi_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(f_x, 0.46664118422711387, decimal=7) npt.assert_almost_equal(f_y, 0.9530892465981603, decimal=7) else: npt.assert_almost_equal(f_x, 0, decimal=7) npt.assert_almost_equal(f_y, 0, decimal=7) x = 0. y = 0. f_x, f_y = self.PEMD.derivatives(x, y, phi_E, gamma, e1, e2) assert f_x == 0. assert f_y == 0. def test_hessian(self): x = np.array([1]) y = np.array([2]) phi_E = 1. gamma = 1.9 q = 0.9 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_xx, f_xy, f_yx, f_yy = self.PEMD.hessian(x, y, phi_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(f_xx, 0.4179041, decimal=7) npt.assert_almost_equal(f_yy, 0.1404714, decimal=7) npt.assert_almost_equal(f_xy, -0.1856134, decimal=7) else: npt.assert_almost_equal(f_xx, 0, decimal=7) npt.assert_almost_equal(f_yy, 0, decimal=7) npt.assert_almost_equal(f_xy, 0, decimal=7) npt.assert_almost_equal(f_xy, f_yx, decimal=8) x = 1. y = 2. phi_E = 1. gamma = 1.9 q = 0.9 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) a = np.zeros_like(x) f_xx, f_xy, f_yx, f_yy = self.PEMD.hessian(x, y, phi_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(f_xx, 0.41790408341142493, decimal=7) npt.assert_almost_equal(f_yy, 0.14047143086334482, decimal=7) npt.assert_almost_equal(f_xy, -0.1856133848300859, decimal=7) else: npt.assert_almost_equal(f_xx, 0, decimal=7) npt.assert_almost_equal(f_yy, 0, decimal=7) npt.assert_almost_equal(f_xy, 0, decimal=7) a += f_xx x = np.array([1, 3, 4]) y = np.array([2, 1, 1]) values = self.PEMD.hessian(x, y, phi_E, gamma, e1, e2) print(values, 'values') if fastell4py_bool: npt.assert_almost_equal(values[0][0], 0.41789957732890953, decimal=5) npt.assert_almost_equal(values[3][0], 0.14047593655054141, decimal=5) npt.assert_almost_equal(values[1][0], -0.18560737698052343, decimal=5) npt.assert_almost_equal(values[0][1], 0.068359818958208918, decimal=5) npt.assert_almost_equal(values[3][1], 0.32494089371516482, decimal=5) npt.assert_almost_equal(values[1][1], -0.097845438684594374, decimal=5) else: npt.assert_almost_equal(values[0][0], 0, decimal=7) def test_spep_spemd(self): x = np.array([1]) y = np.array([0]) phi_E = 1. gamma = 2. q = 1. phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.PEMD.derivatives(x, y, phi_E, gamma, e1, e2) f_x_spep, f_y_spep = self.SPEP.derivatives(x, y, phi_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(f_x[0], f_x_spep[0], decimal=2) else: pass theta_E = 2. gamma = 2. q = 1. phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.PEMD.derivatives(x, y, theta_E, gamma, e1, e2) f_x_spep, f_y_spep = self.SPEP.derivatives(x, y, theta_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(f_x[0], f_x_spep[0], decimal=2) else: pass theta_E = 2. gamma = 1.7 q = 1. phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.PEMD.derivatives(x, y, theta_E, gamma, e1, e2) f_x_spep, f_y_spep = self.SPEP.derivatives(x, y, theta_E, gamma, e1, e2) if fastell4py_bool: npt.assert_almost_equal(f_x[0], f_x_spep[0], decimal=4) def test_bounds(self): from lenstronomy.LensModel.Profiles.spemd import SPEMD profile = SPEMD(suppress_fastell=True) compute_bool = profile._parameter_constraints(q_fastell=-1, gam=-1, s2=-1, q=-1) assert compute_bool is False def test_is_not_empty(self): func = self.PEMD.spemd_smooth.is_not_empty assert func(0.1, 0.2) assert func([0.1], [0.2]) assert func((0.1, 0.3), (0.2, 0.4)) assert func(np.array([0.1]), np.array([0.2])) assert not func([], []) assert not func(np.array([]), np.array([])) def test_density_lens(self): r = 1 kwargs = {'theta_E': 1, 'gamma': 2, 'e1': 0, 'e2': 0} rho = self.PEMD.density_lens(r, **kwargs) rho_spep = self.SPEP.density_lens(r, **kwargs) npt.assert_almost_equal(rho, rho_spep, decimal=7)
class SIE(LensProfileBase): """ class for singular isothermal ellipsoid (SIS with ellipticity) """ param_names = ['theta_E', 'e1', 'e2', 'center_x', 'center_y'] lower_limit_default = { 'theta_E': 0, 'e1': -0.5, 'e2': -0.5, 'center_x': -100, 'center_y': -100 } upper_limit_default = { 'theta_E': 100, 'e1': 0.5, 'e2': 0.5, 'center_x': 100, 'center_y': 100 } def __init__(self, NIE=True, suppress_fastell=False): """ :param NIE: bool, if True, is using the NIE analytic model. Otherwise it uses PEMD with gamma=2 from fastell4py :param suppress_fastell: bool, if True, does not raise if fastell4py is not installed """ self._nie = NIE if NIE: from lenstronomy.LensModel.Profiles.nie import NIE self.profile = NIE() else: from lenstronomy.LensModel.Profiles.pemd import PEMD self.profile = PEMD(suppress_fastell=suppress_fastell) self._s_scale = 0.0000000001 self._gamma = 2 super(SIE, self).__init__() def function(self, x, y, theta_E, e1, e2, center_x=0, center_y=0): """ :param x: :param y: :param theta_E: :param q: :param phi_G: :param center_x: :param center_y: :return: """ if self._nie: return self.profile.function(x, y, theta_E, e1, e2, self._s_scale, center_x, center_y) else: return self.profile.function(x, y, theta_E, self._gamma, e1, e2, center_x, center_y) def derivatives(self, x, y, theta_E, e1, e2, center_x=0, center_y=0): """ :param x: :param y: :param theta_E: :param q: :param phi_G: :param center_x: :param center_y: :return: """ if self._nie: return self.profile.derivatives(x, y, theta_E, e1, e2, self._s_scale, center_x, center_y) else: return self.profile.derivatives(x, y, theta_E, self._gamma, e1, e2, center_x, center_y) def hessian(self, x, y, theta_E, e1, e2, center_x=0, center_y=0): """ :param x: :param y: :param theta_E: :param q: :param phi_G: :param center_x: :param center_y: :return: """ if self._nie: return self.profile.hessian(x, y, theta_E, e1, e2, self._s_scale, center_x, center_y) else: return self.profile.hessian(x, y, theta_E, self._gamma, e1, e2, center_x, center_y) @staticmethod def theta2rho(theta_E): """ converts projected density parameter (in units of deflection) into 3d density parameter :param theta_E: :return: """ fac1 = np.pi * 2 rho0 = theta_E / fac1 return rho0 @staticmethod def mass_3d(r, rho0, e1=0, e2=0): """ mass enclosed a 3d sphere or radius r :param r: radius in angular units :param rho0: density at angle=1 :return: mass in angular units """ mass_3d = 4 * np.pi * rho0 * r return mass_3d def mass_3d_lens(self, r, theta_E, e1=0, e2=0): """ mass enclosed a 3d sphere or radius r given a lens parameterization with angular units :param r: radius in angular units :param theta_E: Einstein radius :return: mass in angular units """ rho0 = self.theta2rho(theta_E) return self.mass_3d(r, rho0) def mass_2d(self, r, rho0, e1=0, e2=0): """ mass enclosed projected 2d sphere of radius r :param r: :param rho0: :param a: :param s: :return: """ alpha = np.pi * np.pi * 2 * rho0 mass_2d = alpha * r return mass_2d def mass_2d_lens(self, r, theta_E, e1=0, e2=0): """ :param r: :param theta_E: :return: """ rho0 = self.theta2rho(theta_E) return self.mass_2d(r, rho0) def grav_pot(self, x, y, rho0, e1=0, e2=0, center_x=0, center_y=0): """ gravitational potential (modulo 4 pi G and rho0 in appropriate units) :param x: :param y: :param rho0: :param a: :param s: :param center_x: :param center_y: :return: """ x_ = x - center_x y_ = y - center_y r = np.sqrt(x_**2 + y_**2) mass_3d = self.mass_3d(r, rho0) pot = mass_3d / r return pot def density_lens(self, r, theta_E, 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. :param r: radius in angles :param theta_E: Einstein radius :param e1: eccentricity component :param e2: eccentricity component :return: density """ rho0 = self.theta2rho(theta_E) return self.density(r, rho0) @staticmethod def density(r, rho0, e1=0, e2=0): """ computes the density :param r: radius in angles :param rho0: density at angle=1 :return: density at r """ rho = rho0 / r**2 return rho @staticmethod def density_2d(x, y, rho0, e1=0, e2=0, center_x=0, center_y=0): """ projected density :param x: :param y: :param rho0: :param center_x: :param center_y: :return: """ x_ = x - center_x y_ = y - center_y r = np.sqrt(x_**2 + y_**2) sigma = np.pi * rho0 / r return sigma
class TestSIE(object): """ tests the Gaussian methods """ def setup(self): from lenstronomy.LensModel.Profiles.sie import SIE from lenstronomy.LensModel.Profiles.pemd import PEMD from lenstronomy.LensModel.Profiles.nie import NIE self.sie = SIE(NIE=False, suppress_fastell=True) self.sie_nie = SIE(NIE=True) self.spemd = PEMD(suppress_fastell=True) self.nie = NIE() def test_function(self): x = np.array([1]) y = np.array([2]) theta_E = 1. q = 0.9 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.sie.function(x, y, theta_E, e1, e2) gamma = 2 values_spemd = self.spemd.function(x, y, theta_E, gamma, e1, e2) assert values == values_spemd values_nie = self.sie_nie.function(x, y, theta_E, e1, e2) s_scale = 0.0000001 values_spemd = self.nie.function(x, y, theta_E, e1, e2, s_scale) npt.assert_almost_equal(values_nie, values_spemd, decimal=6) def test_derivatives(self): x = np.array([1]) y = np.array([2]) theta_E = 1. q = 0.7 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.sie.derivatives(x, y, theta_E, e1, e2) gamma = 2 values_spemd = self.spemd.derivatives(x, y, theta_E, gamma, e1, e2) assert values == values_spemd values = self.sie_nie.derivatives(x, y, theta_E, e1, e2) s_scale = 0.0000001 values_spemd = self.nie.derivatives(x, y, theta_E, e1, e2, s_scale) npt.assert_almost_equal(values, values_spemd, decimal=6) def test_hessian(self): x = np.array([1]) y = np.array([2]) theta_E = 1. q = 0.7 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.sie.hessian(x, y, theta_E, e1, e2) gamma = 2 values_spemd = self.spemd.hessian(x, y, theta_E, gamma, e1, e2) assert values[0] == values_spemd[0] values = self.sie_nie.hessian(x, y, theta_E, e1, e2) s_scale = 0.0000001 values_spemd = self.nie.hessian(x, y, theta_E, e1, e2, s_scale) npt.assert_almost_equal(values, values_spemd, decimal=5)