def apply(self, x, y): scale_matrix = np.array([[self.sxx, self.sxy], [self.sxy, self.syy]]) rot_matrix = rot2deg(self.rot_deg) ha, dec = xy2hadec(x, y, 0, 0) x1t, y1t = hadec2xy(ha, dec, self.dha, self.ddec) xy = scale_matrix.dot(rot_matrix.dot(np.array([x1t, y1t]))) return xy[0], xy[1]
def test_tancorr_fit(self): tcorr = TanCorr() tel_ha1 = 12. tel_dec1 = 80. npts = 24 x1 = 0.1 * np.random.uniform(size=npts) y1 = 0.1 * np.random.uniform(size=npts) ha, dec = xy2hadec(x1, y1, tel_ha1, tel_dec1) true_dha_arcsec = 3. true_ddec_arcsec = 1. tel_ha2 = tel_ha1 + true_dha_arcsec / 3600. tel_dec2 = tel_dec1 + true_ddec_arcsec / 3600. x2, y2 = hadec2xy(ha, dec, tel_ha2, tel_dec2) tcorr.fit(x1, y1, x2, y2) meas_dha_arcsec = tcorr.dha / cosd(tel_dec1) * 3600. meas_ddec_arcsec = tcorr.ddec * 3600. assert (np.abs(true_dha_arcsec - meas_dha_arcsec) < 0.01) assert (np.abs(true_ddec_arcsec - meas_ddec_arcsec) < 0.01)
def test_hadec2xy(self): cha = 12 cdec = 24 x1 = np.random.uniform(size=3) - 0.5 y1 = np.random.uniform(size=3) - 0.5 ha1, dec1 = radec2tan.xy2hadec(x1, y1, cha, cdec) x2, y2 = radec2tan.hadec2xy(ha1, dec1, cha, cdec) assert (np.all(np.abs(x1 - x2) < 1e-6)) assert (np.all(np.abs(y1 - y2) < 1e-6)) # check orientation x, y = radec2tan.hadec2xy(cha + 1, cdec, cha, cdec) assert (x > 0) x, y = radec2tan.hadec2xy(cha, cdec + 1, cha, cdec) assert (y > 0)
def _measure_fieldrot_deg(ha, dec, tel_ha, tel_dec, xfp_mm, yfp_mm): ok = (~(np.isnan(ha * dec * xfp_mm * yfp_mm))) & (xfp_mm**2 + yfp_mm**2 > 10**2) x2, y2 = hadec2xy(ha[ok], dec[ok], tel_ha, tel_dec) # rad return np.rad2deg( np.mean((yfp_mm[ok] * x2 - xfp_mm[ok] * y2) / np.sqrt( (xfp_mm[ok]**2 + yfp_mm[ok]**2) * (x2**2 + y2**2))))
def apply(self,x,y) : scale_matrix = np.array([[self.sxx,self.sxy],[self.sxy,self.syy]]) ca=np.cos(self.rot_deg/180*np.pi) sa=np.sin(self.rot_deg/180*np.pi) rot_matrix = np.array([[ca,-sa],[sa,ca]]) ha,dec = xy2hadec(x,y,0,0) x1t,y1t = hadec2xy(ha,dec,self.dha,self.ddec) xy=scale_matrix.dot(rot_matrix.dot(np.array([x1t,y1t]))) return xy[0],xy[1]
def apply_inverse(self, x, y): det = self.sxx * self.syy - self.sxy**2 scale_matrix = np.array([[self.syy, -self.sxy], [-self.sxy, self.sxx] ]) / det rot_matrix = rot2deg(-self.rot_deg) ha, dec = xy2hadec(x, y, 0, 0) x1t, y1t = hadec2xy(ha, dec, self.dha, self.ddec) xy = rot_matrix.dot(scale_matrix.dot(np.array([x1t, y1t]))) return xy[0], xy[1]
def apply_inverse(self,x,y) : det = self.sxx*self.syy - self.sxy**2 scale_matrix = np.array([[self.syy,-self.sxy],[-self.sxy,self.sxx]])/det ca=np.cos(self.rot_deg/180*np.pi) sa=np.sin(self.rot_deg/180*np.pi) rot_matrix = np.array([[ca,sa],[-sa,ca]]) ha,dec = xy2hadec(x,y,0,0) x1t,y1t = hadec2xy(ha,dec,self.dha,self.ddec) xy=rot_matrix.dot(scale_matrix.dot(np.array([x1t,y1t]))) return xy[0],xy[1]
def compute_fieldrot(self) : # cross of side length 1 degree in tangent plane phi = np.arange(4)*np.pi/2. x1 = np.append(0.,np.pi/180.*np.cos(phi)) y1 = np.append(0.,np.pi/180.*np.sin(phi)) # convert to sky xfp,yfp = tan2fp(x1,y1,self.adc1,self.adc2) ra,dec = self.fp2radec(xfp,yfp) # vanilla transformation from ha,dec to tangent plane ha = self.lst - ra x2,y2 = hadec2xy(ha,dec,ha[0],dec[0]) return 180./np.pi*np.mean((y1[1:]*x2[1:]-x1[1:]*y2[1:])/np.sqrt((x1[1:]**2+y1[1:]**2)*(x2[1:]**2+y2[1:]**2)))
def test_polar_misalignment(self): # circle of coordinates in FP phi = np.linspace(0, np.pi, 4) theta = 1. / 180 * np.pi x1 = np.sin(theta) * np.cos(phi) y1 = np.sin(theta) * np.sin(phi) # pointings for cha in [60]: for cdec in [80]: ha1, dec1 = radec2tan.xy2hadec(x1, y1, cha, cdec) # apply rotation M = radec2tan.compute_polar_misalignment_rotation_matrix( me_arcsec=radec2tan.ME_ARCSEC, ma_arcsec=radec2tan.MA_ARCSEC) ha2, dec2 = radec2tan.getLONLAT( M.dot(radec2tan.getXYZ(ha1, dec1))) # back to FP coordinates cha2, cdec2 = radec2tan.getLONLAT( M.dot(radec2tan.getXYZ(cha, cdec))) x2, y2 = radec2tan.hadec2xy(ha2, dec2, cha2, cdec2) # measure field rotation angle x1 -= np.mean(x1) y1 -= np.mean(y1) x2 -= np.mean(x2) y2 -= np.mean(y2) angle = np.mean( radec2tan.arcsind((x1 * y2 - x2 * y1) / np.sqrt( (x1**2 + y1**2) * (x2**2 + y2**2)))) print( "at HA= {} deg and Dec = {} deg, the mean field rotation angle= {:4.3f} deg " .format(cha, cdec, angle))
def fit(self, x1, y1, x2, y2) : """ Adjust tranformation from focal plane x1,y1 to x2,y2 Args: x1,y1,x2,y2 : 1D np.arrays of coordinates in tangent plane Returns: None """ assert((x1.shape == y1.shape)&(x2.shape == y2.shape)&(x1.shape == x2.shape)) # first ajust an offset using spherical coordinates # assume fiducial pointing of telescope to convert # tangent plane coords to angles self.dha=0. self.ddec=0. x1t=x1+0. y1t=y1+0. ha,dec = xy2hadec(x1,y1,0,0) for i in range(4) : x1t,y1t = hadec2xy(ha,dec,self.dha,self.ddec) dx = np.mean(x2-x1t) dy = np.mean(y2-y1t) #print(i,dx,dy) self.dha -= dx/np.cos(self.ddec)*180./np.pi self.ddec -= dy*180./np.pi x1t,y1t = hadec2xy(ha,dec,self.dha,self.ddec) # now fit simultaneously extra offset, rotation, scale self.nstars=x1t.size H=np.zeros((3,self.nstars)) H[0] = 1. H[1] = x1t H[2] = y1t A = H.dot(H.T) Ai = np.linalg.inv(A) ax = Ai.dot(np.sum(x2*H,axis=1)) x2p = ax[0] + ax[1]*x1t + ax[2]*y1t # x2p = predicted x2 from x1t (=x1 after telescope pointing offset) ay = Ai.dot(np.sum(y2*H,axis=1)) y2p = ay[0] + ay[1]*x1t + ay[2]*y1t # y2p = predicted y2 from y1t # tangent plane coordinates are in radians self.rms_arcsec = np.sqrt( np.mean( (x2-x2p)**2 + (y2-y2p)**2 ) )*(180*3600)/np.pi # interpret this back into telescope pointing offset, field rotation, dilatation # pointing offset # increasing gaia stars x means telescope is more to the left so tel_ha should be decreased # increasing gaia stars y means telescope is more to the bottom so tel_dec should be decreased # tangent plane coordinates are in rad ddha = -ax[0]*180./np.pi dddec = -ay[0]*180./np.pi self.dha += ddha self.ddec += dddec # dilatation and rotation # |ax1 ax2| |sxx sxy| |ca -sa| # |ay1 ay2|=|syx syy|*|sa ca| # ax1=sxx*ca+sxy*sa ; ax2=-sxx*sa+sxy*ca # ay1=syx*ca+syy*sa ; ay2=-syx*sa+syy*ca # ax1+ay2 = (sxx+syy)*ca # ay1-ax2 = (sxx+syy)*sa sxx_p_syy = np.sqrt( (ax[1]+ay[2])**2+(ay[1]-ax[2])**2 ) sa=(ay[1]-ax[2])/sxx_p_syy ca=(ax[1]+ay[2])/sxx_p_syy self.rot_deg = np.arctan2(sa,ca)*180/np.pi sxy = sa*ax[1]+ca*ay[1] - sxx_p_syy*ca*sa sxx =(ax[1]-sxy*sa)/ca syy = (ay[1]-sxy*ca)/sa self.sxx = sxx self.syy = syy self.sxy = sxy