def points(self,npoints): """ compute arrays of npoints equally spaced intermediate points along the great circle. input parameter npoints is the number of points to compute. Returns lons, lats (lists with longitudes and latitudes of intermediate points in degrees). For example npoints=10 will return arrays lons,lats of 10 equally spaced points along the great circle. """ # can't do it if endpoints of great circle are antipodal, since # route is undefined. if self.antipodal: raise ValueError,'cannot compute intermediate points on a great circle whose endpoints are antipodal' d = self.distance delta = 1.0/(npoints-1) f = delta*N.arange(npoints) lat1 = self.lat1 lat2 = self.lat2 lon1 = self.lon1 lon2 = self.lon2 A = N.sin((1-f)*d)/math.sin(d) B = N.sin(f*d)/math.sin(d) x = A*math.cos(lat1)*math.cos(lon1)+B*math.cos(lat2)*math.cos(lon2) y = A*math.cos(lat1)*math.sin(lon1)+B*math.cos(lat2)*math.sin(lon2) z = A*math.sin(lat1) +B*math.sin(lat2) lats=N.arctan2(z,N.sqrt(x**2+y**2)) lons=N.arctan2(y,x) lons = map(math.degrees,lons.tolist()) lats = map(math.degrees,lats.tolist()) return lons,lats
def points(self,npoints): """ compute arrays of npoints equally spaced intermediate points along the great circle. input parameter npoints is the number of points to compute. Returns lons, lats (lists with longitudes and latitudes of intermediate points in degrees). For example npoints=10 will return arrays lons,lats of 10 equally spaced points along the great circle. """ # must ask for at least 2 points. if npoints <= 1: raise ValueError,'npoints must be greater than 1' elif npoints == 2: return [math.degrees(self.lon1),math.degrees(self.lon2)],[math.degrees(self.lat1),math.degrees(self.lat2)] # can't do it if endpoints are antipodal, since # route is undefined. if self.antipodal: raise ValueError,'cannot compute intermediate points on a great circle whose endpoints are antipodal' d = self.gcarclen delta = 1.0/(npoints-1) f = delta*N.arange(npoints) # f=0 is point 1, f=1 is point 2. incdist = self.distance/(npoints-1) lat1 = self.lat1 lat2 = self.lat2 lon1 = self.lon1 lon2 = self.lon2 # perfect sphere, use great circle formula if self.f == 0.: A = N.sin((1-f)*d)/math.sin(d) B = N.sin(f*d)/math.sin(d) x = A*math.cos(lat1)*math.cos(lon1)+B*math.cos(lat2)*math.cos(lon2) y = A*math.cos(lat1)*math.sin(lon1)+B*math.cos(lat2)*math.sin(lon2) z = A*math.sin(lat1) +B*math.sin(lat2) lats=N.arctan2(z,N.sqrt(x**2+y**2)) lons=N.arctan2(y,x) lons = map(math.degrees,lons.tolist()) lats = map(math.degrees,lats.tolist()) # use ellipsoid formulas else: latpt = self.lat1 lonpt = self.lon1 azimuth = self.azimuth12 lons = [math.degrees(lonpt)] lats = [math.degrees(latpt)] for n in range(npoints-2): latptnew,lonptnew,alpha21=vinc_pt(self.f,self.a,latpt,lonpt,azimuth,incdist) d,azimuth,a21=vinc_dist(self.f,self.a,latptnew,lonptnew,lat2,lon2) lats.append(math.degrees(latptnew)) lons.append(math.degrees(lonptnew)) latpt = latptnew; lonpt = lonptnew lons.append(math.degrees(self.lon2)) lats.append(math.degrees(self.lat2)) return lons,lats
def rd2xy(self, skypos, hour=no): """ This method would use the WCS keywords to compute the XY position from a given RA/Dec tuple (in deg). NOTE: Investigate how to let this function accept arrays as well as single positions. WJH 27Mar03 """ if self.ctype1.find('TAN') < 0 or self.ctype2.find('TAN') < 0: print 'RD2XY only supported for TAN projections.' raise TypeError det = self.cd11 * self.cd22 - self.cd12 * self.cd21 if det == 0.0: raise ArithmeticError, "singular CD matrix!" cdinv11 = self.cd22 / det cdinv12 = -self.cd12 / det cdinv21 = -self.cd21 / det cdinv22 = self.cd11 / det # translate (ra, dec) to (x, y) ra0 = DEGTORAD(self.crval1) dec0 = DEGTORAD(self.crval2) if hour: skypos[0] = skypos[0] * 15. ra = DEGTORAD(skypos[0]) dec = DEGTORAD(skypos[1]) bottom = float( N.sin(dec) * N.sin(dec0) + N.cos(dec) * N.cos(dec0) * N.cos(ra - ra0)) if bottom == 0.0: raise ArithmeticError, "Unreasonable RA/Dec range!" xi = RADTODEG((N.cos(dec) * N.sin(ra - ra0) / bottom)) eta = RADTODEG((N.sin(dec) * N.cos(dec0) - N.cos(dec) * N.sin(dec0) * N.cos(ra - ra0)) / bottom) x = cdinv11 * xi + cdinv12 * eta + self.crpix1 y = cdinv21 * xi + cdinv22 * eta + self.crpix2 return x, y
def xy2rd(self, pos): """ This method would apply the WCS keywords to a position to generate a new sky position. The algorithm comes directly from 'imgtools.xy2rd' translate (x,y) to (ra, dec) """ if self.ctype1.find('TAN') < 0 or self.ctype2.find('TAN') < 0: print 'XY2RD only supported for TAN projections.' raise TypeError if isinstance(pos, N.NumArray): # If we are working with an array of positions, # point to just X and Y values posx = pos[:, 0] posy = pos[:, 1] else: # Otherwise, we are working with a single X,Y tuple posx = pos[0] posy = pos[1] xi = self.cd11 * (posx - self.crpix1) + self.cd12 * (posy - self.crpix2) eta = self.cd21 * (posx - self.crpix1) + self.cd22 * (posy - self.crpix2) xi = DEGTORAD(xi) eta = DEGTORAD(eta) ra0 = DEGTORAD(self.crval1) dec0 = DEGTORAD(self.crval2) ra = N.arctan((xi / (N.cos(dec0) - eta * N.sin(dec0)))) + ra0 dec = N.arctan( ((eta * N.cos(dec0) + N.sin(dec0)) / (N.sqrt((N.cos(dec0) - eta * N.sin(dec0))**2 + xi**2)))) ra = RADTODEG(ra) dec = RADTODEG(dec) ra = DIVMOD(ra, 360.) # Otherwise, just return the RA,Dec tuple. return ra, dec
def rd2xy(self,skypos,hour=no): """ This method would use the WCS keywords to compute the XY position from a given RA/Dec tuple (in deg). NOTE: Investigate how to let this function accept arrays as well as single positions. WJH 27Mar03 """ if self.ctype1.find('TAN') < 0 or self.ctype2.find('TAN') < 0: print 'RD2XY only supported for TAN projections.' raise TypeError det = self.cd11*self.cd22 - self.cd12*self.cd21 if det == 0.0: raise ArithmeticError,"singular CD matrix!" cdinv11 = self.cd22 / det cdinv12 = -self.cd12 / det cdinv21 = -self.cd21 / det cdinv22 = self.cd11 / det # translate (ra, dec) to (x, y) ra0 = DEGTORAD(self.crval1) dec0 = DEGTORAD(self.crval2) if hour: skypos[0] = skypos[0] * 15. ra = DEGTORAD(skypos[0]) dec = DEGTORAD(skypos[1]) bottom = float(N.sin(dec)*N.sin(dec0) + N.cos(dec)*N.cos(dec0)*N.cos(ra-ra0)) if bottom == 0.0: raise ArithmeticError,"Unreasonable RA/Dec range!" xi = RADTODEG((N.cos(dec) * N.sin(ra-ra0) / bottom)) eta = RADTODEG((N.sin(dec)*N.cos(dec0) - N.cos(dec)*N.sin(dec0)*N.cos(ra-ra0)) / bottom) x = cdinv11 * xi + cdinv12 * eta + self.crpix1 y = cdinv21 * xi + cdinv22 * eta + self.crpix2 return x,y
def getSineWave(freq, samplecount=320): """ Generate a sine wave of frequency 'freq'. The samples are generated at 8khz. The first 'samplecount' samples will be returned. """ from numarray import sin, arange from math import pi sine = sin(arange(HZ)/(HZ/freq) * 2.0 * pi) sine = sine[:samplecount] return sine
def xy2rd(filename, x,y,hdu = -1, hms = 0, verbose = 0): from numarray import sin,cos,arctan2,sqrt def degtorad(num): return num/180.0*numarray.pi def radtodeg(num): return num/numarray.pi * 180.0 def degtoHMS(num): mmm = int((num-int(num))*60.0) sss = ((num-int(num))*60.0-mmm)*60.0 num = `int(num)`+":"+ `mmm`+":"+`sss` return num keys = ["CRPIX1","CRPIX2","CRVAL1","CRVAL2","CD1_1","CD1_2","CD2_1","CD2_2"] CD = read_keys(filename,keys,hdu) crpix = numarray.zeros((2),numarray.Float) cd = numarray.zeros((2,2),numarray.Float) crpix[0] = CD['CRPIX1'][0] crpix[1] = CD['CRPIX2'][0] ra0 = CD['CRVAL1'][0] dec0 = CD['CRVAL2'][0] cd[0,0] = CD['CD1_1'][0] cd[0,1] = CD['CD1_2'][0] cd[1,0] = CD['CD2_1'][0] cd[1,1] = CD['CD2_2'][0] xi = cd[0, 0] * (x - crpix[0]) + cd[0, 1] * (y - crpix[1]) eta = cd[1, 0] * (x - crpix[0]) + cd[1, 1] * (y - crpix[1]) xi = degtorad(xi) eta = degtorad(eta) ra0 = degtorad(ra0) dec0 = degtorad(dec0) ra = arctan2(xi,cos(dec0)-eta*sin(dec0)) + ra0 dec = arctan2(eta*cos(dec0)+sin(dec0),sqrt((cos(dec0)-eta*sin(dec0))**2 + xi**2)) ra = radtodeg(ra)# % 360.0 # if ra < 0: ra = ra + 360.0 dec = radtodeg(dec) if (hms): return degtoHMS(ra/15.0),degtoHMS(dec) else: return ra,dec
def rd2xy(filename,ra,dec,verbose=0,hdu=-1,hour=0): from numarray import sin,cos,arctan2,sqrt def degtorad(num): return num/180.0*numarray.pi def radtodeg(num): return num/numarray.pi * 180.0 keys = ["CRPIX1","CRPIX2","CRVAL1","CRVAL2","CD1_1","CD1_2","CD2_1","CD2_2"] CD = read_keys(filename,keys,hdu) crpix = numarray.zeros((2),numarray.Float) cd = numarray.zeros((2,2),numarray.Float) cdinv = numarray.zeros((2,2),numarray.Float) crpix[0] = CD['CRPIX1'][0] crpix[1] = CD['CRPIX2'][0] ra0 = CD['CRVAL1'][0] dec0 = CD['CRVAL2'][0] cd[0,0] = CD['CD1_1'][0] cd[0,1] = CD['CD1_2'][0] cd[1,0] = CD['CD2_1'][0] cd[1,1] = CD['CD2_2'][0] det = cd[0,0]*cd[1,1] - cd[0,1]*cd[1,0] if det == 0: raise SingularMatrix cdinv[0,0] = cd[1,1] / det cdinv[0,1] = -cd[0,1] / det cdinv[1,0] = -cd[1,0] / det cdinv[1,1] = cd[0,0] / det print det,cdinv ra0 = degtorad(ra0) dec0 = degtorad(dec0) if hour: ra=ra*15.0 ra = degtorad(ra) dec = degtorad(dec) bottom = sin(dec)*sin(dec0) + cos(dec)*cos(dec0)*cos(ra-ra0) if bottom == 0: raise InvalidRaDecRange xi = cos(dec) * sin(ra-ra0) / bottom eta = (sin(dec)*cos(dec0) - cos(dec)*sin(dec0)*cos(ra-ra0)) / bottom xi = radtodeg(xi) eta = radtodeg(eta) x = cdinv[0, 0] * xi + cdinv[0, 1] * eta + crpix[0] y = cdinv[1, 0] * xi + cdinv[1, 1] * eta + crpix[1] return x,y
def xy2rd(self,pos): """ This method would apply the WCS keywords to a position to generate a new sky position. The algorithm comes directly from 'imgtools.xy2rd' translate (x,y) to (ra, dec) """ if self.ctype1.find('TAN') < 0 or self.ctype2.find('TAN') < 0: print 'XY2RD only supported for TAN projections.' raise TypeError if isinstance(pos,N.NumArray): # If we are working with an array of positions, # point to just X and Y values posx = pos[:,0] posy = pos[:,1] else: # Otherwise, we are working with a single X,Y tuple posx = pos[0] posy = pos[1] xi = self.cd11 * (posx - self.crpix1) + self.cd12 * (posy - self.crpix2) eta = self.cd21 * (posx - self.crpix1) + self.cd22 * (posy - self.crpix2) xi = DEGTORAD(xi) eta = DEGTORAD(eta) ra0 = DEGTORAD(self.crval1) dec0 = DEGTORAD(self.crval2) ra = N.arctan((xi / (N.cos(dec0)-eta*N.sin(dec0)))) + ra0 dec = N.arctan( ((eta*N.cos(dec0)+N.sin(dec0)) / (N.sqrt((N.cos(dec0)-eta*N.sin(dec0))**2 + xi**2))) ) ra = RADTODEG(ra) dec = RADTODEG(dec) ra = DIVMOD(ra, 360.) # Otherwise, just return the RA,Dec tuple. return ra,dec
def psf_select(alpha_j, delta_j): distance = 9999.0 psffile = 'test.fits' psflist = c.psflist r = 3.14159265 / 180.0 for element in psflist: p=pyfits.open(element) header = p[0].header if (header.has_key('RA_TARG')): ra = header['RA_TARG'] if (header.has_key('DEC_TARG')): dec= header['DEC_TARG'] p.close() # d = sqrt((ra - alpha_j) ** 2.0 + (dec - delta_j) ** 2.0) d = n.arccos(n.cos((90.0 - delta_j) * r) * n.cos((90.0 - dec) *\ r) + n.sin((90.0 - delta_j) * r) * n.sin((90.0 - dec) * r) * \ n.cos((alpha_j - ra) * r)) if(d < distance): psffile = element distance = d return psffile, distance
def points(self, npoints): """ compute arrays of npoints equally spaced intermediate points along the great circle. input parameter npoints is the number of points to compute. Returns lons, lats (lists with longitudes and latitudes of intermediate points in degrees). For example npoints=10 will return arrays lons,lats of 10 equally spaced points along the great circle. """ # can't do it if endpoints of great circle are antipodal, since # route is undefined. if self.antipodal: raise ValueError, 'cannot compute intermediate points on a great circle whose endpoints are antipodal' d = self.distance delta = 1.0 / (npoints - 1) f = delta * N.arange(npoints) lat1 = self.lat1 lat2 = self.lat2 lon1 = self.lon1 lon2 = self.lon2 A = N.sin((1 - f) * d) / math.sin(d) B = N.sin(f * d) / math.sin(d) x = A * math.cos(lat1) * math.cos(lon1) + B * math.cos( lat2) * math.cos(lon2) y = A * math.cos(lat1) * math.sin(lon1) + B * math.cos( lat2) * math.sin(lon2) z = A * math.sin(lat1) + B * math.sin(lat2) lats = N.arctan2(z, N.sqrt(x**2 + y**2)) lons = N.arctan2(y, x) lons = map(math.degrees, lons.tolist()) lats = map(math.degrees, lats.tolist()) return lons, lats
def mask(clus_id, line_s): imagefile = c.imagefile sex_cata = c.sex_cata clus_cata = c.out_cata threshold = c.threshold thresh_area = c.thresh_area size = c.size mask_reg = c.mask_reg x = n.reshape(n.arange(size*size),(size,size)) % size x = x.astype(n.Float32) y = n.reshape(n.arange(size*size),(size,size)) / size y = y.astype(n.Float32) values = line_s.split() mask_file = 'ell_mask_' + str(imagefile)[:6] + '_' + str(clus_id) + '.fits' xcntr_o = float(values[1]) #x center of the object ycntr_o = float(values[2]) #y center of the object xcntr = size / 2.0 + 1.0 + xcntr_o - int(xcntr_o) ycntr = size / 2.0 + 1.0 + ycntr_o - int(ycntr_o) mag = float(values[7]) #Magnitude radius = float(values[9]) #Half light radius mag_zero = c.mag_zero #magnitude zero point sky = float(values[10]) #sky pos_ang = float(values[11]) - 90.0 #position angle axis_rat = 1.0 / float(values[12]) #axis ration b/a major_axis = float(values[14]) #major axis of the object z = n.zeros((size,size)) for line_j in open(sex_cata,'r'): try: values = line_j.split() xcntr_n = float(values[1]) #x center of the neighbour ycntr_n = float(values[2]) #y center of the neighbour mag = float(values[7]) #Magnitude radius = float(values[9]) #Half light radius sky = float(values[10]) #sky pos_ang = float(values[11]) #position angle axis_rat = 1.0/float(values[12]) #axis ration b/a si = n.sin(pos_ang * n.pi / 180.0) co = n.cos(pos_ang * n.pi / 180.0) area = float(values[13]) maj_axis = float(values[14])#major axis of neighbour eg = 1.0 - axis_rat one_minus_eg_sq = (1.0-eg)**2.0 if(abs(xcntr_n - xcntr_o) < size/2.0 and \ abs(ycntr_n - ycntr_o) < size/2.0 and \ xcntr_n != xcntr_o and ycntr_n != ycntr_o): if((xcntr_o - xcntr_n) < 0): xn = xcntr + abs(xcntr_n - xcntr_o) if((ycntr_o - ycntr_n) < 0): yn = ycntr + abs(ycntr_n - ycntr_o) if((xcntr_o - xcntr_n) > 0): xn = xcntr - (xcntr_o -xcntr_n) if((ycntr_o - ycntr_n) > 0): yn = ycntr - (ycntr_o -ycntr_n) tx = (x - xn + 0.5) * co + (y - yn + 0.5) * si ty = (xn - 0.5 -x) * si + (y - yn + 0.5) * co R = n.sqrt(tx**2.0 + ty**2.0 / one_minus_eg_sq) z[n.where(R<=mask_reg*maj_axis)] = 1 except: i=1 hdu = pyfits.PrimaryHDU(z.astype(n.Float32)) hdu.writeto(mask_file)
def points(self, npoints): """ compute arrays of npoints equally spaced intermediate points along the great circle. input parameter npoints is the number of points to compute. Returns lons, lats (lists with longitudes and latitudes of intermediate points in degrees). For example npoints=10 will return arrays lons,lats of 10 equally spaced points along the great circle. """ # must ask for at least 2 points. if npoints <= 1: raise ValueError, 'npoints must be greater than 1' elif npoints == 2: return [math.degrees(self.lon1), math.degrees(self.lon2) ], [math.degrees(self.lat1), math.degrees(self.lat2)] # can't do it if endpoints are antipodal, since # route is undefined. if self.antipodal: raise ValueError, 'cannot compute intermediate points on a great circle whose endpoints are antipodal' d = self.gcarclen delta = 1.0 / (npoints - 1) f = delta * N.arange(npoints) # f=0 is point 1, f=1 is point 2. incdist = self.distance / (npoints - 1) lat1 = self.lat1 lat2 = self.lat2 lon1 = self.lon1 lon2 = self.lon2 # perfect sphere, use great circle formula if self.f == 0.: A = N.sin((1 - f) * d) / math.sin(d) B = N.sin(f * d) / math.sin(d) x = A * math.cos(lat1) * math.cos(lon1) + B * math.cos( lat2) * math.cos(lon2) y = A * math.cos(lat1) * math.sin(lon1) + B * math.cos( lat2) * math.sin(lon2) z = A * math.sin(lat1) + B * math.sin(lat2) lats = N.arctan2(z, N.sqrt(x**2 + y**2)) lons = N.arctan2(y, x) lons = map(math.degrees, lons.tolist()) lats = map(math.degrees, lats.tolist()) # use ellipsoid formulas else: latpt = self.lat1 lonpt = self.lon1 azimuth = self.azimuth12 lons = [math.degrees(lonpt)] lats = [math.degrees(latpt)] for n in range(npoints - 2): latptnew, lonptnew, alpha21 = vinc_pt(self.f, self.a, latpt, lonpt, azimuth, incdist) d, azimuth, a21 = vinc_dist(self.f, self.a, latptnew, lonptnew, lat2, lon2) lats.append(math.degrees(latptnew)) lons.append(math.degrees(lonptnew)) latpt = latptnew lonpt = lonptnew lons.append(math.degrees(self.lon2)) lats.append(math.degrees(self.lat2)) return lons, lats
def HookModel( elevs , c , fsin , fcos ): return c+ fsin * numarray.sin(elevs * math.pi / 180 ) + fcos * numarray.cos(elevs * math.pi / 180 )
def recenter(self): """ Reset the reference position values to correspond to the center of the reference frame. Algorithm used here developed by Colin Cox - 27-Jan-2004. """ if self.ctype1.find('TAN') < 0 or self.ctype2.find('TAN') < 0: print 'WCS.recenter() only supported for TAN projections.' raise TypeError # Check to see if WCS is already centered... if self.crpix1 == self.naxis1 / 2. and self.crpix2 == self.naxis2 / 2.: # No recentering necessary... return without changing WCS. return # This offset aligns the WCS to the center of the pixel, in accordance # with the 'align=center' option used by 'drizzle'. #_drz_off = -0.5 _drz_off = 0. _cen = (self.naxis1 / 2. + _drz_off, self.naxis2 / 2. + _drz_off) # Compute the RA and Dec for center pixel _cenrd = self.xy2rd(_cen) _cd = N.array([[self.cd11, self.cd12], [self.cd21, self.cd22]], type=N.Float64) _ra0 = DEGTORAD(self.crval1) _dec0 = DEGTORAD(self.crval2) _ra = DEGTORAD(_cenrd[0]) _dec = DEGTORAD(_cenrd[1]) # Set up some terms for use in the final result _dx = self.naxis1 / 2. - self.crpix1 _dy = self.naxis2 / 2. - self.crpix2 _dE, _dN = DEGTORAD(N.dot(_cd, (_dx, _dy))) _dE_dN = 1 + N.power(_dE, 2) + N.power(_dN, 2) _cosdec = N.cos(_dec) _sindec = N.sin(_dec) _cosdec0 = N.cos(_dec0) _sindec0 = N.sin(_dec0) _n1 = N.power(_cosdec, 2) + _dE * _dE + _dN * _dN * N.power(_sindec, 2) _dra_dE = (_cosdec0 - _dN * _sindec0) / _n1 _dra_dN = _dE * _sindec0 / _n1 _ddec_dE = -_dE * N.tan(_dec) / _dE_dN _ddec_dN = (1 / _cosdec) * ((_cosdec0 / N.sqrt(_dE_dN)) - (_dN * N.sin(_dec) / _dE_dN)) # Compute new CD matrix values now... _cd11n = _cosdec * (self.cd11 * _dra_dE + self.cd21 * _dra_dN) _cd12n = _cosdec * (self.cd12 * _dra_dE + self.cd22 * _dra_dN) _cd21n = self.cd11 * _ddec_dE + self.cd21 * _ddec_dN _cd22n = self.cd12 * _ddec_dE + self.cd22 * _ddec_dN _new_orient = RADTODEG(N.arctan2(_cd12n, _cd22n)) # Update the values now... self.crpix1 = _cen[0] self.crpix2 = _cen[1] self.crval1 = RADTODEG(_ra) self.crval2 = RADTODEG(_dec) # Keep the same plate scale, only change the orientation self.rotateCD(_new_orient) # These would update the CD matrix with the new rotation # ALONG with the new plate scale which we do not want. self.cd11 = _cd11n self.cd12 = _cd12n self.cd21 = _cd21n self.cd22 = _cd22n
def recenter(self): """ Reset the reference position values to correspond to the center of the reference frame. Algorithm used here developed by Colin Cox - 27-Jan-2004. """ if self.ctype1.find('TAN') < 0 or self.ctype2.find('TAN') < 0: print 'WCS.recenter() only supported for TAN projections.' raise TypeError # Check to see if WCS is already centered... if self.crpix1 == self.naxis1/2. and self.crpix2 == self.naxis2/2.: # No recentering necessary... return without changing WCS. return # This offset aligns the WCS to the center of the pixel, in accordance # with the 'align=center' option used by 'drizzle'. #_drz_off = -0.5 _drz_off = 0. _cen = (self.naxis1/2.+ _drz_off,self.naxis2/2. + _drz_off) # Compute the RA and Dec for center pixel _cenrd = self.xy2rd(_cen) _cd = N.array([[self.cd11,self.cd12],[self.cd21,self.cd22]],type=N.Float64) _ra0 = DEGTORAD(self.crval1) _dec0 = DEGTORAD(self.crval2) _ra = DEGTORAD(_cenrd[0]) _dec = DEGTORAD(_cenrd[1]) # Set up some terms for use in the final result _dx = self.naxis1/2. - self.crpix1 _dy = self.naxis2/2. - self.crpix2 _dE,_dN = DEGTORAD(N.dot(_cd,(_dx,_dy))) _dE_dN = 1 + N.power(_dE,2) + N.power(_dN,2) _cosdec = N.cos(_dec) _sindec = N.sin(_dec) _cosdec0 = N.cos(_dec0) _sindec0 = N.sin(_dec0) _n1 = N.power(_cosdec,2) + _dE*_dE + _dN*_dN*N.power(_sindec,2) _dra_dE = (_cosdec0 - _dN*_sindec0)/_n1 _dra_dN = _dE*_sindec0 /_n1 _ddec_dE = -_dE*N.tan(_dec) / _dE_dN _ddec_dN = (1/_cosdec) * ((_cosdec0 / N.sqrt(_dE_dN)) - (_dN*N.sin(_dec) / _dE_dN)) # Compute new CD matrix values now... _cd11n = _cosdec * (self.cd11*_dra_dE + self.cd21 * _dra_dN) _cd12n = _cosdec * (self.cd12*_dra_dE + self.cd22 * _dra_dN) _cd21n = self.cd11 * _ddec_dE + self.cd21 * _ddec_dN _cd22n = self.cd12 * _ddec_dE + self.cd22 * _ddec_dN _new_orient = RADTODEG(N.arctan2(_cd12n,_cd22n)) # Update the values now... self.crpix1 = _cen[0] self.crpix2 = _cen[1] self.crval1 = RADTODEG(_ra) self.crval2 = RADTODEG(_dec) # Keep the same plate scale, only change the orientation self.rotateCD(_new_orient) # These would update the CD matrix with the new rotation # ALONG with the new plate scale which we do not want. self.cd11 = _cd11n self.cd12 = _cd12n self.cd21 = _cd21n self.cd22 = _cd22n