def beamy(self, feed, freq): bpat = visibility.cylinder_beam(self._angpos, self.zenith, self.illumination_y * self.cylinder_width / self.wavelengths[freq]) bm = np.zeros_like(self._angpos) if self.ortho_pol: bm[:, 0] = bpat else: thatz, phatz = coord.thetaphi_plane_cart(self.zenith) thatp, phatp = coord.thetaphi_plane_cart(self._angpos) bm[:, 0] = np.dot(thatp, thatz) * bpat bm[:, 1] = np.dot(phatp, thatz) * bpat return bm
def polpattern(angpos, dipole): """Calculate the unit polarisation vectors at each position on the sphere for a dipole direction. Parameters ---------- angpos : np.ndarray[npoints, 2] The positions on the sphere to calculate at. dipole : np.ndarray[2 or 3] The unit vector for the dipole direction. If length is 2, assume in vector is in spherical polars, if 3 it's cartesian. Returns ------- vectors : np.ndarray[npoints, 2] Vector at each point in thetahat, phihat basis. """ if dipole.shape[0] == 2: dipole = coord.sph_to_cart(dipole) thatp, phatp = coord.thetaphi_plane_cart(angpos) polvec = np.zeros(angpos.shape[:-1] + (2,), dtype=angpos.dtype) # Calculate components by projecting into basis. polvec[..., 0] = np.dot(thatp, dipole) polvec[..., 1] = np.dot(phatp, dipole) # Normalise length to unity. coord.norm_vec2(polvec) return polvec
def beam_y(angpos, zenith, width, fwhm_e, fwhm_h, rot=[0.0, 0.0, 0.0]): """Beam amplitude across the sky for the Y dipole (points N). Using ExpTan model. Parameters ---------- angpos : np.ndarray[npoints, 2] Angular position on the sky. zenith : np.ndarray[2] Position of zenith in spherical polars. width : scalar Cylinder width in wavelengths. fwhm_e, fwhm_h Full with at half power in the E and H planes of the antenna. Returns ------- beam : np.ndarray[npoints, 2] Amplitude vector of beam at each point (in thetahat, phihat) """ # Reverse as thetahat points south that, phat = coord.thetaphi_plane_cart(zenith) xhat, yhat, zhat = rotate_ypr(rot, phat, -that, coord.sph_to_cart(zenith)) pvec = polpattern(angpos, yhat) amp = beam_amp(angpos, zenith, width, fwhm_h, fwhm_e, rot=rot) return amp[:, np.newaxis] * pvec
def polpattern(angpos, dipole): """Calculate the unit polarisation vectors at each position on the sphere for a dipole direction. Parameters ---------- angpos : np.ndarray[npoints, 2] The positions on the sphere to calculate at. dipole : np.ndarray[2 or 3] The unit vector for the dipole direction. If length is 2, assume in vector is in spherical polars, if 3 it's cartesian. Returns ------- vectors : np.ndarray[npoints, 2] Vector at each point in thetahat, phihat basis. """ if dipole.shape[0] == 2: dipole = coord.sph_to_cart(dipole) thatp, phatp = coord.thetaphi_plane_cart(angpos) polvec = np.zeros(angpos.shape[:-1] + (2,), dtype=angpos.dtype) # Calculate components by projecting into basis. polvec[..., 0] = np.dot(thatp, dipole) polvec[..., 1] = np.dot(phatp, dipole) # Normalise length to unity. polvec = polvec * (np.sum(polvec**2, axis=-1)**-0.5)[..., np.newaxis] return polvec
def beamy(self, feed, freq): bpat = visibility.cylinder_beam( self._angpos, self.zenith, self.illumination_y * self.cylinder_width / self.wavelengths[freq]) bm = np.zeros_like(self._angpos) if self.ortho_pol: bm[:, 0] = bpat else: thatz, phatz = coord.thetaphi_plane_cart(self.zenith) thatp, phatp = coord.thetaphi_plane_cart(self._angpos) bm[:, 0] = np.dot(thatp, thatz) * bpat bm[:, 1] = np.dot(phatp, thatz) * bpat return bm
def _setup_gridbeam_interpolation(self): # grid beam coordinates self._x_grid = self._primary_beam.phi[:] self._y_grid = self._primary_beam.theta[:] # celestial coordinates angpos = hputil.ang_positions(self._nside) x_cel = coord.sph_to_cart(angpos).T # rotate to telescope coords # first align y with N, then polar axis with NCP self._x_tel = cylbeam.rotate_ypr( (1.5 * np.pi, np.radians(90.0 - self.latitude), 0), *x_cel) # mask any pixels outside grid x_t, y_t, z_t = self._x_tel self._pix_mask = ((z_t > 0) & (np.abs(x_t) < np.abs(self._x_grid.max())) & (np.abs(y_t) < np.abs(self._y_grid.max()))) # pre-compute polarisation pattern # taken from driftscan zenith = np.array([np.pi / 2.0 - np.radians(self.latitude), 0.0]) that, phat = coord.thetaphi_plane_cart(zenith) xhat, yhat, zhat = cylbeam.rotate_ypr([-self.rotation_angle, 0.0, 0.0], phat, -that, coord.sph_to_cart(zenith)) self._pvec_x = cylbeam.polpattern(angpos, xhat) self._pvec_y = cylbeam.polpattern(angpos, yhat)
def pol_IQU(sph_arr, zenith, feed1, feed2): r"""The polarisation tensors at each point, projected onto two feeds. Parameters ---------- sph_arr : np.ndarray Angular positions (in spherical polar co-ordinates). zenith : np.ndarray The zenith vector in spherical polar-coordinates. feed1, feed2 : np.ndarray Unit vectors for the two feeds. Should be given in (u,v) coordinates. Returns ------- pI, pQ, pU : np.ndarray The projected polarisations at each angular position. Notes ----- For each position :math:`\hat{n}` in `sph_arr` calculate: .. math:: f_1^a f_2^b \mathcal{P}^X_{ab} where X is one of I, Q or U. The co-ordinate system defining the polarisation at each point is :math:`(\hat{\theta}, \hat{\phi})`. """ # Get theta, phi plane at each point. t_hat, p_hat = coord.thetaphi_plane_cart(sph_arr) # Get feed vectors in 3D Cartesian co-ordinates uhat, vhat = uv_plane_cart(zenith) f1c = feed1[0] * uhat + feed1[1] * vhat f2c = feed2[0] * uhat + feed2[1] * vhat # Project feed vectors into theta-phi plane. f1_t = np.inner(t_hat, f1c) f1_p = np.inner(p_hat, f1c) f2_t = np.inner(t_hat, f2c) f2_p = np.inner(p_hat, f2c) pI = 0.5 * (f1_t * f2_t + f1_p * f2_p) # I pQ = 0.5 * (f1_t * f2_t - f1_p * f2_p) # Q pU = 0.5 * (f1_t * f2_p + f1_p * f2_t) # U return pI, pQ, pU
def pol_IQU(sph_arr, zenith, feed1, feed2): r"""The polarisation tensors at each point, projected onto two feeds. Parameters ---------- sph_arr : np.ndarray Angular positions (in spherical polar co-ordinates). zenith : np.ndarray The zenith vector in spherical polar-coordinates. feed1, feed2 : np.ndarray Unit vectors for the two feeds. Should be given in (u,v) coordinates. Returns ------- pI, pQ, pU : np.ndarray The projected polarisations at each angular position. Notes ----- For each position :math:`\hat{n}` in `sph_arr` calculate: .. math:: f_1^a f_2^b \mathcal{P}^X_{ab} where X is one of I, Q or U. The co-ordinate system defining the polarisation at each point is :math:`(\hat{\theta}, \hat{\phi})`. """ # Get theta, phi plane at each point. t_hat, p_hat = coord.thetaphi_plane_cart(sph_arr) # Get feed vectors in 3D Cartesian co-ordinates uhat, vhat = uv_plane_cart(zenith) f1c = feed1[0] * uhat + feed1[1] * vhat f2c = feed2[0] * uhat + feed2[1] * vhat # Project feed vectors into theta-phi plane. f1_t = np.inner(t_hat, f1c) f1_p = np.inner(p_hat, f1c) f2_t = np.inner(t_hat, f2c) f2_p = np.inner(p_hat, f2c) pI = 0.5*(f1_t*f2_t + f1_p*f2_p) # I pQ = 0.5*(f1_t*f2_t - f1_p*f2_p) # Q pU = 0.5*(f1_t*f2_p + f1_p*f2_t) # U return pI, pQ, pU
def uv_plane_cart(zenith): r"""Fetch unit vectors in the UV plane. Parameters ---------- zenith : np.ndarray The zenith vector in spherical polar-coordinates. Returns ------- uhat, vhat : np.ndarray Unit vectors in the UV plane. `uhat` points East, and `vhat` points North. """ t_hat, phat = coord.thetaphi_plane_cart(zenith) return phat, -t_hat
def beam_amp(angpos, zenith, width, fwhm_x, fwhm_y, rot=[0.0, 0.0, 0.0]): """Beam amplitude across the sky. Parameters ---------- angpos : np.ndarray[npoints] Angular position on the sky. zenith : np.ndarray[2] Position of zenith on spherical polars. width : scalar Cylinder width in wavelengths. fwhm_x, fwhm_y : scalar Full with at half power in the x and y directions. rot : [yaw, pitch, roll] Rotation to apply to cylinder in yaw, pitch and roll from North. Returns ------- beam : np.ndarray[npoints] Amplitude of beam at each point. """ global _beam_pat_cache if _beam_pat_cache is None: _beam_pat_cache = cachetools.LRUCache(maxsize=100) that, phat = coord.thetaphi_plane_cart(zenith) xhat, yhat, zhat = rotate_ypr(rot, phat, -that, coord.sph_to_cart(zenith)) yplane = lambda t: beam_exptan(t, fwhm_y) # Get the diffracted beam pattern from the cache, or calculate it if it's not # present bpkey = (fwhm_x, width) if bpkey not in _beam_pat_cache: xplane = lambda t: beam_exptan(t, fwhm_x) _beam_pat_cache[bpkey] = fraunhofer_cylinder(xplane, width) beampat = _beam_pat_cache[bpkey] cvec = coord.sph_to_cart(angpos) horizon = (np.dot(cvec, coord.sph_to_cart(zenith)) > 0.0).astype(np.float64) ew_amp = beampat(np.dot(cvec, xhat)) ns_amp = yplane(np.dot(cvec, yhat)) return ew_amp * ns_amp * horizon
def beam_amp(angpos, zenith, width, fwhm_x, fwhm_y, rot=[0.0, 0.0, 0.0]): """Beam amplitude across the sky. Parameters ---------- angpos : np.ndarray[npoints] Angular position on the sky. zenith : np.ndarray[2] Position of zenin on spherical polars. width : scalar Cylinder width in wavelengths. fwhm_x, fwhm_y : scalar Full with at half power in the x and y directions. rot : [yaw, pitch, roll] Rotation to apply to cylinder in yaw, pitch and roll from North. Returns ------- beam : np.ndarray[npoints] Amplitude of beam at each point. """ that, phat = coord.thetaphi_plane_cart(zenith) xhat, yhat, zhat = rotate_ypr(rot, phat, -that, coord.sph_to_cart(zenith)) xplane = lambda t: beam_exptan(t, fwhm_x) yplane = lambda t: beam_exptan(t, fwhm_y) beampat = fraunhofer_cylinder(xplane, width) cvec = coord.sph_to_cart(angpos) horizon = (np.dot(cvec, coord.sph_to_cart(zenith)) > 0.0).astype( np.float64) ew_amp = beampat(np.dot(cvec, xhat)) ns_amp = yplane(np.arcsin(np.dot(cvec, yhat))) return ew_amp * ns_amp * horizon
def beam_amp(angpos, zenith, width, fwhm_x, fwhm_y, rot=[0.0, 0.0, 0.0]): """Beam amplitude across the sky. Parameters ---------- angpos : np.ndarray[npoints] Angular position on the sky. zenith : np.ndarray[2] Position of zenin on spherical polars. width : scalar Cylinder width in wavelengths. fwhm_x, fwhm_y : scalar Full with at half power in the x and y directions. rot : [yaw, pitch, roll] Rotation to apply to cylinder in yaw, pitch and roll from North. Returns ------- beam : np.ndarray[npoints] Amplitude of beam at each point. """ that, phat = coord.thetaphi_plane_cart(zenith) xhat, yhat, zhat = rotate_ypr(rot, phat, -that, coord.sph_to_cart(zenith)) xplane = lambda t: beam_exptan(t, fwhm_x) yplane = lambda t: beam_exptan(t, fwhm_y) beampat = fraunhofer_cylinder(xplane, width) cvec = coord.sph_to_cart(angpos) horizon = (np.dot(cvec, coord.sph_to_cart(zenith)) > 0.0).astype(np.float64) ew_amp = beampat(np.dot(cvec, xhat)) ns_amp = yplane(np.arcsin(np.dot(cvec, yhat))) return (ew_amp * ns_amp * horizon)