def test_function(self): """ :return: """ lens = NIE_lens() light = NIE_light() x = np.linspace(0.1, 10, 10) e1, e2 = 0.1, 0 s = 0.2 kwargs_light = {'amp': 1., 'e1': e1, 'e2': e2, 's_scale': s} kwargs_lens = {'theta_E': 1., 'e1': e1, 'e2': e2, 's_scale': s} flux = light.function(x=x, y=1., **kwargs_light) f_xx, f_yy, f_xy = lens.hessian(x=x, y=1., **kwargs_lens) kappa = 1/2. * (f_xx + f_yy) npt.assert_almost_equal(flux/flux[-1], kappa/kappa[-1], decimal=4)
class TestChameleon(object): """ class to test the Moffat profile """ def setup(self): self.chameleon = Chameleon() self.nie = NIE() def test_theta_E_convert(self): w_c, w_t = 2, 1 theta_E_convert, w_c, w_t = self.chameleon._theta_E_convert(theta_E=1, w_c=w_c, w_t=w_t) assert w_c == 1 assert w_t == 2 def test_function(self): """ :return: """ x = np.linspace(0.1, 10, 10) w_c, w_t = 0.5, 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_light = { 'theta_E': 1., 'w_c': .5, 'w_t': 1., 'e1': e1, 'e2': e2 } theta_E_convert, w_c, w_t = self.chameleon._theta_E_convert(theta_E=1, w_c=0.5, w_t=1.) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) kwargs_1 = { 'theta_E': theta_E_convert, 's_scale': s_scale_1, 'e1': e1, 'e2': e2 } kwargs_2 = { 'theta_E': theta_E_convert, 's_scale': s_scale_2, 'e1': e1, 'e2': e2 } f_ = self.chameleon.function(x=x, y=1., **kwargs_light) f_1 = self.nie.function(x=x, y=1., **kwargs_1) f_2 = self.nie.function(x=x, y=1., **kwargs_2) npt.assert_almost_equal(f_, (f_1 - f_2), decimal=5) def test_derivatives(self): """ :return: """ x = np.linspace(0.1, 10, 10) w_c, w_t = 0.5, 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_light = { 'theta_E': 1., 'w_c': .5, 'w_t': 1., 'e1': e1, 'e2': e2 } theta_E_convert, w_c, w_t = self.chameleon._theta_E_convert(theta_E=1, w_c=0.5, w_t=1.) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) kwargs_1 = { 'theta_E': theta_E_convert, 's_scale': s_scale_1, 'e1': e1, 'e2': e2 } kwargs_2 = { 'theta_E': theta_E_convert, 's_scale': s_scale_2, 'e1': e1, 'e2': e2 } f_x, f_y = self.chameleon.derivatives(x=x, y=1., **kwargs_light) f_x_1, f_y_1 = self.nie.derivatives(x=x, y=1., **kwargs_1) f_x_2, f_y_2 = self.nie.derivatives(x=x, y=1., **kwargs_2) npt.assert_almost_equal(f_x, (f_x_1 - f_x_2), decimal=5) npt.assert_almost_equal(f_y, (f_y_1 - f_y_2), decimal=5) f_x, f_y = self.chameleon.derivatives(x=1, y=0., **kwargs_light) npt.assert_almost_equal(f_x, 1, decimal=1) def test_hessian(self): """ :return: """ x = np.linspace(0.1, 10, 10) w_c, w_t = 0.5, 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_light = { 'theta_E': 1., 'w_c': .5, 'w_t': 1., 'e1': e1, 'e2': e2 } theta_E_convert, w_c, w_t = self.chameleon._theta_E_convert(theta_E=1, w_c=0.5, w_t=1.) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) kwargs_1 = { 'theta_E': theta_E_convert, 's_scale': s_scale_1, 'e1': e1, 'e2': e2 } kwargs_2 = { 'theta_E': theta_E_convert, 's_scale': s_scale_2, 'e1': e1, 'e2': e2 } f_xx, f_yy, f_xy = self.chameleon.hessian(x=x, y=1., **kwargs_light) f_xx_1, f_yy_1, f_xy_1 = self.nie.hessian(x=x, y=1., **kwargs_1) f_xx_2, f_yy_2, f_xy_2 = self.nie.hessian(x=x, y=1., **kwargs_2) npt.assert_almost_equal(f_xx, (f_xx_1 - f_xx_2), decimal=5) npt.assert_almost_equal(f_yy, (f_yy_1 - f_yy_2), decimal=5) npt.assert_almost_equal(f_xy, (f_xy_1 - f_xy_2), decimal=5)
class TestSPEMD(object): """ tests the Gaussian methods """ def setup(self): from lenstronomy.LensModel.Profiles.spemd import SPEMD self.SPEMD = SPEMD(suppress_fastell=True) from lenstronomy.LensModel.Profiles.nie import NIE self.NIE = NIE() def test_function(self): phi_E = 1. gamma = 2. q = 0.999 phi_G = 1. s_scale = 0.1 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1., 2]) y = np.array([2, 0]) values = self.SPEMD.function(x, y, phi_E, gamma, e1, e2, s_scale) if fastell4py_bool: values_nie = self.NIE.function(x, y, phi_E, e1, e2, s_scale) delta_f = values[0] - values[1] delta_f_nie = values_nie[0] - values_nie[1] npt.assert_almost_equal(delta_f, delta_f_nie, decimal=5) else: npt.assert_almost_equal(values, 0, decimal=5) def test_derivatives(self): x = np.array([1]) y = np.array([2]) phi_E = 1. gamma = 2. q = 1. phi_G = 1. s_scale = 0.1 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.SPEMD.derivatives(x, y, phi_E, gamma, e1, e2, s_scale) if fastell4py_bool: f_x_nie, f_y_nie = self.NIE.derivatives(x, y, phi_E, e1, e2, s_scale) npt.assert_almost_equal(f_x, f_x_nie, decimal=4) npt.assert_almost_equal(f_y, f_y_nie, decimal=4) else: npt.assert_almost_equal(f_x, 0, decimal=7) npt.assert_almost_equal(f_y, 0, decimal=7) q = 0.7 phi_G = 1. s_scale = 0.001 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.SPEMD.derivatives(x, y, phi_E, gamma, e1, e2, s_scale) if fastell4py_bool: f_x_nie, f_y_nie = self.NIE.derivatives(x, y, phi_E, e1, e2, s_scale) npt.assert_almost_equal(f_x, f_x_nie, decimal=4) npt.assert_almost_equal(f_y, f_y_nie, decimal=4) else: npt.assert_almost_equal(f_x, 0, decimal=7) npt.assert_almost_equal(f_y, 0, decimal=7) def test_hessian(self): x = np.array([1.]) y = np.array([2.]) phi_E = 1. gamma = 2. q = 0.9 phi_G = 1. s_scale = 0.001 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_xx, f_xy, f_yx, f_yy = self.SPEMD.hessian(x, y, phi_E, gamma, e1, e2, s_scale) if fastell4py_bool: f_xx_nie, f_xy_nie, f_yx_nie, f_yy_nie = self.NIE.hessian( x, y, phi_E, e1, e2, s_scale) npt.assert_almost_equal(f_xx, f_xx_nie, decimal=4) npt.assert_almost_equal(f_yy, f_yy_nie, decimal=4) npt.assert_almost_equal(f_xy, f_xy_nie, decimal=4) npt.assert_almost_equal(f_yx, f_yx_nie, decimal=4) 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) def test_bounds(self): compute_bool = self.SPEMD._parameter_constraints(q_fastell=-1, gam=-1, s2=-1, q=-1) assert compute_bool is False def test_is_not_empty(self): func = self.SPEMD.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([]))
class TestNIE(object): """ tests the Gaussian methods """ def setup(self): self.nie = NIE() self.spemd = SPEMD(suppress_fastell=True) self.sis = SIS() def test_function(self): y = np.array([1., 2]) x = np.array([0., 0.]) theta_E = 1. q = 0.9999 s = 0.00001 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.nie.function(x, y, theta_E, e1, e2, s_scale=s) delta_pot = values[1] - values[0] values_spemd = self.sis.function(x, y, theta_E) delta_pot_spemd = values_spemd[1] - values_spemd[0] npt.assert_almost_equal(delta_pot, delta_pot_spemd, decimal=4) if bool_test is True: q = 0.99 s = 0.000001 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.nie.function(x, y, theta_E, e1, e2, s_scale=s) delta_pot = values[1] - values[0] gamma = 2. values_spemd = self.spemd.function(x, y, theta_E, gamma, e1, e2, s_scale=s) delta_pot_spemd = values_spemd[1] - values_spemd[0] npt.assert_almost_equal(delta_pot, delta_pot_spemd, decimal=2) def test_derivatives(self): x = np.array([1]) y = np.array([2]) theta_E = 1. q = 0.99999 phi_G = 0 s = 0.0000001 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.nie.derivatives(x, y, theta_E, e1, e2, s_scale=s) f_x_spemd, f_y_spemd = self.sis.derivatives(x, y, theta_E) npt.assert_almost_equal(f_x, f_x_spemd, decimal=4) npt.assert_almost_equal(f_y, f_y_spemd, decimal=4) if bool_test is True: q = 0.99 s = 0.000001 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.nie.derivatives(x, y, theta_E, e1, e2, s_scale=s) gamma = 2. f_x_spemd, f_y_spemd = self.spemd.derivatives(x, y, theta_E, gamma, e1, e2, s_scale=s) print(f_x/f_x_spemd, 'ratio deflections') print(1+(1-q)/2) npt.assert_almost_equal(f_x, f_x_spemd, decimal=2) npt.assert_almost_equal(f_y, f_y_spemd, decimal=2) def test_hessian(self): x = np.array([1]) y = np.array([2]) theta_E = 1. q = 0.999999 phi_G = 0 s = 0.0000001 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_xx, f_yy, f_xy = self.nie.hessian(x, y, theta_E, e1, e2, s_scale=s) f_xx_spemd, f_yy_spemd, f_xy_spemd = self.sis.hessian(x, y, theta_E) npt.assert_almost_equal(f_xx, f_xx_spemd, decimal=4) npt.assert_almost_equal(f_yy, f_yy_spemd, decimal=4) npt.assert_almost_equal(f_xy, f_xy_spemd, decimal=4) def test_convergence2surface_brightness(self): from lenstronomy.LightModel.Profiles.nie import NIE as NIE_Light nie_light = NIE_Light() kwargs = {'e1': 0.3, 'e2': -0.05, 's_scale': 0.5} x, y = util.make_grid(numPix=10, deltapix=0.1) f_xx, f_yy, f_xy = self.nie.hessian(x, y, theta_E=1, **kwargs) kappa = 1/2. * (f_xx + f_yy) flux = nie_light.function(x, y, amp=1, **kwargs) npt.assert_almost_equal(kappa/np.sum(kappa), flux/np.sum(flux), decimal=5) def test_static(self): x, y = 1., 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_lens = {'theta_E': 1., 's_scale': .1, 'e1': e1, 'e2': e2} f_ = self.nie.function(x, y, **kwargs_lens) self.nie.set_static(**kwargs_lens) f_static = self.nie.function(x, y, **kwargs_lens) npt.assert_almost_equal(f_, f_static, decimal=8) self.nie.set_dynamic() kwargs_lens = {'theta_E': 2., 's_scale': .1, 'e1': e1, 'e2': e2} f_dyn = self.nie.function(x, y, **kwargs_lens) assert f_dyn != f_static
class TestEPLvsNIE(object): """ tests the Gaussian methods """ def setup(self): from lenstronomy.LensModel.Profiles.epl import EPL self.EPL = EPL() from lenstronomy.LensModel.Profiles.nie import NIE self.NIE = NIE() def test_function(self): phi_E = 1. gamma = 2. q = 0.999 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1., 2]) y = np.array([2, 0]) values = self.EPL.function(x, y, phi_E, gamma, e1, e2) values_nie = self.NIE.function(x, y, phi_E, e1, e2, 0.) delta_f = values[0] - values[1] delta_f_nie = values_nie[0] - values_nie[1] npt.assert_almost_equal(delta_f, delta_f_nie, decimal=5) q = 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1., 2]) y = np.array([2, 0]) values = self.EPL.function(x, y, phi_E, gamma, e1, e2) values_nie = self.NIE.function(x, y, phi_E, e1, e2, 0.) delta_f = values[0] - values[1] delta_f_nie = values_nie[0] - values_nie[1] npt.assert_almost_equal(delta_f, delta_f_nie, decimal=5) q = 0.4 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1., 2]) y = np.array([2, 0]) values = self.EPL.function(x, y, phi_E, gamma, e1, e2) values_nie = self.NIE.function(x, y, phi_E, e1, e2, 0.) delta_f = values[0] - values[1] delta_f_nie = values_nie[0] - values_nie[1] npt.assert_almost_equal(delta_f, delta_f_nie, decimal=5) def test_derivatives(self): x = np.array([1]) y = np.array([2]) 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.EPL.derivatives(x, y, phi_E, gamma, e1, e2) f_x_nie, f_y_nie = self.NIE.derivatives(x, y, phi_E, e1, e2, 0.) npt.assert_almost_equal(f_x, f_x_nie, decimal=4) npt.assert_almost_equal(f_y, f_y_nie, decimal=4) q = 0.7 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.EPL.derivatives(x, y, phi_E, gamma, e1, e2) f_x_nie, f_y_nie = self.NIE.derivatives(x, y, phi_E, e1, e2, 0.) npt.assert_almost_equal(f_x, f_x_nie, decimal=4) npt.assert_almost_equal(f_y, f_y_nie, decimal=4) def test_hessian(self): x = np.array([1.]) y = np.array([2.]) phi_E = 1. gamma = 2. 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.EPL.hessian(x, y, phi_E, gamma, e1, e2) f_xx_nie, f_xy_nie, f_yx_nie, f_yy_nie = self.NIE.hessian(x, y, phi_E, e1, e2, 0.) npt.assert_almost_equal(f_xx, f_xx_nie, decimal=4) npt.assert_almost_equal(f_yy, f_yy_nie, decimal=4) npt.assert_almost_equal(f_xy, f_xy_nie, decimal=4) npt.assert_almost_equal(f_xy, f_yx, decimal=8) def test_density_lens(self): r = 1 kwargs = {'theta_E': 1, 'gamma': 2, 'e1': 0, 'e2': 0} rho = self.EPL.density_lens(r, **kwargs) from lenstronomy.LensModel.Profiles.spep import SPEP spep = SPEP() rho_spep = spep.density_lens(r, **kwargs) npt.assert_almost_equal(rho, rho_spep, decimal=7) def test_mass_3d_lens(self): r = 1 kwargs = {'theta_E': 1, 'gamma': 2, 'e1': 0, 'e2': 0} rho = self.EPL.mass_3d_lens(r, **kwargs) from lenstronomy.LensModel.Profiles.spep import SPEP spep = SPEP() rho_spep = spep.mass_3d_lens(r, **kwargs) npt.assert_almost_equal(rho, rho_spep, decimal=7) def test_static(self): x, y = 1., 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_lens = {'theta_E': 1., 'gamma': 1.5, 'e1': e1, 'e2': e2} f_ = self.EPL.function(x, y, **kwargs_lens) self.EPL.set_static(**kwargs_lens) f_static = self.EPL.function(x, y, **kwargs_lens) npt.assert_almost_equal(f_, f_static, decimal=8) self.EPL.set_dynamic() kwargs_lens = {'theta_E': 2., 'gamma': 1.9, 'e1': e1, 'e2': e2} f_dyn = self.EPL.function(x, y, **kwargs_lens) assert f_dyn != f_static def test_regularization(self): phi_E = 1. gamma = 2. q = 1. phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = 0. y = 0. f_x, f_y = self.EPL.derivatives(x, y, phi_E, gamma, e1, e2) npt.assert_almost_equal(f_x, 0.) npt.assert_almost_equal(f_y, 0.) x = 0. y = 0. f_xx, f_xy, f_yx, f_yy = self.EPL.hessian(x, y, phi_E, gamma, e1, e2) assert f_xx > 10 ** 5 assert f_yy > 10 ** 5 #npt.assert_almost_equal(f_xx, 10**10) #npt.assert_almost_equal(f_yy, 10**10) npt.assert_almost_equal(f_xy, 0) npt.assert_almost_equal(f_yx, 0)
class TestNIE(object): """ tests the Gaussian methods """ def setup(self): from lenstronomy.LensModel.Profiles.nie import NIE from lenstronomy.LensModel.Profiles.spemd_smooth import SPEMD_SMOOTH from lenstronomy.LensModel.Profiles.sis import SIS self.nie = NIE() self.spemd = SPEMD_SMOOTH() self.sis = SIS() def test_function(self): y = np.array([1., 2]) x = np.array([0., 0.]) theta_E = 1. q = 0.9999 s = 0.00001 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.nie.function(x, y, theta_E, e1, e2, s_scale=s) delta_pot = values[1] - values[0] values_spemd = self.sis.function(x, y, theta_E) delta_pot_spemd = values_spemd[1] - values_spemd[0] npt.assert_almost_equal(delta_pot, delta_pot_spemd, decimal=4) if bool_test is True: q = 0.99 s = 0.000001 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) values = self.nie.function(x, y, theta_E, e1, e2, s_scale=s) delta_pot = values[1] - values[0] gamma = 2. values_spemd = self.spemd.function(x, y, theta_E, gamma, e1, e2, s_scale=s) delta_pot_spemd = values_spemd[1] - values_spemd[0] npt.assert_almost_equal(delta_pot, delta_pot_spemd, decimal=2) def test_derivatives(self): x = np.array([1]) y = np.array([2]) theta_E = 1. q = 0.99999 phi_G = 0 s = 0.0000001 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.nie.derivatives(x, y, theta_E, e1, e2, s_scale=s) f_x_spemd, f_y_spemd = self.sis.derivatives(x, y, theta_E) npt.assert_almost_equal(f_x, f_x_spemd, decimal=4) npt.assert_almost_equal(f_y, f_y_spemd, decimal=4) if bool_test is True: q = 0.99 s = 0.000001 phi_G = 0 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.nie.derivatives(x, y, theta_E, e1, e2, s_scale=s) gamma = 2. f_x_spemd, f_y_spemd = self.spemd.derivatives(x, y, theta_E, gamma, e1, e2, s_scale=s) print(f_x / f_x_spemd, 'ratio deflections') print(1 + (1 - q) / 2) npt.assert_almost_equal(f_x, f_x_spemd, decimal=2) npt.assert_almost_equal(f_y, f_y_spemd, decimal=2) def test_hessian(self): x = np.array([1]) y = np.array([2]) theta_E = 1. q = 0.999999 phi_G = 0 s = 0.0000001 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_xx, f_yy, f_xy = self.nie.hessian(x, y, theta_E, e1, e2, s_scale=s) f_xx_spemd, f_yy_spemd, f_xy_spemd = self.sis.hessian(x, y, theta_E) npt.assert_almost_equal(f_xx, f_xx_spemd, decimal=4) npt.assert_almost_equal(f_yy, f_yy_spemd, decimal=4) npt.assert_almost_equal(f_xy, f_xy_spemd, decimal=4)
class TestChameleon(object): """ class to test the Moffat profile """ def setup(self): self.chameleon = Chameleon() self.nie = NIE() def test_theta_E_convert(self): w_c, w_t = 2, 1 theta_E_convert, w_c, w_t, s_scale_1, s_scale_2 = self.chameleon.param_convert( alpha_1=1, w_c=w_c, w_t=w_t, e1=0, e2=0) assert w_c == 1 assert w_t == 2 assert theta_E_convert == 0 def test_function(self): """ :return: """ x = np.linspace(0.1, 10, 10) w_c, w_t = 0.5, 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_light = { 'alpha_1': 1., 'w_c': .5, 'w_t': 1., 'e1': e1, 'e2': e2 } theta_E_convert, w_c, w_t, s_scale_1, s_scale_2 = self.chameleon.param_convert( alpha_1=1, w_c=0.5, w_t=1., e1=e1, e2=e2) kwargs_1 = { 'theta_E': theta_E_convert, 's_scale': s_scale_1, 'e1': e1, 'e2': e2 } kwargs_2 = { 'theta_E': theta_E_convert, 's_scale': s_scale_2, 'e1': e1, 'e2': e2 } f_ = self.chameleon.function(x=x, y=1., **kwargs_light) f_1 = self.nie.function(x=x, y=1., **kwargs_1) f_2 = self.nie.function(x=x, y=1., **kwargs_2) npt.assert_almost_equal(f_, (f_1 - f_2), decimal=5) def test_derivatives(self): """ :return: """ x = np.linspace(0.1, 10, 10) w_c, w_t = 0.5, 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_light = { 'alpha_1': 1., 'w_c': .5, 'w_t': 1., 'e1': e1, 'e2': e2 } theta_E_convert, w_c, w_t, s_scale_1, s_scale_2 = self.chameleon.param_convert( alpha_1=1, w_c=0.5, w_t=1., e1=e1, e2=e2) kwargs_1 = { 'theta_E': theta_E_convert, 's_scale': s_scale_1, 'e1': e1, 'e2': e2 } kwargs_2 = { 'theta_E': theta_E_convert, 's_scale': s_scale_2, 'e1': e1, 'e2': e2 } f_x, f_y = self.chameleon.derivatives(x=x, y=1., **kwargs_light) f_x_1, f_y_1 = self.nie.derivatives(x=x, y=1., **kwargs_1) f_x_2, f_y_2 = self.nie.derivatives(x=x, y=1., **kwargs_2) npt.assert_almost_equal(f_x, (f_x_1 - f_x_2), decimal=5) npt.assert_almost_equal(f_y, (f_y_1 - f_y_2), decimal=5) f_x, f_y = self.chameleon.derivatives(x=1, y=0., **kwargs_light) npt.assert_almost_equal(f_x, 1, decimal=1) def test_hessian(self): """ :return: """ x = np.linspace(0.1, 10, 10) w_c, w_t = 0.5, 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_light = { 'alpha_1': 1., 'w_c': .5, 'w_t': 1., 'e1': e1, 'e2': e2 } theta_E_convert, w_c, w_t, s_scale_1, s_scale_2 = self.chameleon.param_convert( alpha_1=1, w_c=0.5, w_t=1., e1=e1, e2=e2) kwargs_1 = { 'theta_E': theta_E_convert, 's_scale': s_scale_1, 'e1': e1, 'e2': e2 } kwargs_2 = { 'theta_E': theta_E_convert, 's_scale': s_scale_2, 'e1': e1, 'e2': e2 } f_xx, f_xy, f_yx, f_yy = self.chameleon.hessian(x=x, y=1., **kwargs_light) f_xx_1, f_xy_1, f_yx_1, f_yy_1 = self.nie.hessian(x=x, y=1., **kwargs_1) f_xx_2, f_xy_2, f_yx_2, f_yy_2 = self.nie.hessian(x=x, y=1., **kwargs_2) npt.assert_almost_equal(f_xx, (f_xx_1 - f_xx_2), decimal=5) npt.assert_almost_equal(f_yy, (f_yy_1 - f_yy_2), decimal=5) npt.assert_almost_equal(f_xy, (f_xy_1 - f_xy_2), decimal=5) npt.assert_almost_equal(f_yx, (f_yx_1 - f_yx_2), decimal=5) def test_static(self): x, y = 1., 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_light = { 'alpha_1': 1., 'w_c': .5, 'w_t': 1., 'e1': e1, 'e2': e2 } f_ = self.chameleon.function(x, y, **kwargs_light) self.chameleon.set_static(**kwargs_light) f_static = self.chameleon.function(x, y, **kwargs_light) npt.assert_almost_equal(f_, f_static, decimal=8) self.chameleon.set_dynamic() kwargs_light = { 'alpha_1': 2., 'w_c': .5, 'w_t': 1., 'e1': e1, 'e2': e2 } f_dyn = self.chameleon.function(x, y, **kwargs_light) assert f_dyn != f_static
class TestSIE(object): """ tests the Gaussian methods """ def setup(self): from lenstronomy.LensModel.Profiles.sie import SIE from lenstronomy.LensModel.Profiles.spemd import SPEMD from lenstronomy.LensModel.Profiles.nie import NIE self.sie = SIE(NIE=False) self.sie_nie = SIE(NIE=True) self.spemd = SPEMD() 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 = 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, values_spemd, decimal=6) def test_derivatives(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.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.9 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)
class Chameleon(LensProfileBase): """ class of the Chameleon model (See Suyu+2014) an elliptical truncated double isothermal profile """ param_names = ['alpha_1', 'w_c', 'w_t', 'e1', 'e2', 'center_x', 'center_y'] lower_limit_default = {'alpha_1': 0, 'w_c': 0, 'w_t': 0, 'e1': -0.8, 'e2': -0.8, 'center_x': -100, 'center_y': -100} upper_limit_default = {'alpha_1': 100, 'w_c': 100, 'w_t': 100, 'e1': 0.8, 'e2': 0.8, 'center_x': 100, 'center_y': 100} def __init__(self, static=False): self._nie_1 = NIE() self._nie_2 = NIE() super(Chameleon, self).__init__() self._static = static def function(self, x, y, alpha_1, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param alpha_1: deflection angle at 1 (arcseconds) from the center :param w_c: see Suyu+2014 :param w_t: see Suyu+2014 :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: ra center :param center_y: dec center :return: lensing potential """ theta_E_conv, w_c, w_t, s_scale_1, s_scale_2 = self.param_convert(alpha_1, w_c, w_t, e1, e2) f_1 = self._nie_1.function(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_2 = self._nie_2.function(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_ = f_1 - f_2 return f_ def derivatives(self, x, y, alpha_1, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param alpha_1: deflection angle at 1 (arcseconds) from the center :param w_c: see Suyu+2014 :param w_t: see Suyu+2014 :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: ra center :param center_y: dec center :return: deflection angles (RA, DEC) """ theta_E_conv, w_c, w_t, s_scale_1, s_scale_2 = self.param_convert(alpha_1, w_c, w_t, e1, e2) f_x_1, f_y_1 = self._nie_1.derivatives(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_x_2, f_y_2 = self._nie_2.derivatives(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_x = f_x_1 - f_x_2 f_y = f_y_1 - f_y_2 return f_x, f_y def hessian(self, x, y, alpha_1, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param alpha_1: deflection angle at 1 (arcseconds) from the center :param w_c: see Suyu+2014 :param w_t: see Suyu+2014 :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: ra center :param center_y: dec center :return: second derivatives of the lensing potential (Hessian: f_xx, f_xy, f_yx, f_yy) """ theta_E_conv, w_c, w_t, s_scale_1, s_scale_2 = self.param_convert(alpha_1, w_c, w_t, e1, e2) f_xx_1, f_xy_1, f_yx_1, f_yy_1 = self._nie_1.hessian(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_xx_2, f_xy_2, f_yx_2, f_yy_2 = self._nie_2.hessian(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_xx = f_xx_1 - f_xx_2 f_yy = f_yy_1 - f_yy_2 f_xy = f_xy_1 - f_xy_2 f_yx = f_yx_1 - f_yx_2 return f_xx, f_xy, f_yx, f_yy def param_convert(self, alpha_1, w_c, w_t, e1, e2): """ convert the parameter alpha_1 (deflection angle one arcsecond from the center) into the "Einstein radius" scale parameter of the two NIE profiles :param alpha_1: deflection angle at 1 (arcseconds) from the center :param w_c: see Suyu+2014 :param w_t: see Suyu+2014 :param e1: eccentricity modulus :param ee: eccentricity modulus :return: """ if self._static is True: return self._theta_convert_static, self._w_c_static, self._w_t_stactic, self._s_scale_1_static, self._s_scale_2_static return self._param_convert(alpha_1, w_c, w_t, e1, e2) def _param_convert(self, alpha_1, w_c, w_t, e1, e2): if not w_t >= w_c: return 0, w_t, w_c, 1, 1 s_scale_1 = w_c s_scale_2 = w_t f_x_1, f_y_1 = self._nie_1.derivatives(1, 0, theta_E=1, e1=0, e2=0, s_scale=s_scale_1) f_x_2, f_y_2 = self._nie_2.derivatives(1, 0, theta_E=1, e1=0, e2=0, s_scale=s_scale_2) f_x = f_x_1 - f_x_2 theta_E_convert = alpha_1 / f_x phi_G, q = param_util.ellipticity2phi_q(e1, e2) s_scale_1 = np.sqrt(4 * w_c ** 2 / (1. + q) ** 2) s_scale_2 = np.sqrt(4 * w_t ** 2 / (1. + q) ** 2) return theta_E_convert, w_c, w_t, s_scale_1, s_scale_2 def set_static(self, alpha_1, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param logM: :param concentration: :param center_x: :param center_y: :return: """ self._static = True self._theta_convert_static, self._w_c_static, self._w_t_stactic, self._s_scale_1_static, self._s_scale_2_static = self._param_convert(alpha_1, w_c, w_t, e1, e2) self._nie_1.set_static(self._theta_convert_static, e1, e2, self._s_scale_1_static, center_x, center_y) self._nie_2.set_static(self._theta_convert_static, e1, e2, self._s_scale_2_static, center_x, center_y) def set_dynamic(self): """ :return: """ self._static = False if hasattr(self, '_theta_convert_static'): del self._theta_convert_static if hasattr(self, '_w_c_static'): del self._w_c_static if hasattr(self, '_w_t_stactic'): del self._w_t_stactic if hasattr(self, '_s_scale_1_static'): del self._s_scale_1_static if hasattr(self, '_s_scale_2_static'): del self._s_scale_2_static self._nie_1.set_dynamic() self._nie_2.set_dynamic()
class TestEPL(object): """ tests the Gaussian methods """ def setup(self): from lenstronomy.LensModel.Profiles.epl import EPL self.EPL = EPL() from lenstronomy.LensModel.Profiles.nie import NIE self.NIE = NIE() def test_function(self): phi_E = 1. t = 1. q = 0.999 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1., 2]) y = np.array([2, 0]) values = self.EPL.function(x, y, phi_E, e1, e2, t) values_nie = self.NIE.function(x, y, phi_E, e1, e2, 0.) delta_f = values[0] - values[1] delta_f_nie = values_nie[0] - values_nie[1] npt.assert_almost_equal(delta_f, delta_f_nie, decimal=5) q = 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1., 2]) y = np.array([2, 0]) values = self.EPL.function(x, y, phi_E, e1, e2, t) values_nie = self.NIE.function(x, y, phi_E, e1, e2, 0.) delta_f = values[0] - values[1] delta_f_nie = values_nie[0] - values_nie[1] npt.assert_almost_equal(delta_f, delta_f_nie, decimal=5) q = 0.4 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1., 2]) y = np.array([2, 0]) values = self.EPL.function(x, y, phi_E, e1, e2, t) values_nie = self.NIE.function(x, y, phi_E, e1, e2, 0.) delta_f = values[0] - values[1] delta_f_nie = values_nie[0] - values_nie[1] npt.assert_almost_equal(delta_f, delta_f_nie, decimal=5) def test_derivatives(self): x = np.array([1]) y = np.array([2]) phi_E = 1. t = 1. q = 1. phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.EPL.derivatives(x, y, phi_E, e1, e2, t) f_x_nie, f_y_nie = self.NIE.derivatives(x, y, phi_E, e1, e2, 0.) npt.assert_almost_equal(f_x, f_x_nie, decimal=4) npt.assert_almost_equal(f_y, f_y_nie, decimal=4) q = 0.7 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.EPL.derivatives(x, y, phi_E, e1, e2, t) f_x_nie, f_y_nie = self.NIE.derivatives(x, y, phi_E, e1, e2, 0.) npt.assert_almost_equal(f_x, f_x_nie, decimal=4) npt.assert_almost_equal(f_y, f_y_nie, decimal=4) def test_hessian(self): x = np.array([1.]) y = np.array([2.]) phi_E = 1. t = 1. q = 0.9 phi_G = 1. e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_xx, f_yy, f_xy = self.EPL.hessian(x, y, phi_E, e1, e2, t) f_xx_nie, f_yy_nie, f_xy_nie = self.NIE.hessian( x, y, phi_E, e1, e2, 0.) npt.assert_almost_equal(f_xx, f_xx_nie, decimal=4) npt.assert_almost_equal(f_yy, f_yy_nie, decimal=4) npt.assert_almost_equal(f_xy, f_xy_nie, decimal=4) def test_static(self): x, y = 1., 1. phi_G, q = 0.3, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) kwargs_lens = {'theta_E': 1., 't': 1.5, 'e1': e1, 'e2': e2} f_ = self.EPL.function(x, y, **kwargs_lens) self.EPL.set_static(**kwargs_lens) f_static = self.EPL.function(x, y, **kwargs_lens) npt.assert_almost_equal(f_, f_static, decimal=8) self.EPL.set_dynamic() kwargs_lens = {'theta_E': 2., 't': 0.5, 'e1': e1, 'e2': e2} f_dyn = self.EPL.function(x, y, **kwargs_lens) assert f_dyn != f_static
class Chameleon(object): """ class of the Chameleon model (See Suyu+2014) an elliptical truncated double isothermal profile """ param_names = ['theta_E', 'w_c', 'w_t', 'e1', 'e2', 'center_x', 'center_y'] lower_limit_default = { 'theta_E': 0, 'w_c': 0, 'w_t': 0, 'e1': -0.8, 'e2': -0.8, 'center_x': -100, 'center_y': -100 } upper_limit_default = { 'theta_E': 100, 'w_c': 100, 'w_t': 100, 'e1': 0.8, 'e2': 0.8, 'center_x': 100, 'center_y': 100 } def __init__(self): self.nie = NIE() def function(self, x, y, theta_E, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param amp: amplitude of first power-law flux :param flux_ratio: ratio of amplitudes of first to second power-law profile :param gamma1: power-law slope :param gamma2: power-law slope :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: center :param center_y: center :return: flux of chameleon profile """ theta_E_conv, w_c, w_t = self._theta_E_convert(theta_E, w_c, w_t) #if not w_t > w_c: # w_t, w_c = w_c, w_t phi_G, q = param_util.ellipticity2phi_q(e1, e2) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) f_1 = self.nie.function(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_2 = self.nie.function(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_ = f_1 - f_2 return f_ def derivatives(self, x, y, theta_E, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param amp: amplitude of first power-law flux :param flux_ratio: ratio of amplitudes of first to second power-law profile :param gamma1: power-law slope :param gamma2: power-law slope :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: center :param center_y: center :return: flux of chameleon profile """ theta_E_conv, w_c, w_t = self._theta_E_convert(theta_E, w_c, w_t) #if not w_t > w_c: # w_t, w_c = w_c, w_t phi_G, q = param_util.ellipticity2phi_q(e1, e2) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) f_x_1, f_y_1 = self.nie.derivatives(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_x_2, f_y_2 = self.nie.derivatives(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_x = f_x_1 - f_x_2 f_y = f_y_1 - f_y_2 return f_x, f_y def hessian(self, x, y, theta_E, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param theta_E: amplitude of first power-law flux :param flux_ratio: ratio of amplitudes of first to second power-law profile :param gamma1: power-law slope :param gamma2: power-law slope :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: center :param center_y: center :return: flux of chameleon profile """ theta_E_conv, w_c, w_t = self._theta_E_convert(theta_E, w_c, w_t) #if not w_t > w_c: # w_t, w_c = w_c, w_t phi_G, q = param_util.ellipticity2phi_q(e1, e2) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) f_xx_1, f_yy_1, f_xy_1 = self.nie.hessian(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_xx_2, f_yy_2, f_xy_2 = self.nie.hessian(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_xx = f_xx_1 - f_xx_2 f_yy = f_yy_1 - f_yy_2 f_xy = f_xy_1 - f_xy_2 return f_xx, f_yy, f_xy def _theta_E_convert(self, theta_E, w_c, w_t): """ convert the parameter theta_E (deflection angle one arcsecond from the center) into the "Einstein radius" scale parameter of the two NIE profiles :param theta_E: :param w_c: :param w_t: :return: """ if not w_t > w_c: w_t, w_c = w_c, w_t s_scale_1 = w_c s_scale_2 = w_t f_x_1, f_y_1 = self.nie.derivatives(1, 0, theta_E=1, e1=0, e2=0, s_scale=s_scale_1) f_x_2, f_y_2 = self.nie.derivatives(1, 0, theta_E=1, e1=0, e2=0, s_scale=s_scale_2) f_x = f_x_1 - f_x_2 theta_E_convert = theta_E / f_x return theta_E_convert, w_c, w_t
class TestSPEMD(object): """ tests the Gaussian methods """ def setup(self): from lenstronomy.LensModel.Profiles.spemd_smooth import SPEMD_SMOOTH self.SPEMD_SMOOT = SPEMD_SMOOTH() from lenstronomy.LensModel.Profiles.nie import NIE self.NIE = NIE() def test_function(self): phi_E = 1. gamma = 2. q = 0.999 phi_G = 1. s_scale = 0.1 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) x = np.array([1., 2]) y = np.array([2, 0]) values = self.SPEMD_SMOOT.function(x, y, phi_E, gamma, e1, e2, s_scale) if fastell4py_bool: values_nie = self.NIE.function(x, y, phi_E, e1, e2, s_scale) delta_f = values[0] - values[1] delta_f_nie = values_nie[0] - values_nie[1] npt.assert_almost_equal(delta_f, delta_f_nie, decimal=5) else: npt.assert_almost_equal(values, 0, decimal=5) def test_derivatives(self): x = np.array([1]) y = np.array([2]) phi_E = 1. gamma = 2. q = 0.7 phi_G = 1. s_scale = 0.1 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_x, f_y = self.SPEMD_SMOOT.derivatives(x, y, phi_E, gamma, e1, e2, s_scale) if fastell4py_bool: f_x_nie, f_y_nie = self.NIE.derivatives(x, y, phi_E, e1, e2, s_scale) #TODO test with higher precision, convention of theta_E might be slightly different from NIE with SPEMD npt.assert_almost_equal(f_x, f_x_nie, decimal=2) npt.assert_almost_equal(f_y, f_y_nie, decimal=2) else: npt.assert_almost_equal(f_x, 0, decimal=7) npt.assert_almost_equal(f_y, 0, decimal=7) def test_hessian(self): x = np.array([1.]) y = np.array([2.]) phi_E = 1. gamma = 2. q = 0.9 phi_G = 1. s_scale = 0.1 e1, e2 = param_util.phi_q2_ellipticity(phi_G, q) f_xx, f_yy, f_xy = self.SPEMD_SMOOT.hessian(x, y, phi_E, gamma, e1, e2, s_scale) if fastell4py_bool: f_xx_nie, f_yy_nie, f_xy_nie = self.NIE.hessian( x, y, phi_E, e1, e2, s_scale) npt.assert_almost_equal(f_xx, f_xx_nie, decimal=3) npt.assert_almost_equal(f_yy, f_yy_nie, decimal=3) npt.assert_almost_equal(f_xy, f_xy_nie, decimal=3) 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) def test_bounds(self): theta_E, gamma, q, phi_G, s_scale = self.SPEMD_SMOOT._parameter_constraints( theta_E=-1, s_scale=0, gamma=3, q=2, phi_G=0) assert theta_E == 0 def test_is_not_empty(self): func = self.SPEMD_SMOOT.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([]))
class Chameleon(object): """ class of the Chameleon model (See Suyu+2014) an elliptical truncated double isothermal profile """ param_names = ['alpha_1', 'w_c', 'w_t', 'e1', 'e2', 'center_x', 'center_y'] lower_limit_default = { 'alpha_1': 0, 'w_c': 0, 'w_t': 0, 'e1': -0.8, 'e2': -0.8, 'center_x': -100, 'center_y': -100 } upper_limit_default = { 'alpha_1': 100, 'w_c': 100, 'w_t': 100, 'e1': 0.8, 'e2': 0.8, 'center_x': 100, 'center_y': 100 } def __init__(self): self.nie = NIE() def function(self, x, y, alpha_1, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param alpha_1: deflection angle at 1 (arcseconds) from the center :param w_c: see Suyu+2014 :param w_t: see Suyu+2014 :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: ra center :param center_y: dec center :return: lensing potential """ theta_E_conv, w_c, w_t = self._theta_convert(alpha_1, w_c, w_t) phi_G, q = param_util.ellipticity2phi_q(e1, e2) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) f_1 = self.nie.function(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_2 = self.nie.function(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_ = f_1 - f_2 return f_ def derivatives(self, x, y, alpha_1, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param alpha_1: deflection angle at 1 (arcseconds) from the center :param w_c: see Suyu+2014 :param w_t: see Suyu+2014 :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: ra center :param center_y: dec center :return: deflection angles (RA, DEC) """ theta_E_conv, w_c, w_t = self._theta_convert(alpha_1, w_c, w_t) phi_G, q = param_util.ellipticity2phi_q(e1, e2) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) f_x_1, f_y_1 = self.nie.derivatives(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_x_2, f_y_2 = self.nie.derivatives(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_x = f_x_1 - f_x_2 f_y = f_y_1 - f_y_2 return f_x, f_y def hessian(self, x, y, alpha_1, w_c, w_t, e1, e2, center_x=0, center_y=0): """ :param x: ra-coordinate :param y: dec-coordinate :param alpha_1: deflection angle at 1 (arcseconds) from the center :param w_c: see Suyu+2014 :param w_t: see Suyu+2014 :param e1: ellipticity parameter :param e2: ellipticity parameter :param center_x: ra center :param center_y: dec center :return: second derivatives of the lensing potential (Hessian: f_xx, f_yy, f_xy) """ theta_E_conv, w_c, w_t = self._theta_convert(alpha_1, w_c, w_t) phi_G, q = param_util.ellipticity2phi_q(e1, e2) s_scale_1 = np.sqrt(4 * w_c**2 / (1. + q)**2) s_scale_2 = np.sqrt(4 * w_t**2 / (1. + q)**2) f_xx_1, f_yy_1, f_xy_1 = self.nie.hessian(x, y, theta_E_conv, e1, e2, s_scale_1, center_x, center_y) f_xx_2, f_yy_2, f_xy_2 = self.nie.hessian(x, y, theta_E_conv, e1, e2, s_scale_2, center_x, center_y) f_xx = f_xx_1 - f_xx_2 f_yy = f_yy_1 - f_yy_2 f_xy = f_xy_1 - f_xy_2 return f_xx, f_yy, f_xy def _theta_convert(self, alpha_1, w_c, w_t): """ convert the parameter alpha_1 (deflection angle one arcsecond from the center) into the "Einstein radius" scale parameter of the two NIE profiles :param alpha_1: deflection angle at 1 (arcseconds) from the center :param w_c: see Suyu+2014 :param w_t: see Suyu+2014 :return: """ if not w_t >= w_c: return 0, w_t, w_c #w_t, w_c = w_c, w_t s_scale_1 = w_c s_scale_2 = w_t f_x_1, f_y_1 = self.nie.derivatives(1, 0, theta_E=1, e1=0, e2=0, s_scale=s_scale_1) f_x_2, f_y_2 = self.nie.derivatives(1, 0, theta_E=1, e1=0, e2=0, s_scale=s_scale_2) f_x = f_x_1 - f_x_2 theta_E_convert = alpha_1 / f_x return theta_E_convert, w_c, w_t