def test_d_r_dy(self): x = 1 y = 0 out = calc_util.d_r_dy(x, y) assert out == 0 x, y = util.make_grid(numPix=10, deltapix=0.1) dy = 0.000001 out = calc_util.d_r_dy(x, y) r, phi = param_util.cart2polar(x, y) r_dy, phi_dy = param_util.cart2polar(x, y + dy) dr_dy = (r_dy - r) / dy npt.assert_almost_equal(dr_dy, out, decimal=5)
def test_d_r_dx(self): x = 1 y = 0 out = calc_util.d_r_dx(x, y) assert out == 1 x, y = util.make_grid(numPix=10, deltapix=0.1) dx = 0.000001 out = calc_util.d_r_dx(x, y) r, phi = param_util.cart2polar(x, y) r_dx, phi_dx = param_util.cart2polar(x + dx, y) dr_dx = (r_dx - r) / dx npt.assert_almost_equal(dr_dx, out, decimal=5)
def test_d_phi_dx(self): x, y = np.array([1., 0., -1.]), np.array([1., 1., -1.]) dx, dy = 0.0001, 0.0001 r, phi = param_util.cart2polar(x, y, center_x=0, center_y=0) d_phi_dx = calc_util.d_phi_dx(x, y) d_phi_dy = calc_util.d_phi_dy(x, y) r_dx, phi_dx = param_util.cart2polar(x + dx, y, center_x=0, center_y=0) r_dy, phi_dy = param_util.cart2polar(x, y + dy, center_x=0, center_y=0) d_phi_dx_num = (phi_dx - phi) / dx d_phi_dy_num = (phi_dy - phi) / dy npt.assert_almost_equal(d_phi_dx, d_phi_dx_num, decimal=4) npt.assert_almost_equal(d_phi_dy, d_phi_dy_num, decimal=4)
def test_cart2polar(): #singel 2d coordinate transformation center_x, center_y = 0, 0 x = 1 y = 1 r, phi = param_util.cart2polar(x, y, center_x, center_y) assert r == np.sqrt(2) #radial part assert phi == np.arctan(1) #array of 2d coordinates x = np.array([1, 2]) y = np.array([1, 1]) r, phi = param_util.cart2polar(x, y, center_x, center_y) assert r[0] == np.sqrt(2) #radial part assert phi[0] == np.arctan(1)
def derivatives(self, x, y, coeff, d_r, d_phi, center_x, center_y): """ :param x: x-coordinate :param y: y-coordinate :param coeff: float, amplitude of basis :param d_r: period of radial sinusoidal in units of angle :param d_phi: period of tangential sinusoidal in radian :param center_x: center of rotation for tangential basis :param center_y: center of rotation for tangential basis :return: f_x, f_y """ r, theta = param_util.cart2polar(x, y, center_x=center_x, center_y=center_y) dphi_ = d_phi / self._2_pi d_phi_dr = self._d_phi_r(r, d_r) * self._phi_theta(theta, dphi_) d_phi_d_theta = self._d_phi_theta(theta, dphi_) * self._phi_r(r, d_r) x_ = x - center_x y_ = y - center_y dr_dx = derivative_util.d_r_dx(x_, y_) dr_dy = derivative_util.d_r_dy(x_, y_) d_theta_dx = derivative_util.d_phi_dx(x_, y_) d_theta_dy = derivative_util.d_phi_dy(x_, y_) f_x = d_phi_dr * dr_dx + d_phi_d_theta * d_theta_dx f_y = d_phi_dr * dr_dy + d_phi_d_theta * d_theta_dy return f_x * coeff, f_y * coeff
def function(self, x, y, coeffs, beta, center_x=0, center_y=0): shapelets = self._createShapelet(coeffs) r, phi = param_util.cart2polar(x, y, center=np.array([center_x, center_y])) f_ = self._shapeletOutput(r, phi, beta, shapelets) return f_
def alpha_ext(self, x, y, kwargs_slice): """ deflection angle for (x,y) outside the elliptical slice :param kwargs_slice: dict, dictionary with the slice definition (a,b,psi,sigma_0) """ z = complex(x, y) r, phi = param_util.cart2polar(x, y) zb = z.conjugate() psi = kwargs_slice['psi'] a = kwargs_slice['a'] b = kwargs_slice['b'] f2 = a**2 - b**2 sig_0 = kwargs_slice['sigma_0'] median_op = False # when (x,y) is on one of the ellipse axis, there might be an issue when calculating the square root of # zb ** 2 * e2ipsi - f2. When the argument has an imaginary part ==0, having 0. or -0. may return different # answers. Therefore, for points (x,y) close to one axis, we take 3 points (one is x,y ; another one is a delta # away from this position, perpendicularly to the axis ; another one is at -delta perpendicularly away from # x,y). We calculate the function for each point and take the median. This avoids any singularity for points # along the axis but it slows down the function. if np.abs(np.sin(phi - psi)) <= 10 ** -10 \ or np.abs(np.sin(phi - psi - np.pi / 2.)) <= 10 ** -10: # very close to one of the ellipse axis median_op = True e2ipsi = c.exp(2j * psi) eipsi = c.exp(1j * psi) if median_op is True: eps = 10**-10 z_minus_eps = complex(r * np.cos(phi - eps), r * np.sin(phi - eps)) zb_minus_eps = z_minus_eps.conjugate() z_plus_eps = complex(r * np.cos(phi + eps), r * np.sin(phi + eps)) zb_plus_eps = z_plus_eps.conjugate() I_out_minus = 2 * a * b / f2 * ( zb_minus_eps * e2ipsi - eipsi * self.sign(zb_minus_eps * eipsi) * c.sqrt(zb_minus_eps**2 * e2ipsi - f2)) * sig_0 I_out_plus = 2 * a * b / f2 * ( zb_plus_eps * e2ipsi - eipsi * self.sign(zb_plus_eps * eipsi) * c.sqrt(zb_plus_eps**2 * e2ipsi - f2)) * sig_0 I_out_mid = 2 * a * b / f2 * (zb * e2ipsi - eipsi * self.sign( zb * eipsi) * c.sqrt(zb**2 * e2ipsi - f2)) * sig_0 I_out_real = np.median( [I_out_minus.real, I_out_plus.real, I_out_mid.real]) I_out_imag = np.median( [I_out_minus.imag, I_out_plus.imag, I_out_mid.imag]) else: I_out = 2 * a * b / f2 * (zb * e2ipsi - eipsi * self.sign( zb * eipsi) * c.sqrt(zb**2 * e2ipsi - f2)) * sig_0 I_out_real = I_out.real I_out_imag = I_out.imag # buf = zb ** 2 * e2ipsi - f2 ##problem with 0. and -0. giving different answers # if buf.real == 0: # buf = complex(0, buf.imag) # if buf.imag == 0: # buf = complex(buf.real, 0) return I_out_real, I_out_imag
def function(self, x, y, e1, e2, ra_0=0, dec_0=0): # change to polar coordinates psi_ext, gamma_ext = param_util.ellipticity2phi_gamma(e1, e2) r, phi = param_util.cart2polar(x - ra_0, y - dec_0) f_ = 1. / 2 * gamma_ext * r**2 * np.cos(2 * (phi - psi_ext)) #x_ = x - ra_0 #y_ = y - dec_0 #f_ = 1/2. * (e1 * x_ * x_ + 2 * e2 * x_ * y_ - e1 * y_ * y_) return f_
def derivatives(self, x, y, coeffs, beta, center_x=0, center_y=0): """ returns df/dx and df/dy of the function """ shapelets = self._createShapelet(coeffs) r, phi = param_util.cart2polar(x, y, center_x=center_x, center_y=center_y) alpha1_shapelets, alpha2_shapelets = self._alphaShapelets(shapelets, beta) f_x = self._shapeletOutput(r, phi, beta, alpha1_shapelets) f_y = self._shapeletOutput(r, phi, beta, alpha2_shapelets) return f_x, f_y
def _param_penalties(self, lens_args_tovary): penalty = 0 for pname in self.params_to_constrain.keys(): if pname == 'shear': index1 = self.param_class.routine.params_to_vary.index( 'shear_e1') index2 = self.param_class.routine.params_to_vary.index( 'shear_e2') shear, _ = cart2polar(lens_args_tovary[index1], lens_args_tovary[index2]) penalty += 0.5 * ( (shear - self.params_to_constrain['shear'][0]) * self.params_to_constrain['shear'][1]**-1)**2 elif pname == 'shear_pa': index1 = self.param_class.routine.params_to_vary.index( 'shear_e1') index2 = self.param_class.routine.params_to_vary.index( 'shear_e2') _, shear_pa = cart2polar(lens_args_tovary[index1], lens_args_tovary[index2]) penalty += 0.5 * ( (shear_pa - self.params_to_constrain['shear_pa'][0]) * self.params_to_constrain['shear_pa'][1]**-1)**2 else: index = self.param_class.routine.params_to_vary.index(pname) value = lens_args_tovary[index] target = self.params_to_constrain[pname][0] sigma = self.params_to_constrain[pname][1] penalty += 0.5 * ((value - target) * sigma**-1)**2 return penalty
def function(self, x, y, kappa_ext, ra_0=0, dec_0=0): """ lensing potential :param x: x-coordinate :param y: y-coordinate :param kappa_ext: external convergence :return: lensing potential """ theta, phi = param_util.cart2polar(x - ra_0, y - dec_0) f_ = 1./2 * kappa_ext * theta**2 return f_
def pot_ext(self, x, y, kwargs_slice): """ lensing potential for (x,y) outside the elliptical slice :param kwargs_slice: dict, dictionary with the slice definition (a,b,psi,sigma_0) """ z = complex(x, y) # zb = z.conjugate() psi = kwargs_slice['psi'] a = kwargs_slice['a'] b = kwargs_slice['b'] sig_0 = kwargs_slice['sigma_0'] r, phi = param_util.cart2polar(x, y) median_op = False # when (x,y) is on one of the ellipse axis, there might be an issue when calculating the square root of # z ** 2 * em2ipsi - f2. When the argument has an imaginary part ==0, having 0. or -0. may return different # answers. Therefore, for points (x,y) close to one axis, we take 3 points (one is x,y ; another one is a delta # away from this position, perpendicularly to the axis ; another one is at -delta perpendicularly away from # x,y). We calculate the function for each point and take the median. This avoids any singularity for points # along the axis but it slows down the function. if np.abs(np.sin(phi - psi)) <= 10 ** -10 \ or np.abs(np.sin(phi - psi - np.pi / 2.)) <= 10 ** -10: # very close to one of the ellipse axis median_op = True e = (a - b) / (a + b) f2 = a ** 2 - b ** 2 emipsi = c.exp(-1j * psi) em2ipsi = c.exp(-2j * psi) if median_op is True: eps = 10 ** -10 z_minus_eps = complex(r * np.cos(phi - eps), r * np.sin(phi - eps)) z_plus_eps = complex(r * np.cos(phi + eps), r * np.sin(phi + eps)) pot_ext_minus = (1 - e ** 2) / (4 * e) * (f2 * c.log( (self.sign(z_minus_eps * emipsi) * z_minus_eps * emipsi + c.sqrt(z_minus_eps ** 2 * em2ipsi - f2)) / 2.) - self.sign(z_minus_eps * emipsi) * z_minus_eps * emipsi * c.sqrt( z_minus_eps ** 2 * em2ipsi - f2) + z_minus_eps ** 2 * em2ipsi) * sig_0 pot_ext_plus = (1 - e ** 2) / (4 * e) * (f2 * c.log( (self.sign(z_plus_eps * emipsi) * z_plus_eps * emipsi + c.sqrt(z_plus_eps ** 2 * em2ipsi - f2)) / 2.) - self.sign(z_plus_eps * emipsi) * z_plus_eps * emipsi * c.sqrt( z_plus_eps ** 2 * em2ipsi - f2) + z_plus_eps ** 2 * em2ipsi) * sig_0 pot_ext_mid = (1 - e ** 2) / (4 * e) * ( f2 * c.log((self.sign(z * emipsi) * z * emipsi + c.sqrt(z ** 2 * em2ipsi - f2)) / 2.) - self.sign(z * emipsi) * z * emipsi * c.sqrt(z ** 2 * em2ipsi - f2) + z ** 2 * em2ipsi) * sig_0 pot_ext = np.median([pot_ext_minus.real, pot_ext_plus.real, pot_ext_mid.real]) else: pot_ext = ((1 - e ** 2) / (4 * e) * ( f2 * c.log((self.sign(z * emipsi) * z * emipsi + c.sqrt(z ** 2 * em2ipsi - f2)) / 2.) - self.sign(z * emipsi) * z * emipsi * c.sqrt(z ** 2 * em2ipsi - f2) + z ** 2 * em2ipsi) * sig_0).real return pot_ext
def function(x, y, gamma_ext, psi_ext, ra_0=0, dec_0=0): """ :param x: x-coordinate (angle) :param y: y0-coordinate (angle) :param gamma_ext: shear strength :param psi_ext: shear angle (radian) :param ra_0: x/ra position where shear deflection is 0 :param dec_0: y/dec position where shear deflection is 0 :return: """ # change to polar coordinate r, phi = param_util.cart2polar(x - ra_0, y - dec_0) f_ = 1. / 2 * gamma_ext * r**2 * np.cos(2 * (phi - psi_ext)) return f_
def function(self, x, y, m, a_m, phi_m, center_x=0, center_y=0): """ Lensing potential of multipole contribution (for 1 component with m>=2) This uses the same definitions as Xu et al.(2013) in Appendix B3 https://arxiv.org/pdf/1307.4220.pdf :param m: int, multipole order, m>=2 :param a_m: float, multipole strength :param phi_m: float, multipole orientation in radian :param center_x: x-position :param center_y: x-position :return: lensing potential """ r, phi = param_util.cart2polar(x, y, center_x=center_x, center_y=center_y) f_ = r*a_m /(1-m**2) * np.cos(m*(phi-phi_m)) return f_
def _dlambda_t_dt_analytic(x, y, theta_E, gamma, q, phi_G): # polar coordinates with respect to x-axis r, phi = param_util.cart2polar(x, y, center_x=0, center_y=0) epsilon = (1 - q**2) / (1 + q**2) # radial component in respect to rotation of deflector r_ = r * np.sqrt(1 - epsilon * np.cos(2 * (phi - phi_G))) # equivalent Einstein radius for elliptical mass definition theta_E_prim = np.sqrt(2 * q / (1 + q**2)) * theta_E dlambda_t_dr = _dlambda_t_dr_analytic(r_, theta_E_prim, gamma) dr_de_t = epsilon * np.sin( 2 * (phi - phi_G)) / np.sqrt(1 - epsilon * np.cos(2 * (phi - phi_G))) return dlambda_t_dr * dr_de_t, dlambda_t_dr
def hessian(self, x, y, coeffs, beta, 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 """ shapelets = self._createShapelet(coeffs) r, phi = param_util.cart2polar(x, y, center_x=center_x, center_y=center_y) kappa_shapelets=self._kappaShapelets(shapelets, beta) gamma1_shapelets, gamma2_shapelets=self._gammaShapelets(shapelets, beta) kappa_value=self._shapeletOutput(r, phi, beta, kappa_shapelets) gamma1_value=self._shapeletOutput(r, phi, beta, gamma1_shapelets) gamma2_value=self._shapeletOutput(r, phi, beta, gamma2_shapelets) f_xx = kappa_value + gamma1_value f_xy = gamma2_value f_yy = kappa_value - gamma1_value return f_xx, f_xy, f_xy, f_yy
def derivatives(self,x,y, m, a_m, phi_m, center_x=0, center_y=0): """ Deflection of a multipole contribution (for 1 component with m>=2) This uses the same definitions as Xu et al.(2013) in Appendix B3 https://arxiv.org/pdf/1307.4220.pdf :param m: int, multipole order, m>=2 :param a_m: float, multipole strength :param phi_m: float, multipole orientation in radian :param center_x: x-position :param center_y: x-position :return: deflection angles alpha_x, alpha_y """ r, phi = param_util.cart2polar(x, y, center_x=center_x, center_y=center_y) f_x = np.cos(phi)*a_m/(1-m**2) * np.cos(m*(phi-phi_m)) + np.sin(phi)*m*a_m/(1-m**2)*np.sin(m*(phi-phi_m)) f_y = np.sin(phi)*a_m/(1-m**2) * np.cos(m*(phi-phi_m)) - np.cos(phi)*m*a_m/(1-m**2)*np.sin(m*(phi-phi_m)) return f_x, f_y
def hessian(self, x, y, m, a_m, phi_m, center_x=0, center_y=0): """ Hessian of a multipole contribution (for 1 component with m>=2) This uses the same definitions as Xu et al.(2013) in Appendix B3 https://arxiv.org/pdf/1307.4220.pdf :param m: int, multipole order, m>=2 :param a_m: float, multipole strength :param phi_m: float, multipole orientation in radian :param center_x: x-position :param center_y: x-position :return: f_xx, f_xy, f_yx, f_yy """ r, phi = param_util.cart2polar(x, y, center_x=center_x, center_y=center_y) r = np.maximum(r, 0.000001) f_xx = 1./r * np.sin(phi)**2 * a_m *np.cos(m*(phi-phi_m)) f_yy = 1./r * np.cos(phi)**2 * a_m *np.cos(m*(phi-phi_m)) f_xy = -1./r * a_m * np.cos(phi) * np.sin(phi) * np.cos(m*(phi-phi_m)) return f_xx, f_xy, f_xy, f_yy
def function(self, x, y, amp, beta, n, m, complex_bool, center_x, center_y): """ :param x: x-coordinate, numpy array :param y: y-ccordinate, numpy array :param amp: amplitude normalization :param beta: shaplet scale :param n: order of polynomial :param m: roational invariance :param center_x: center of shapelet :param center_y: center of shapelet :return: amplitude of shapelet at possition (x, y) """ r, phi = param_util.cart2polar(x, y, center_x, center_y) if complex_bool is True: return amp * self._chi_n_m(r, beta, n, m) * np.exp(-1j * m * phi).imag else: return amp * self._chi_n_m(r, beta, n, m) * np.exp(-1j * m * phi).real
def _pre_calc(self, x, y, beta, n_max, center_x, center_y): """ :param x: :param y: :param beta: :param n_max: :param center_x: :param center_y: :return: """ L_list = [] # polar coordinates r, phi = param_util.cart2polar(x, y, center=np.array([center_x, center_y])) num_param = self.shapelets.num_param(n_max) # compute real and imaginary part of the complex angles in the range n_max theta_m_real_list, theta_m_imag_list = [], [] for i in range(n_max + 1): m = i exp_complex = np.exp(-1j * m * phi) theta_m_real_list.append(exp_complex.real) theta_m_imag_list.append(exp_complex.imag) # compute the Laguerre polynomials in n, m chi_n_m_list = [[0 for x in range(n_max + 1)] for y in range(n_max + 1)] for n in range(n_max + 1): for m in range(n + 1): if (n - m) % 2 == 0 or self._exponential is True: chi_n_m_list[n][m] = self.shapelets._chi_n_m(r, beta, n, m) # combine together the pre-computed components for index in range(num_param): n, m, complex_bool = self.shapelets.index2poly(index) if complex_bool is True: L_i = chi_n_m_list[n][m] * theta_m_imag_list[m] else: L_i = chi_n_m_list[n][m] * theta_m_real_list[m] L_list.append(L_i) return L_list
def function(self, x, y, coeff, d_r, d_phi, center_x, center_y): """ :param x: x-coordinate :param y: y-coordinate :param coeff: float, amplitude of basis :param d_r: period of radial sinusoidal in units of angle :param d_phi: period of tangential sinusoidal in radian :param center_x: center of rotation for tangential basis :param center_y: center of rotation for tangential basis :return: """ r, phi = param_util.cart2polar(x, y, center_x=center_x, center_y=center_y) dphi_ = d_phi / self._2_pi phi_r = self._phi_r(r, d_r) phi_theta = self._phi_theta(phi, dphi_) return phi_r * phi_theta * coeff
def hessian(self, x, y, coeff, d_r, d_phi, center_x, center_y): """ :param x: x-coordinate :param y: y-coordinate :param coeff: float, amplitude of basis :param d_r: period of radial sinusoidal in units of angle :param d_phi: period of tangential sinusoidal in radian :param center_x: center of rotation for tangential basis :param center_y: center of rotation for tangential basis :return: f_xx, f_yy, f_xy """ r, theta = param_util.cart2polar(x, y, center_x=center_x, center_y=center_y) dphi_ = d_phi / self._2_pi d_phi_dr = self._d_phi_r(r, d_r) * self._phi_theta(theta, dphi_) d_phi_dr2 = self._d_phi_r2(r, d_r) * self._phi_theta(theta, dphi_) d_phi_d_theta = self._d_phi_theta(theta, dphi_) * self._phi_r(r, d_r) d_phi_d_theta2 = self._d_phi_theta2(theta, dphi_) * self._phi_r(r, d_r) d_phi_dr_dtheta = self._d_phi_r(r, d_r) * self._d_phi_theta( theta, dphi_) x_ = x - center_x y_ = y - center_y dr_dx = derivative_util.d_r_dx(x_, y_) dr_dy = derivative_util.d_r_dy(x_, y_) d_theta_dx = derivative_util.d_phi_dx(x_, y_) d_theta_dy = derivative_util.d_phi_dy(x_, y_) dr_dxx = derivative_util.d_x_diffr_dx(x_, y_) dr_dxy = derivative_util.d_x_diffr_dy(x_, y_) dr_dyy = derivative_util.d_y_diffr_dy(x_, y_) d_theta_dxx = derivative_util.d_phi_dxx(x_, y_) d_theta_dyy = derivative_util.d_phi_dyy(x_, y_) d_theta_dxy = derivative_util.d_phi_dxy(x_, y_) f_xx = d_phi_dr2 * dr_dx**2 + d_phi_dr * dr_dxx + d_phi_d_theta2 * d_theta_dx**2 + d_phi_d_theta * d_theta_dxx + 2 * d_phi_dr_dtheta * dr_dx * d_theta_dx f_yy = d_phi_dr2 * dr_dy**2 + d_phi_dr * dr_dyy + d_phi_d_theta2 * d_theta_dy**2 + d_phi_d_theta * d_theta_dyy + 2 * d_phi_dr_dtheta * dr_dy * d_theta_dy f_xy = d_phi_dr2 * dr_dx * dr_dy + d_phi_dr * dr_dxy + d_phi_d_theta2 * d_theta_dx * d_theta_dy + d_phi_d_theta * d_theta_dxy + d_phi_dr_dtheta * dr_dx * d_theta_dy + d_phi_dr_dtheta * dr_dy * d_theta_dx return f_xx * coeff, f_xy * coeff, f_xy * coeff, f_yy * coeff
def function(x, y, gamma_ext, psi_ext, ra_0=0, dec_0=0): # change to polar coordinate r, phi = param_util.cart2polar(x - ra_0, y - dec_0) f_ = 1. / 2 * gamma_ext * r**2 * np.cos(2 * (phi - psi_ext)) return f_
def function(self, x, y, e1, e2, ra_0=0, dec_0=0): # change to polar coordinates psi_ext, gamma_ext = param_util.ellipticity2phi_gamma(e1, e2) theta, phi = param_util.cart2polar(x - ra_0, y - dec_0) f_ = 1. / 2 * gamma_ext * theta**2 * np.cos(2 * (phi - psi_ext)) return f_