def combine_fitsheader(headers, cdelt=None, pa=None): """ Returns a FITS header which encompasses all input headers. """ if not isinstance(headers, (list, tuple)): header = (headers, ) if len(headers) == 1 and cdelt is None and pa is None: return headers[0] crval = barycenter_lonlat([h['CRVAL1'] for h in headers], [h['CRVAL2'] for h in headers]) if cdelt is None or pa is None: cdeltpa = [get_cdelt_pa(h) for h in headers] if cdelt is None: cdelt = min([np.min(abs(cdelt)) for cdelt, pa in cdeltpa]) if pa is None: pa = tmf.mean_degrees(np.array([pa for cdelt, pa in cdeltpa])) header0 = create_fitsheader((1, 1), cdelt=cdelt, pa=pa, crpix=(1, 1), crval=crval) proj0 = wcs.Projection(header0) xy0 = [] for h in headers: proj = wcs.Projection(h) nx = h['NAXIS1'] ny = h['NAXIS2'] x = h['CRPIX1'] y = h['CRPIX2'] edges = proj.toworld( ([0.5, x, nx + 0.5, 0.5, x, nx + 0.5, 0.5, x, nx + 0.5], [0.5, 0.5, 0.5, y, y, y, ny + 0.5, ny + 0.5, ny + 0.5])) xy0.append(proj0.topixel(edges)) xmin0 = np.round(min([min(c[0]) for c in xy0])) xmax0 = np.round(max([max(c[0]) for c in xy0])) ymin0 = np.round(min([min(c[1]) for c in xy0])) ymax0 = np.round(max([max(c[1]) for c in xy0])) header0['NAXIS1'] = int(xmax0 - xmin0 + 1) header0['NAXIS2'] = int(ymax0 - ymin0 + 1) header0['CRPIX1'] = 2 - xmin0 header0['CRPIX2'] = 2 - ymin0 return header0
def area_within_reg(reg_name, base_fits=m31): ''' returns deg^s deg^2 to arcsec^2: areas*3600.*3600. deg^2 to arcmin^2: areas*3600. ''' # finds area of concentric reg shapes # use GenUtils.area for the area of a polygon. tot_areas, areas = [], [] proj = wcs.Projection(f_header) r = pyregion.open(reg_name).as_imagecoord(header=f_header) patch_list, artist_list = r.get_mpl_patches_texts() for p in patch_list[::-1]: verts_xy = p.get_xy() pixels = (verts_xy[:, 0], verts_xy[:, 1]) ra_v, dec_v = proj.toworld(pixels) verts = np.column_stack((ra_v, dec_v)) tot_areas.append(area(verts)) for i in range(len(tot_areas)): if i == len(tot_areas) - 1: areas.append(tot_areas[i]) else: areas.append(tot_areas[i] - tot_areas[i + 1]) # deg^2 to arcsec^2: areas*3600.*3600. # deg^2 to arcmin^2: areas*3600. return np.array(areas)
def loadFromFITS(self, inputFITS): """ load a FITS histogram file Arguments: - `inputfits`: filename or fits HDU """ if (type(inputFITS) == str): hdu = pyfits.open(inputFITS).pop(0) else: hdu = inputFITS self.hist = hdu.data.transpose() self._bins = self.hist.shape proj = wcs.Projection(hdu.header) ndim = len(self._bins) edges = [] self._range = [] axisnames = [] self._ctypes = [] for dim in xrange(ndim): # note that histogramdd returns edges for 0-N+1 (including # the lower edge of the non-existant next bin), so we do # the same here to keep things the same a = np.zeros((self._bins[dim] + 1, ndim)) a[:, dim] = np.arange(self._bins[dim] + 1) + 0.5 edges.append(proj.toworld(a)[:, dim]) self._range.append((edges[dim][0], edges[dim][-1])) self._ctypes.append(hdu.header["CTYPE%d" % (dim + 1)]) if (hdu.header.get("CNAME%d" % (dim + 1))): axisnames.append(hdu.header["CNAME%d" % (dim + 1)]) else: axisnames.append(self._ctypes[dim][0:4]) self.axisNames = np.array(axisnames) self._binLowerEdges = edges self._range = np.array(self._range) if (hdu.header.get("BSCALE")): self.valueScale = hdu.header["BSCALE"] if (hdu.header.get("BSCALE")): self.valueZero = hdu.header["BZERO"] if (hdu.header.get("NSAMP")): self._numsamples += int(hdu.header["NSAMP"])
def __init__(self, wcs, **keywords): """ wcs : FITS header or Kapteyn wcs.Projection instance Representation of the world coordinate system """ import kapteyn.wcs as kwcs if isinstance(wcs, pyfits.Header): wcs = kwcs.Projection(wcs) if 'dtype' not in keywords: keywords['dtype'] = float wcs.allow_invalid = True Operator.__init__(self, **keywords) self.wcs = wcs
def load_header(self, header, fobj=None): # For kapteyn, header just needs to be duck-typed like a dict self.header = {} self.header.update(header.items()) self.fix_bad_headers() try: self.wcs = kapwcs.Projection(self.header, skyout=self._skyout) self.coordsys = choose_coord_system(self.header) except Exception as e: self.logger.error("Error making WCS object: %s" % (str(e))) self.wcs = None
def points_inside_reg(pyfits_obj, reg_name, ra_points, dec_points, plot=False): ''' Takes an open fits file (pyfits_obj), a reg file (reg_name), ra and dec array, and returns the indices of the ra dec array inside each shape in the region file. Will also plot... inds - cumulative ''' if plot == True: ax = pywcsgrid2.subplot(111, header=pyfits_obj[0].header) ax.grid() ax.imshow(pyfits_obj[0].data, cmap=cm.gray, origin="lower") # load projection, reg shapes, and get them in python proj = wcs.Projection(pyfits_obj[0].header) r = pyregion.open(reg_name).as_imagecoord(header=pyfits_obj[0].header) patch_list, artist_list = r.get_mpl_patches_texts() radec = np.column_stack((ra_points, dec_points)) # get masks of ra,dec in each shape masks = [] for p in patch_list[::-1]: if plot == True: ax.add_patch(p) verts_xy = p.get_xy() pixels = (verts_xy[:, 0], verts_xy[:, 1]) ra_v, dec_v = proj.toworld(pixels) verts = np.column_stack((ra_v, dec_v)) masks.append(nxutils.points_inside_poly(radec, verts)) # subtract masks from outside to inside to not over count. inds = [] for i in range(len(masks) - 1): isolated_mask = (masks[i] - masks[i + 1]) if len(isolated_mask) > 0: within = np.nonzero(isolated_mask)[0] inds.append(within) if plot == True: ax["fk5"].plot(ra_points[within], dec_points[within], '.', alpha=0.2, label='%i' % i, color=cols[i]) for t in artist_list: ax.add_artist(t) ax.add_compass(loc=1) ax.legend() return inds
def load_header(self, header, fobj=None): # For kapteyn, header just needs to be duck-typed like a dict self.header = {} self.header.update(header.items()) self.fix_bad_headers() try: self.logger.debug("Trying to make kapteyn wcs object") self.wcs = kapwcs.Projection(self.header, skyout=self._skyout) self.coordsys = get_coord_system_name(self.header) self.logger.debug("Coordinate system is: %s" % (self.coordsys)) except Exception as e: self.logger.error("Error making WCS object: %s" % (str(e))) self.wcs = None
"""Fit gamma-ray images with Sherpa.""" import sherpa.astro.ui as ui from kapteyn import wcs, positions try: from astropy.io import fits except: import pyfits as fits filename = 'skymap_ex.fits' nomposstr = '05h34m31.94s 22d00m52.2s' header = fits.getheader(filename) proj = wcs.Projection(header) xc, yc = float(header['NAXIS1']) / 2., float(header['NAXIS2']) / 2. ui.load_image(filename) ui.notice2d('circle({0}, {1}, {2})'.format(xc, yc, float(header['NAXIS2']) / 4.)) ui.set_source(ui.gauss2d.g1 + ui.gauss2d.g2) g1.xpos = xc g1.ypos = yc g2.fwhm = g1.fwhm = 3. ui.link(g2.xpos, g1.xpos) ui.link(g2.ypos, g1.ypos) g2.ampl = 50. g1.ampl = 50. ui.guess() ui.fit() ui.image_fit() ui.covar() conf = ui.get_covar_results() conf_dict = dict([(n, (v, l, h)) for n, v, l, h in zip( conf.parnames, conf.parvals, conf.parmins, conf.parmaxes)])
distortion_corrected_header = raw_header.copy() import global_PC_distort transformed_crpix = global_PC_distort.transform_to_global_pixel_coords( 0, raw_CRPIX1, raw_CRPIX2) #transformed_crpix = global_PC_distort.transform_to_global_pixel_coords(0, raw_CRPIX1,raw_CRPIX2, 0.28*180/math.pi ) distortion_corrected_header["CRPIX1"] = transformed_crpix[0] distortion_corrected_header["CRPIX2"] = transformed_crpix[1] print "Raw crpix1", raw_header["CRPIX1"] print "corrected crpix1", distortion_corrected_header["CRPIX1"] #now load it as a pixel / WCS transformation distortion_corrected_map = (wcs.Projection(distortion_corrected_header)).sub( nsub=2) ########################################################################## #Chip to chip adjustments are approximate alterations to the Holtzman 1995 solution as determined by eye, by comparison with drizzled mosaics from HLA in 2010 #NB the HLA mosaics presumably use the Anderson 2003 solution, hence the discrepancy. #Ideally the distortion correction should be rewritten to match Anderson's, but this is a stop gap measure that produces aesthetically pleasing (And presumably, approximately correct) plots. WF_to_PC_pix = 2.187 #approximate pixel size ratio #chip_adjustments_x=[0, 0, 0, 0] #chip_adjustments_y=[0, 0, 0, 0] chip_adjustments_x = [0, 0.6 * WF_to_PC_pix, 1.3 * WF_to_PC_pix, 0] chip_adjustments_y = [
def get_img_WCS_map(fits_filename): hdulist = pyfits.open(fits_filename) header = hdulist[0].header proj = wcs.Projection(header) return proj.sub(nsub=2)
minorCoordOriginsArray[i,0] = minorCoordArray[i,0] - \ minorPosOffset * math.sin(math.radians(minorPA)) minorCoordTipsArray[i,0] = minorCoordArray[i,0] + \ minorPosOffset * math.sin(math.radians(minorPA)) for i in xrange(0, minorCoordArray.shape[0]): minorCoordOriginsArray[i,1] = minorCoordArray[i,1] - \ minorPosOffset * math.cos(math.radians(minorPA)) minorCoordTipsArray[i,1] = minorCoordArray[i,1] + \ minorPosOffset * math.cos(math.radians(minorPA)) # Extract pixel coordinates from wcs coordinates # Define header for calculations proj1 = kwcs.Projection(hmom0) # extract coordinate information of extra axes extraCoords = proj1.toworld((1., 1., 1.)) def arrowHead(image, x, y, dx, dy, head='origin'): theta = math.atan2(-dy, -dx) # make body image.arrow(x, y, dx, dy) # Make head barb = 10 phi = math.radians(10) if head == 'origin': rho = theta + phi else: rho = math.atan2(dy, dx) + phi
def FITS_to_HPX(header, data, Nside, return_sparse=False): """Convert data from FITS format to sparse HPX grid Parameters ---------- header : dict or PyFITS header WCS header describing the coordinates of the input array data : array_like Input data array Nside : int HEALPix gridding parameter Returns ------- hpx_data : csr matrix The HPX-projected data """ # Here's what we do for this function: we're working in "IMG coords" # (i.e. the projection of the input data) and "HPX coords" (i.e. the # projection of the output data). In between, we use "WCS coords". # # These are the steps involved: # 1. Create an array of image edge-pixels in IMG coords, and project # these to HPX coords. # 2. From these bounds, create a regular grid of HPX coords that covers # the image. Project this grid to IMG coords. # 3. In IMG coords, interpolate the image data to the healpix grid. # 4. Use this data to construct a sparse array in HPX coords. if header['NAXIS'] != 2: raise ValueError("input data & header must be two dimensional") if data.shape != (header['NAXIS2'], header['NAXIS1']): raise ValueError("data shape must match header metadata") # Create wcs projection instance from the header proj_img = wcs.Projection(header) # Create wcs projection for healpix grid # Note that the "pixel" coordinates here are measured in degrees... # 0 to 360 in x/RA and -90 to 90 in y/DEC proj_hpx = wcs.Projection({ 'NAXIS': 2, 'CTYPE1': 'RA---HPX', 'CTYPE2': 'DEC--HPX' }) # Define the dimension of the HEALPIX SciDB grid Nx_hpx, Ny_hpx = HPX_grid_size(Nside) dx_hpx = dy_hpx = HPX_grid_step(Nside) #x_hpx = np.linspace(0, 360, Nx_hpx, endpoint=False) #y_hpx = np.linspace(-90, 90, Ny_hpx) # Find the coordinates of the pixels at the edge of the image # Projecting these onto the healpix grid will give the bounds we need. img_bounds_x = np.arange(header['NAXIS2']) zeros_x = np.zeros_like(img_bounds_x) img_bounds_y = np.arange(header['NAXIS1']) zeros_y = np.zeros_like(img_bounds_y) img_bounds_pix = np.concatenate([ img_bounds_x, img_bounds_x, zeros_y, zeros_y + img_bounds_x[-1], zeros_x, zeros_x + img_bounds_y[-1], img_bounds_y, img_bounds_y ]).reshape((2, -1)).T x_bound_hpx, y_bound_hpx =\ proj_hpx.topixel(proj_img.toworld(img_bounds_pix)).T # here we take the pixels at the edge of the boundaries of the image, # transform them to HPX coordinates, and find the required extent # of the HPX pixel grid. # [TODO: check for crossing the pole] # first we need to calculate pixel number i_bound_hpx = x_bound_hpx / dx_hpx j_bound_hpx = (y_bound_hpx + 90.) / dy_hpx i_hpx = np.arange(int(np.floor(i_bound_hpx.min())), int(np.ceil(i_bound_hpx.max()) + 1)) j_hpx = np.arange(int(np.floor(j_bound_hpx.min())), int(np.ceil(j_bound_hpx.max()) + 1)) x_hpx = i_hpx * dx_hpx y_hpx = j_hpx * dy_hpx - 90. # Create the grid of HPX pixels pixel_ind_hpx = np.vstack(map(np.ravel, np.meshgrid(i_hpx, j_hpx))).T pixel_locs_hpx = np.vstack(map(np.ravel, np.meshgrid(x_hpx, y_hpx))).T pixel_locs_img = proj_img.topixel(proj_hpx.toworld(pixel_locs_hpx)) ## DEBUG: Plot the borders & grid in the HPX projection #import matplotlib.pyplot as plt #plt.plot(i_bound_hpx, j_bound_hpx, '.k') #plt.plot(pixel_ind_hpx[:, 0], pixel_ind_hpx[:, 1], '.r') #plt.show() #exit() ## DEBUG: Plot the HPX grid in the IMG projection #import matplotlib.pyplot as plt #plt.plot(img_bounds_pix[:, 0], img_bounds_pix[:, 1], '.k') #plt.plot(pixel_locs_img[:, 0], pixel_locs_img[:, 1], '.r') #plt.show() #exit() # Interpolate from data to pixel locations I = GridInterpolation(data, [0, 0], [1, 1]) HPX_vals = I(pixel_locs_img) #.reshape(len(y_hpx), len(x_hpx)) # # DEBUG: Plot regridded input data next to the interpolated HPX data # import matplotlib.pyplot as plt # plt.figure(figsize=(8, 8)) # plt.subplot(211, aspect='equal') # plt.contourf(x_hpx, y_hpx, HPX_vals) # plt.subplot(212, aspect='equal') # plt.contourf(regrid(data, 5)) # plt.show() # exit() good_vals = ~np.isnan(HPX_vals) x, y = pixel_ind_hpx[good_vals].T HPX_vals = HPX_vals[good_vals] if return_sparse: return sparse.coo_matrix((HPX_vals, (x, y)), shape=(Nx_hpx, Ny_hpx)) else: output = np.zeros(len(HPX_vals), dtype=[('time', np.int64), ('x', np.int64), ('y', np.int64), ('val', np.float64)]) # use MJD in seconds output['time'] = int(header['TAI'] * 24 * 60 * 60) output['x'] = x output['y'] = y output['val'] = HPX_vals return output
def XY2radec(pyfits_obj, x, y): # returns ra,dec based on (an already opened) fits image. proj = wcs.Projection(pyfits_obj[0].header) pixels = (x, y) return proj.toworld(pixels)
m31 = '/Users/Phil/research/PHAT/m31_fullfield.fits' # MAC data_src = '/Users/Phil/research/PHAT/Data/' base_fits = '/Users/Phil/research/PHAT/Data/12058_M31-B01-F10-UVIS_F336W_drz.chip1.fits' # astro network data_src = '/astro/net/angst2/philrose/PHAT/FullBricks/' base_fits = '/astro/net/angst2/philrose/PHAT/Fields/drzs/12058_M31-B01-F10-UVIS_F336W_drz.chip1.fits' print 'fits are centered with', base_fits f = pyfits.open(base_fits) f_shape = (f[0].header["NAXIS1"], f[0].header["NAXIS2"]) f_data = f[0].data f_proj = wcs.Projection(f[0].header) f_header = f[0].header f.close() def read_basefits(): return f def radec_to_reg(ra, dec, outfile='radec.reg', shape='circle', size=0.5, header='default'): if header == 'default':
kvdict['demin'] = float(kvdict['demin']) except: print('Provide lower declination demin') raise (BaseException) try: getkey(kvdict, 'outfile') except: print('Provide output file outfile') raise (BaseException) # Open hdu hduc = fits.open(kvdict['infile'])[0] w = wcs.WCS(hduc.header, naxis=2) hdu = read2dim(hduc, 0) proj = kapwcs.Projection(hdu.header) proj.skyout = (kapwcs.equatorial, kapwcs.fk5, 'J2000') if 'tempfile' in kvdict.keys(): # Get info hduinfoc = fits.open(kvdict['tempfile'])[0] # This makes the whole thing slightly unprecise. Write into the doc that it's always the first plane as a reference plane hduinfo = read2dim(hduinfoc, 0) nypsinfo = hduinfo.shape[-2] nxpsinfo = hduinfo.shape[-1] #wnew = wcs.WCS(hduinfo.header, naxis=2) #solution = wnew.wcs_pix2world(nxps,nyps,0) projinfo = kapwcs.Projection(hduinfo.header) projinfo.skyout = (kapwcs.equatorial, kapwcs.fk5, 'J2000') pixelinfo = ([1, nxpsinfo], [1, nypsinfo])
Vr = header_gds['VELR'] fr = header_gds['CRVAL1'] df = header_gds['CDELT1'] crpix = header_gds['CRPIX1'] c = wcs.c # Speed of light p = pixrange = arange(crpix - 2, crpix + 3) # Range of pixels for which we # want world coordinates # Calculate the barycentric equivalents fb = f0 * (1.0 - Vr / c) Vtopo = c * ((fb * fb - fr * fr) / (fb * fb + fr * fr)) dfb = df * (c - Vtopo) / sqrt(c * c - Vtopo * Vtopo) print("Topocentric correction (km/s):", Vtopo / 1000) print("Barycentric frequency and increment (Hz):", fb, dfb) # VRAD from spectral translation, assumed to give the correct velocities proj = wcs.Projection(header_gds) spec = proj.spectra(ctype='VRAD') V1 = spec.toworld1d(pixrange) # Radio velocities with GIPSY formula with barycentric # values (excact). V2 = Vr - c * (p - crpix) * dfb / f0 # Radio velocities with GIPSY formula without rest frequency and # with barycentric values (exact). V3 = Vr + (p - crpix) * dfb * (Vr - c) / fb # Radio velocities with GIPSY formula using topocentric, # values (approximation). V4 = Vr - c * (p - crpix) * df / f0
if opts.juldate is None: del(c[s]) else: ephem.Body.compute(c[s], date) srcs,coff,catalogs = a.scripting.parse_srcs(opts.src,opts.cat) cat = a.src.get_catalog(srcs=srcs,catalogs=catalogs) update_pos(cat) for file in args: print file hdulist = pf.open(file) hdr = hdulist[0].header width = n.abs(opts.width/hdulist[0].header.get('CDELT1')) proj = wcs.Projection(hdulist[0].header) img_ra = hdulist[0].header.get('CRVAL1')*a.img.deg2rad img_dec = hdulist[0].header.get('CRVAL2')*a.img.deg2rad center = a.phs.RadioFixedBody(img_ra, img_dec) ephem.FixedBody.compute(center,ephem.J2000) for name,src in cat.iteritems(): src_sep = ephem.separation(src,center) if src_sep<opts.sep: if opts.verb: print "getting \n",src ra = src.ra * a.img.rad2deg dec = src.dec * a.img.rad2deg if opts.verb:print src_sep,ra,dec px = n.round(proj.topixel((ra,dec,1,1))) if opts.verb:print "at",px # if opts.verb:print "subimg"
cdelt = (-1.5, 3) pa = -25. header = create_fitsheader((10,10), cdelt=cdelt, pa=pa) cdelt_, pa_ = wu.get_cdelt_pa(header) if any_neq(cdelt, cdelt_): raise TestFailure() if any_neq(pa, pa_): raise TestFailure() # combine_fitsheader headers = [ wu.create_fitsheader((1,1), cdelt=3., crval=(0,0)), wu.create_fitsheader((3,3), cdelt=1., crval=(1,1)), wu.create_fitsheader((5,5), cdelt=1., crval=(3,3)), wu.create_fitsheader((2,2), cdelt=1., crval=(5,5)), ] header0 = wu.combine_fitsheader(headers) proj0 = wcs.Projection(header0) for iheader, header in enumerate(headers): nx = header['NAXIS1'] ny = header['NAXIS2'] x = header['CRPIX1'] y = header['CRPIX2'] edges = (np.array(3*(0.5,x,nx+0.5)), np.array((0.5,0.5,0.5,y,y,y,ny+0.5,ny+0.5,ny+0.5))) a,d = wcs.Projection(header).toworld(edges) x0,y0 = proj0.topixel((a,d)) epsilon = 1.e-10 if np.any(x0 < 0.5-epsilon) or np.any(y0 < 0.5-epsilon): raise TestFailure() if np.any(x0 > header0['NAXIS1'] + 0.5 + epsilon): raise TestFailure() if np.any(y0 > header0['NAXIS2'] + 0.5 + epsilon): raise TestFailure()