def cutout_range(self, rac, decc, xw, yw, units='pixels', coordsys='galactic'): """ computes the pixel range (min max) of a frame centered at (rac, decc) with width xw, yw (in arc seconds) :param rac: :param decc: :param xw: :param yw: :return: """ head = self.header wcs = pywcs.WCS(head) if units == 'wcs': if coordsys == 'celestial' and wcs.wcs.lngtyp == 'GLON': rac, decc = coords.Position((rac, decc), system=coordsys).galactic() elif coordsys == 'galactic' and wcs.wcs.lngtyp == 'RA': rac, decc = coords.Position((rac, decc), system=coordsys).j2000() else: raise ValueError("problem with wcs instance.") xx, yy = wcs.all_world2pix(rac, decc, 0) xx = int(xx) yy = int(yy) print('the center of the image is at pixel coordinates %f, %f.' % (xx, yy)) if units == 'pixels': xmin, xmax = np.max([0, xx - xw]), np.min([self.naxis1, xx + xw]) ymin, ymax = np.max([0, yy - yw]), np.min([self.naxis2, yy + yw]) elif units == 'arcseconds': cd1, cd2 = self.pixel_size xmin, xmax = np.max([0, xx - xw / np.abs(cd1)]), np.min( [self.naxis1, xx + xw / np.abs(cd1)]) ymin, ymax = np.max([0, yy - yw / np.abs(cd2)]), np.min( [self.naxis2, yy + yw / np.abs(cd2)]) else: raise Exception("Can't use units %s." % units) if xmax < 0 or ymax < 0: raise ValueError("Max Coordinate is outside of map: %f,%f." % (xmax, ymax)) if ymin >= head.get('NAXIS2') or xmin >= head.get('NAXIS1'): raise ValueError("Min Coordinate is outside of map: %f,%f." % (xmin, ymin)) return xmin, xmax, ymin, ymax
def coords_in_image(fitsfile, lon, lat, system='galactic'): """ Determine whether the coordinates are inside the image """ if not isinstance(fitsfile, fits.HDUList): fitsfile = fits.open(fitsfile) wcs = pywcs.WCS(flatten_header(fitsfile[0].header)) if 'RA' in wcs.wcs.ctype[0]: pos = coordinates.Position((lon, lat), system=system) lon, lat = pos.j2000() if 'GLON' in wcs.wcs.ctype[0]: pos = coordinates.Position((lon, lat), system=system) lon, lat = pos.galactic() x, y = wcs.wcs_world2pix(lon, lat, 0) #DEBUG print x,y,wcs.naxis1,wcs.naxis2 if (0 < x < wcs.naxis1) and (0 < y < wcs.naxis2): return True else: return False
def _cutout(self, fits_filename, xc, yc, xw, yw, units='pixels', clobber=True, useMontage=False, coordsys='galactic', verbose=False, exposure_map=False): """ Inputs: file - pyfits HDUList (must be 2D) xc,yc - x and y coordinates in the fits files' coordinate system (CTYPE) xw,yw - x and y width (pixels or wcs) units - specify units to use: either pixels or wcs outfile - optional output file """ # file = pyfits.open(fits_filename) # head = file['SCI'].header.copy() head = self.header.copy() wcs = pywcs.WCS(head) if units == 'wcs': if coordsys == 'celestial' and wcs.wcs.lngtyp == 'GLON': xc, yc = coords.Position((xc, yc), system=coordsys).galactic() elif coordsys == 'galactic' and wcs.wcs.lngtyp == 'RA': xc, yc = coords.Position((xc, yc), system=coordsys).j2000() xx, yy = wcs.all_world2pix(xc, yc, 0) print('the center of the image is at pixel coordinates %f, %f.' % (xx, yy)) if units == 'pixels': xmin, xmax = np.max([0, xx - xw]), np.min([self.naxis1, xx + xw]) ymin, ymax = np.max([0, yy - yw]), np.min([self.naxis2, yy + yw]) elif units == 'wcs': xmin, xmax = np.max([0, xx - xw / np.abs(self.cd1)]), np.min( [self.naxis1, xx + xw / np.abs(self.cd1)]) ymin, ymax = np.max([0, yy - yw / np.abs(self.cd2)]), np.min( [self.naxis2, yy + yw / np.abs(self.cd2)]) else: raise Exception("Can't use units %s." % units) self._xmin_c, self._xmax_c = xmin, xmax self._ymin_c, self._ymax_c = ymin, ymax if xmax < 0 or ymax < 0: raise ValueError("Max Coordinate is outside of map: %f,%f." % (xmax, ymax)) if ymin >= head.get('NAXIS2') or xmin >= head.get('NAXIS1'): raise ValueError("Min Coordinate is outside of map: %f,%f." % (xmin, ymin)) head = self.change_header(head, xmin, xmax, ymin, ymax) img = self.image_full()[int(ymin):int(ymax), int(xmin):int(xmax)].copy() # img = file['SCI'].data[ymin:ymax, xmin:xmax] if verbose: print("Cut image %s to %s. xrange: %f:%f, yrange: %f:%f" % (fits_filename, img.shape, xmin, xmax, ymin, ymax)) if exposure_map: exp_map = self.exposure_full()[int(ymin):int(ymax), int(xmin):int(xmax)].copy() else: exp_map = None ra_coord, dec_coord = self.get_coordinates(xmin, xmax, ymin, ymax, wcs) return img, head, exp_map, ra_coord, dec_coord
def rotcrop_cube(x1, y1, x2, y2, cubename, outname, xwidth=25, ywidth=25, in_system='galactic', out_system='equatorial', overwrite=True, newheader=None, xcen=None, ycen=None): """ Crop a data cube and then rotate it with montage """ cubefile = fits.open(cubename) if xcen is None and ycen is None: pos1 = coordinates.Position([x1, y1], system=in_system) pos2 = coordinates.Position([x2, y2], system=in_system) if cubefile[0].header.get('CTYPE1')[:2] == 'RA': x1, y1 = pos1.j2000() x2, y2 = pos2.j2000() coord_system = 'celestial' elif cubefile[0].header.get('CTYPE1')[:4] == 'GLON': x1, y1 = pos1.galactic() x2, y2 = pos2.galactic() coord_system = 'galactic' xcen = (x1 + x2) / 2.0 ycen = (y1 + y2) / 2.0 print(xcen, ycen, xwidth, ywidth, coord_system) else: coord_system = in_system sc = subcube(cubefile[0].data, xcen, xwidth, ycen, ywidth, widthunits='pixels', units="wcs", header=cubefile[0].header, return_HDU=True) # note: there should be no security risk here because fits' writeto # will not overwrite by default tempcube = tempfile.mktemp(suffix='.fits') sc.writeto(tempcube) pa = posang.posang(x1, y1, x2, y2, system=coord_system) - 90 if newheader is None: newheader = sc.header.copy() cd11 = newheader.get('CDELT1') if newheader.get( 'CDELT1') else newheader.get('CD1_1') cd22 = newheader.get('CDELT2') if newheader.get( 'CDELT2') else newheader.get('CD2_2') cd12 = newheader.get('CD1_2') if newheader.get('CD1_2') else 0.0 cd21 = newheader.get('CD2_1') if newheader.get('CD2_1') else 0.0 cdelt = numpy.sqrt(cd11**2 + cd12**2) tempheader = tempfile.mktemp(suffix='.hdr') ycensign = "+" if numpy.sign(ycen) >= 0 else "-" montage.mHdr("%s %1s%s" % (xcen, ycensign, numpy.abs(ycen)), xwidth * cdelt, tempheader, system=out_system, height=ywidth * cdelt, pix_size=cdelt * 3600.0, rotation=pa) os.system("sed -i bck '/END/d' %s" % (tempheader)) newheader2 = fits.Header() newheader2.fromTxtFile(tempheader) #newheader2.fromtextfile(tempheader) for key in ('CRPIX3', 'CRVAL3', 'CDELT3', 'CD3_3', 'CUNIT3', 'WCSTYPE3', 'CTYPE3'): if newheader.get(key): newheader2[key] = newheader.get(key) if newheader.get('CD3_3') and newheader2.get('CDELT3') is None: newheader2['CDELT3'] = newheader.get('CD3_3') if astropy.version.major >= 2 or (astropy.version.major == 1 and astropy.version.minor >= 3): newheader2.toTxtFile(tempheader, overwrite=True) else: newheader2.toTxtFile(tempheader, clobber=True) #if newheader2.get('CDELT3') is None: # raise Exception("No CD3_3 or CDELT3 in header.") else: if isinstance(newheader, str): newheader2 = fits.Header() newheader2.fromTxtFile(newheader) tempheader = tempfile.mktemp(suffix='.hdr') if astropy.version.major >= 2 or (astropy.version.major == 1 and astropy.version.minor >= 3): newheader2.toTxtFile(tempheader, overwrite=True) else: newheader2.toTxtFile(tempheader, clobber=True) montage.wrappers.reproject_cube(tempcube, outname, header=tempheader, clobber=overwrite) #print "\n",outname #os.system('imhead %s | grep CDELT' % outname) # AWFUL hack because montage removes CDELT3 tempcube = fits.open(outname) tempcube.header = newheader2 #if tempcube.header.get('CDELT3') is None: # raise Exception("No CD3_3 or CDELT3 in header.") #print tempcube.header.get('CDELT3') if astropy.version.major >= 2 or (astropy.version.major == 1 and astropy.version.minor >= 3): tempcube.writeto(outname, overwrite=True) else: tempcube.writeto(outname, clobber=True) #print tempcube.get('CDELT3') #print "\n",outname #os.system('imhead %s | grep CDELT' % outname) return