def test_elliptisity2phi_q_symmetry(): phi, q = 1.5, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi, q) phi_new, q_new = param_util.ellipticity2phi_q(e1, e2) assert phi == phi_new assert q == q_new phi, q = -1.5, 0.8 e1, e2 = param_util.phi_q2_ellipticity(phi, q) phi_new, q_new = param_util.ellipticity2phi_q(e1, e2) assert phi == phi_new assert q == q_new e1, e2 = 0.1, -0.1 phi, q = param_util.ellipticity2phi_q(e1, e2) e1_new, e2_new = param_util.phi_q2_ellipticity(phi, q) npt.assert_almost_equal(e1, e1_new, decimal=10) npt.assert_almost_equal(e2, e2_new, decimal=10) e1, e2 = 2.99, -0.0 phi, q = param_util.ellipticity2phi_q(e1, e2) print(phi, q) e1_new, e2_new = param_util.phi_q2_ellipticity(phi, q) phi_new, q_new = param_util.ellipticity2phi_q(e1_new, e2_new) npt.assert_almost_equal(phi, phi_new, decimal=10) npt.assert_almost_equal(q, q_new, decimal=10)
def condition_diskbulgebar(kwargs_lens, kwargs_source, kwargs_lens_light, kwargs_ps, kwargs_special, kwargs_extinction): logL = 0 phi0, q0 = param_util.ellipticity2phi_q(kwargs_lens_light[0]['e1'], kwargs_lens_light[0]['e2']) phi1, q1 = param_util.ellipticity2phi_q(kwargs_lens_light[1]['e1'], kwargs_lens_light[1]['e2']) phi2, q2 = param_util.ellipticity2phi_q(kwargs_lens_light[2]['e1'], kwargs_lens_light[2]['e2']) if (kwargs_lens_light[0]['R_sersic'] < kwargs_lens_light[1]['R_sersic']): logL -= 10**15 if (kwargs_lens_light[0]['R_sersic'] * 0.15 > kwargs_lens_light[1]['R_sersic']): logL -= 10**15 if (kwargs_lens_light[0]['R_sersic'] > kwargs_lens_light[2]['R_sersic']): logL -= 10**15 if (kwargs_lens_light[0]['R_sersic'] * 0.15 < kwargs_lens_light[2]['R_sersic']): logL -= 10**15 if (q0 < q2) or (q1 < q0): logL -= 10**15 if abs(phi0 - (-apertures[0].theta)) > 5 / 180 * np.pi: logL -= 10**15 if abs(phi2 - (-apertures[2].theta)) > 5 / 180 * np.pi: logL -= 10**15 return logL
def test_displace_eccentricity(): #x, y = np.array([1, 0]), np.array([0, 1]) x, y = util.make_grid(numPix=10, deltapix=1) e1 = 0.1 #.1 e2 = -0 #.1 center_x, center_y = 0, 0 x_, y_ = param_util.transform_e1e2(x, y, e1, e2, center_x=center_x, center_y=center_y) 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) print(cos_phi, sin_phi) xt1 = cos_phi * x_shift + sin_phi * y_shift xt2 = -sin_phi * x_shift + cos_phi * y_shift xt1 *= np.sqrt(q) xt2 /= np.sqrt(q) npt.assert_almost_equal(x_, xt1, decimal=8) npt.assert_almost_equal(y_, xt2, decimal=8) x, y = util.make_grid(numPix=10, deltapix=1) x, y = np.array([1, 0]), np.array([0, 1]) e1 = 0.1 #.1#.1 e2 = 0 center_x, center_y = 0, 0 x_, y_ = param_util.transform_e1e2(x, y, e1, e2, center_x=center_x, center_y=center_y) 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) print(cos_phi, sin_phi) xt1 = cos_phi * x_shift + sin_phi * y_shift xt2 = -sin_phi * x_shift + cos_phi * y_shift xt1 *= np.sqrt(q) xt2 /= np.sqrt(q) npt.assert_almost_equal(x_, xt1, decimal=8) npt.assert_almost_equal(y_, xt2, decimal=8)
def test_ellipticity2phi_q(): e1, e2 = 0.3, 0 phi, q = param_util.ellipticity2phi_q(e1, e2) assert phi == 0 assert q == 0.53846153846153844 # Works on np arrays as well e1 = np.array([0.3, 0.9]) e2 = np.array([0.0, 0.9]) phi, q = param_util.ellipticity2phi_q(e1, e2) assert np.allclose(phi, [0.0, 0.39269908], atol=1.e-08) assert np.allclose(q, [0.53846153, 5.00025001e-05], atol=1.e-08)
def condition_bulgedisk(kwargs_lens, kwargs_source, kwargs_lens_light, kwargs_ps, kwargs_special, kwargs_extinction): logL = 0 phi0, q0 = param_util.ellipticity2phi_q(kwargs_source[0]['e1'], kwargs_source[0]['e2']) phi1, q1 = param_util.ellipticity2phi_q(kwargs_source[1]['e1'], kwargs_source[1]['e2']) cond_0 = (kwargs_source[0]['R_sersic'] > kwargs_source[1]['R_sersic'] * 0.9) cond_1 = (kwargs_source[0]['R_sersic'] < kwargs_source[1]['R_sersic'] * 0.15) cond_2 = (q0 < q1) if cond_0 or cond_1 or cond_2: logL -= 10**15 return logL
def condition_diskbulge(kwargs_lens, kwargs_source, kwargs_lens_light, kwargs_ps, kwargs_special, kwargs_extinction): logL = 0 phi0, q0 = param_util.ellipticity2phi_q(kwargs_lens_light[0]['e1'], kwargs_lens_light[0]['e2']) phi1, q1 = param_util.ellipticity2phi_q(kwargs_lens_light[1]['e1'], kwargs_lens_light[1]['e2']) if (kwargs_lens_light[1]['R_sersic'] > kwargs_lens_light[0]['R_sersic']): logL -= 10**15 if (kwargs_lens_light[1]['R_sersic'] < kwargs_lens_light[0]['R_sersic'] * 0.15): logL -= 10**15 # if (q1 < 0.9): # logL -= 10**15 return logL
def function(self, x, y, Rs, alpha_Rs, e1, e2, center_x=0, center_y=0): """ returns elliptically distorted NFW lensing potential :param x: angular position (normally in units of arc seconds) :param y: angular position (normally in units of arc seconds) :param Rs: turn over point in the slope of the NFW profile in angular unit :param alpha_Rs: deflection (angular units) at projected Rs :param e1: eccentricity component in x-direction :param e2: eccentricity component in y-direction :param center_x: center of halo (in angular units) :param center_y: center of halo (in angular units) :return: lensing potential """ 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.9999) 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) rho0_input = self.nfw._alpha2rho0(alpha_Rs=alpha_Rs, Rs=Rs) if Rs < 0.0000001: Rs = 0.0000001 f_ = self.nfw.nfwPot(R_, Rs, rho0_input) return f_
def function(self, x, y, theta_E, gamma, e1, e2, s_scale, center_x=0, center_y=0): """ :param x: x-coordinate (angle) :param y: y-coordinate (angle) :param theta_E: Einstein radius (angle), pay attention to specific definition! :param gamma: logarithmic slope of the power-law profile. gamma=2 corresponds to isothermal :param e1: eccentricity component :param e2: eccentricity component :param s_scale: smoothing scale in the center of the profile (angle) :param center_x: x-position of lens center :param center_y: y-position of lens center :return: lensing potential """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) theta_E, gamma, q, phi_G, s_scale = self._parameter_constraints(theta_E, gamma, q, phi_G, s_scale) x_shift = x - center_x y_shift = y - center_y q_fastell, gam, s2 = self.convert_params(theta_E, gamma, q, s_scale) cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) x1 = cos_phi*x_shift+sin_phi*y_shift x2 = -sin_phi*x_shift+cos_phi*y_shift if self._fastell4py_bool and self.is_not_empty(x1, x2): potential = self.fastell4py.ellipphi(x1, x2, q_fastell, gam, arat=q, s2=s2) n = len(np.atleast_1d(x)) if n <= 1: if np.shape(x) == (): return np.array(potential[0]) else: potential = np.zeros_like(x1) Warning("SPEMD model output replaced by zeros as fastell4py package is not installed!") return potential
def function(self, x, y, theta_E, gamma, e1, e2, s_scale, center_x=0, center_y=0): phi_G, q = param_util.ellipticity2phi_q(e1, e2) theta_E, gamma, q, phi_G, s_scale = self._parameter_constraints( theta_E, gamma, q, phi_G, s_scale) x_shift = x - center_x y_shift = y - center_y q_fastell, gam = self.convert_params(theta_E, gamma, q) cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) x1 = cos_phi * x_shift + sin_phi * y_shift x2 = -sin_phi * x_shift + cos_phi * y_shift if self._fastell4py_bool and self.is_not_empty(x1, x2): potential = self.fastell4py.ellipphi(x1, x2, q_fastell, gam, arat=q, s2=s_scale) n = len(np.atleast_1d(x)) if n <= 1: if np.shape(x) == (): return np.array(potential[0]) else: potential = np.zeros_like(x1) return potential
def add_qphi_columns(metadata): """Add alternate ellipticity definitions (axis ratio and angle) for each component for which ellipticity was defined in terms of e1, e2 Parameters ---------- metadata : pd.DataFrame the metadatadata generated by Baobab Returns ------- pd.DataFrame metadata augmented with e1, e2 for each relevant component """ e1_col_names = sorted(fnmatch.filter(metadata.columns.values, '*_e1')) e2_col_names = sorted(fnmatch.filter(metadata.columns.values, '*_e2')) for i, e1_col_name in enumerate(e1_col_names): e2_col_name = e2_col_names[i] comp_name = e1_col_name.split('_e1')[ 0] # component name, e.g. 'lens_light' e1 = metadata[e1_col_name].values e2 = metadata[e2_col_name].values phi, q = param_util.ellipticity2phi_q(e1, e2) metadata['{:s}_q'.format(comp_name)] = q metadata['{:s}_phi'.format(comp_name)] = phi return metadata
def derivatives(self, x, y, sigma0, Ra, Rs, 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) x_ = (cos_phi * x_shift + sin_phi * y_shift) * np.sqrt(1 - e) y_ = (-sin_phi * x_shift + cos_phi * y_shift) * np.sqrt(1 + e) f_x_prim, f_y_prim = self.spherical.derivatives(x_, y_, sigma0, Ra, Rs, 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 args_to_kwargs(self, args): (thetaE, center_x, center_y, e1, e2, g1, g2) = args gamma = self.kwargs_lens[0]['gamma'] kwargs_epl = { 'theta_E': thetaE, 'center_x': center_x, 'center_y': center_y, 'e1': e1, 'e2': e2, 'gamma': gamma } kwargs_shear = {'gamma1': g1, 'gamma2': g2} self.kwargs_lens[0] = kwargs_epl self.kwargs_lens[1] = kwargs_shear self.kwargs_lens[2]['center_x'] = center_x self.kwargs_lens[2]['center_y'] = center_y phi, _ = ellipticity2phi_q(e1, e2) self.kwargs_lens[2]['phi_m'] = phi return self.kwargs_lens
def function(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0): """ :param x: set of x-coordinates :type x: array of size (n) :param theta_E: Einstein radius of lense :type theta_E: float. :param gamma: power law slope of mass profifle :type gamma: <2 float :param e1: eccentricity :type e1: -1<e1<1 :param e2: eccentricity :type e2: -1<e1<1 :returns: function :raises: AttributeError, KeyError """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) gamma, q = self._param_bounds(gamma, q) theta_E *= q x_shift = x - center_x y_shift = y - center_y E = theta_E / (((3 - gamma) / 2.)**(1. / (1 - gamma)) * np.sqrt(q)) #E = phi_E eta = -gamma + 3 xt1 = np.cos(phi_G) * x_shift + np.sin(phi_G) * y_shift xt2 = -np.sin(phi_G) * x_shift + np.cos(phi_G) * y_shift p2 = xt1**2 + xt2**2 / q**2 s2 = 0. # softening return 2 * E**2 / eta**2 * ((p2 + s2) / E**2)**(eta / 2)
def derivatives(self, x, y, a, s, e1, e2, center_x, center_y): """ :param x: coordinate in image plane (angle) :param y: coordinate in image plane (angle) :param a: lensing strength :param s: core radius :param e1: eccentricity :param e2: eccentricity :param center_x: center of profile :param center_y: center of profile :return: deflection in x- and y-direction """ phi_q, q = param_util.ellipticity2phi_q(e1, e2) # shift x_ = x - center_x y_ = y - center_y # rotate x__, y__ = util.rotate(x_, y_, phi_q) f__x, f__y = self.major_axis_model.derivatives(x__, y__, a, s, q) # rotate deflections back f_x, f_y = util.rotate(f__x, f__y, -phi_q) return f_x, f_y
def derivatives(self, x, y, Rs, alpha_Rs, e1, e2, center_x=0, center_y=0): """ returns df/dx and df/dy of the function, calculated as an elliptically distorted deflection angle of the spherical NFW profile :param x: angular position (normally in units of arc seconds) :param y: angular position (normally in units of arc seconds) :param Rs: turn over point in the slope of the NFW profile in angular unit :param alpha_Rs: deflection (angular units) at projected Rs :param e1: eccentricity component in x-direction :param e2: eccentricity component in y-direction :param center_x: center of halo (in angular units) :param center_y: center of halo (in angular units) :return: deflection in x-direction, deflection in y-direction """ 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.9999) 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) rho0_input = self.nfw._alpha2rho0(alpha_Rs=alpha_Rs, Rs=Rs) if Rs < 0.0000001: Rs = 0.0000001 f_x_prim, f_y_prim = self.nfw.nfwAlpha(R_, Rs, rho0_input, xt1, xt2) 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, sigma0, Rs, e1, e2, center_x=0, center_y=0): """ returns Hessian matrix of function d^2f/dx^2, d^2/dxdy, d^2/dydx, d^f/dy^2 """ phi_q, q = param_util.ellipticity2phi_q(e1, e2) # shift x_ = x - center_x y_ = y - center_y # rotate x__, y__ = util.rotate(x_, y_, phi_q) f__xx, f__xy, __, f__yy = self.cse_major_axis_set.hessian( x__ / Rs, y__ / Rs, self._a_list, self._s_list, q) # rotate back kappa = 1. / 2 * (f__xx + f__yy) gamma1__ = 1. / 2 * (f__xx - f__yy) gamma2__ = f__xy gamma1 = np.cos(2 * phi_q) * gamma1__ - np.sin(2 * phi_q) * gamma2__ gamma2 = +np.sin(2 * phi_q) * gamma1__ + np.cos(2 * phi_q) * gamma2__ f_xx = kappa + gamma1 f_yy = kappa - gamma1 f_xy = gamma2 const = self._normalization(sigma0, Rs, q) / Rs**2 return const * f_xx, const * f_xy, const * f_xy, const * f_yy
def hessian(self, x, y, theta_E, e1, e2, s_scale, center_x=0, center_y=0): """ :param x: :param y: :param theta_E: :param e1: :param e2: :param s_scale: :param center_x: :param center_y: :return: """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) theta_E = self._theta_E_q_convert(theta_E, q) # shift x_ = x - center_x y_ = y - center_y # rotate x__, y__ = util.rotate(x_, y_, phi_G) # evaluate f__xx, f__yy, f__xy = self.nie_simple.hessian(x__, y__, theta_E, s_scale, q) # rotate back kappa = 1./2 * (f__xx + f__yy) gamma1__ = 1./2 *(f__xx - f__yy) gamma2__ = f__xy gamma1 = np.cos(2 * phi_G) * gamma1__ - np.sin(2 * phi_G) * gamma2__ gamma2 = +np.sin(2 * phi_G) * gamma1__ + np.cos(2 * phi_G) * gamma2__ f_xx = kappa + gamma1 f_yy = kappa - gamma1 f_xy = gamma2 return f_xx, f_yy, f_xy
def derivatives(self, x, y, theta_E, e1, e2, s_scale, center_x=0, center_y=0): """ :param x: :param y: :param theta_E: :param e1: :param e2: :param s_scale: :param center_x: :param center_y: :return: """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) theta_E = self._theta_E_q_convert(theta_E, q) # shift x_ = x - center_x y_ = y - center_y # rotate x__, y__ = util.rotate(x_, y_, phi_G) # evaluate f__x, f__y = self.nie_simple.derivatives(x__, y__, theta_E, s_scale, q) # rotate back f_x, f_y = util.rotate(f__x, f__y, -phi_G) return f_x, f_y
def derivatives(self, x, y, sigma0, Ra, Rs, 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_, y_ = param_util.transform_e1e2_square_average( x, y, e1, e2, center_x, center_y) e = param_util.q2e(q) cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) f_x_prim, f_y_prim = self.spherical.derivatives(x_, y_, sigma0, Ra, Rs, 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 test_convergernce(self): """ test the convergence and compares it with the original Sersic profile :return: """ x = np.array([0, 0, 0, 0, 0]) y = np.array([0.5, 1, 1.5, 2, 2.5]) n_sersic = 4.5 R_sersic = 2.5 k_eff = 0.2 f_xx, f_xy, f_yx, f_yy = self.sersic.hessian(x, y, n_sersic, R_sersic, k_eff) kappa = (f_xx + f_yy) / 2. assert kappa[0] > 0 flux = self.sersic_light.function(x, y, amp=1., R_sersic=R_sersic, n_sersic=n_sersic) flux /= flux[0] kappa /= kappa[0] npt.assert_almost_equal(flux[1], kappa[1], decimal=5) xvalues = np.linspace(0.5, 3., 100) e1, e2 = 0.4, 0. q = ellipticity2phi_q(e1, e2)[1] kappa_ellipse = self.sersic_2.projected_mass(xvalues, 0, q, n_sersic, R_sersic, k_eff) fxx, _, _, fyy = self.sersic_2.hessian(xvalues, 0, n_sersic, R_sersic, k_eff, e1, e2) npt.assert_almost_equal(kappa_ellipse, 0.5 * (fxx + fyy), decimal=5)
def hessian(self, x, y, a, s, e1, e2, center_x, center_y): """ :param x: coordinate in image plane (angle) :param y: coordinate in image plane (angle) :param a: lensing strength :param s: core radius :param e1: eccentricity :param e2: eccentricity :param center_x: center of profile :param center_y: center of profile :return: hessian elements f_xx, f_xy, f_yx, f_yy """ phi_q, q = param_util.ellipticity2phi_q(e1, e2) # shift x_ = x - center_x y_ = y - center_y # rotate x__, y__ = util.rotate(x_, y_, phi_q) f__xx, f__xy, __, f__yy = self.major_axis_model.hessian(x__, y__, a, s, q) # rotate back kappa = 1. / 2 * (f__xx + f__yy) gamma1__ = 1. / 2 * (f__xx - f__yy) gamma2__ = f__xy gamma1 = np.cos(2 * phi_q) * gamma1__ - np.sin(2 * phi_q) * gamma2__ gamma2 = +np.sin(2 * phi_q) * gamma1__ + np.cos(2 * phi_q) * gamma2__ f_xx = kappa + gamma1 f_yy = kappa - gamma1 f_xy = gamma2 return f_xx, f_xy, f_xy, f_yy
def function(self, x, y, amp, R_sersic, Re, n_sersic, gamma, e1, e2, center_x=0, center_y=0, alpha=3.0, max_R_frac=100.0): """ :param x: :param y: :param amp: surface brightness/amplitude value at the half light radius :param R_sersic: semi-major axis half light radius :param Re: "break" core radius :param n_sersic: Sersic index :param gamma: inner power-law exponent :param e1: eccentricity parameter :param e2: eccentricity parameter :param center_x: center in x-coordinate :param center_y: center in y-coordinate :param alpha: sharpness of the transition between the cusp and the outer Sersic profile (float) :param max_R_frac: maximum window outside of which the mass is zeroed, in units of R_sersic (float) :return: Cored Sersic profile value at (x, y) """ #TODO max_R_frac not implemented phi_G, q = param_util.ellipticity2phi_q(e1, e2) R_ = self.get_distance_from_center(x, y, phi_G, q, center_x, center_y) R = self._R_stable(R_) bn = self.b_n(n_sersic) result = amp * (1 + (Re / R)**alpha)**(gamma/alpha)*np.exp(-bn*(((R ** alpha + Re ** alpha)/R_sersic**alpha)**(1./(alpha*n_sersic)) - 1.)) return np.nan_to_num(result)
def args_to_kwargs(self, args): (thetaE, center_x, center_y, e1, e2, g1, g2) = args gamma = self.kwargs_lens[0]['gamma'] kwargs_epl = { 'theta_E': thetaE, 'center_x': center_x, 'center_y': center_y, 'e1': e1, 'e2': e2, 'gamma': gamma } phi, _ = shear_cartesian2polar(g1, g2) gamma1, gamma2 = shear_polar2cartesian(phi, self._shear_strength) kwargs_shear = {'gamma1': gamma1, 'gamma2': gamma2} self.kwargs_lens[0] = kwargs_epl self.kwargs_lens[1] = kwargs_shear self.kwargs_lens[2]['center_x'] = center_x self.kwargs_lens[2]['center_y'] = center_y phi, _ = ellipticity2phi_q(e1, e2) self.kwargs_lens[2]['phi_m'] = phi return self.kwargs_lens
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, amp, sigma, e1, e2, center_x=0, center_y=0): """ Compute the derivatives of function angles :math:`\partial f/\partial x`, :math:`\partial f/\partial y` at :math:`x,\ y`. :param x: x coordinate :type x: ``float`` or ``numpy.array`` :param y: y coordinate :type y: ``float`` or ``numpy.array`` :param amp: Amplitude of Gaussian, convention: :math:`A/(2 \pi\sigma^2) \exp(-(x^2+y^2/q^2)/2\sigma^2)` :type amp: ``float`` :param sigma: Standard deviation of Gaussian :type sigma: ``float`` :param e1: Ellipticity parameter 1 :type e1: ``float`` :param e2: Ellipticity parameter 2 :type e2: ``float`` :param center_x: x coordinate of centroid :type center_x: ``float`` :param center_y: y coordianate of centroid :type center_y: ``float`` :return: Deflection angle :math:`\partial f/\partial x`, :math:`\partial f/\partial y` for elliptical Gaussian convergence. :rtype: tuple ``(float, float)`` or ``(numpy.array, numpy.array)`` with each ``numpy.array``'s shape equal to ``x.shape``. """ phi_g, q = param_util.ellipticity2phi_q(e1, e2) if q > 1 - self.min_ellipticity: return self.spherical.derivatives(x, y, amp, sigma, center_x, center_y) # adjusting amplitude to make the notation compatible with the # formulae given in Shajib (2019). amp_ = amp / (2 * np.pi * sigma**2) # converting ellipticity definition from q*x^2 + y^2/q to q^2*x^2 + y^2 sigma_ = sigma * np.sqrt(q) # * q x_shift = x - center_x y_shift = y - center_y cos_phi = np.cos(phi_g) sin_phi = np.sin(phi_g) # rotated coordinates x_ = cos_phi * x_shift + sin_phi * y_shift y_ = -sin_phi * x_shift + cos_phi * y_shift _p = q / sigma_ / np.sqrt(2 * (1. - q**2)) sig_func_re, sig_func_im = self.sigma_function(_p * x_, _p * y_, q) alpha_x_ = amp_ * sigma_ * self.sgn(x_ + 1j * y_) * np.sqrt( 2 * np.pi / (1. - q**2)) * sig_func_re alpha_y_ = -amp_ * sigma_ * self.sgn(x_ + 1j * y_) * np.sqrt( 2 * np.pi / (1. - q**2)) * sig_func_im # rotate back to the original frame f_x = alpha_x_ * cos_phi - alpha_y_ * sin_phi f_y = alpha_x_ * sin_phi + alpha_y_ * cos_phi return f_x, f_y
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 derivatives(self, x, y, Rs, alpha_Rs, e1, e2, center_x=0, center_y=0): """ returns df/dx and df/dy of the function, calculated as an elliptically distorted deflection angle of the spherical NFW profile :param x: angular position (normally in units of arc seconds) :param y: angular position (normally in units of arc seconds) :param Rs: turn over point in the slope of the NFW profile in angular unit :param alpha_Rs: deflection (angular units) at projected Rs :param e1: eccentricity component in x-direction :param e2: eccentricity component in y-direction :param center_x: center of halo (in angular units) :param center_y: center of halo (in angular units) :return: deflection in x-direction, deflection in y-direction """ x_, y_ = param_util.transform_e1e2_square_average( x, y, e1, e2, center_x, center_y) phi_G, q = param_util.ellipticity2phi_q(e1, e2) cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) e = abs(1 - q) R_ = np.sqrt(x_**2 + y_**2) rho0_input = self.nfw.alpha2rho0(alpha_Rs=alpha_Rs, Rs=Rs) if Rs < 0.0000001: Rs = 0.0000001 f_x_prim, f_y_prim = self.nfw.nfwAlpha(R_, Rs, rho0_input, x_, y_) 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 translate_result(self): """ Translate some parameter results to make the fitting more readable, including the flux value, and the elliptical. """ import lenstronomy.Util.param_util as param_util from galight.tools.measure_tools import model_flux_cal self.final_result_galaxy = copy.deepcopy(self.source_result) flux_sersic_model = model_flux_cal(self.final_result_galaxy) for i in range(len(self.final_result_galaxy)): source = self.final_result_galaxy[i] source['phi_G'], source['q'] = param_util.ellipticity2phi_q( source['e1'], source['e2']) source['flux_sersic_model'] = flux_sersic_model[i] source['flux_within_frame'] = np.sum(self.image_host_list[i]) source['magnitude'] = -2.5 * np.log10( source['flux_within_frame']) + self.zp self.final_result_galaxy[i] = source self.final_result_ps = copy.deepcopy(self.ps_result) for i in range(len(self.final_result_ps)): ps = self.final_result_ps[i] ps['flux_within_frame'] = np.sum(self.image_ps_list[i]) ps['magnitude'] = -2.5 * np.log10( ps['flux_within_frame']) + self.zp self.final_result_ps[i] = ps
def function(self, x, y, amp, R_sersic, n_sersic, e1, e2, center_x=0, center_y=0, max_R_frac=100.0): """ :param x: :param y: :param amp: surface brightness/amplitude value at the half light radius :param R_sersic: semi-major axis half light radius :param n_sersic: Sersic index :param e1: eccentricity parameter :param e2: eccentricity parameter :param center_x: center in x-coordinate :param center_y: center in y-coordinate :param max_R_frac: maximum window outside of which the mass is zeroed, in units of R_sersic (float) :return: Sersic profile value at (x, y) """ R_sersic = np.maximum(0, R_sersic) phi_G, q = param_util.ellipticity2phi_q(e1, e2) R = self.get_distance_from_center(x, y, phi_G, q, center_x, center_y) result = self._r_sersic(R, R_sersic, n_sersic, max_R_frac) return amp * result
def derivatives(self, x, y, n_sersic, R_sersic, k_eff, e1, e2, center_x=0, center_y=0): """ returns df/dx and df/dy of the function """ phi_G, q = param_util.ellipticity2phi_q(e1, e2) e = abs(1. - q) cos_phi = np.cos(phi_G) sin_phi = np.sin(phi_G) x_, y_ = self._coord_transf(x, y, q, phi_G, center_x, center_y) f_x_prim, f_y_prim = self.sersic.derivatives(x_, y_, n_sersic, R_sersic, k_eff) 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