def all_tools(hdu_in, hdr_out): hcr = hcongrid_hdu(hdu_in, hdr_out) ast = wcsalign(hdu_in, hdr_out) rep = pyreproject(hdu_in, hdr_out) mon = montage_hdu(hdu_in, hdr_out) return hcr,ast,rep,mon
def regrid(hd1, im1, im2raw, hd2): """ Regrid the low resolution image to have the same dimension and pixel size with the high resolution image. Return ---------- hdu2 : An object containing both the image and the header This will containt the regridded low resolution image, and the image header taken from the high resolution observation. im2 : (float point?) array The image array which stores the regridded low resolution image. nax1, nax2 : int(s) Number of pixels in each of the spatial axes. pixscale : float (?) pixel size in the input high resolution image. Parameters ---------- hd1 : header object The header of the high resolution image im1 : (float point?) array The high resolution image im2raw : (float point?) array The pre-regridded low resolution image hd2 : header object header of the low resolution image """ # Sanity Checks: assert hd2[ 'NAXIS'] == im2raw.ndim == 2, 'Error: Input lores image dimension non-equal to 2.' assert hd1[ 'NAXIS'] == im1.ndim == 2, 'Error: Input hires image dimension non-equal to 2.' # read pixel scale from the header of high resolution image pixscale = FITS_tools.header_tools.header_to_platescale(hd1) log.debug('pixscale = {0}'.format(pixscale)) # read the image array size from the high resolution image nax1, nax2 = ( hd1['NAXIS1'], hd1['NAXIS2'], ) # create a new HDU object to store the regridded image hdu2 = fits.PrimaryHDU(data=im2raw, header=hd2) # regrid the image hdu2 = hcongrid_hdu(hdu2, hd1) im2 = hdu2.data.squeeze() # return variables return hdu2, im2, nax1, nax2, pixscale
def regrid(hd1, im1, im2raw, hd2): """ Regrid the low resolution image to have the same dimension and pixel size with the high resolution image. Parameters ---------- hd1 : header object The header of the high resolution image im1 : (float point?) array The high resolution image im2raw : (float point?) array The pre-regridded low resolution image hd2 : header object header of the low resolution image Returns ------- hdu2 : An object containing both the image and the header This will containt the regridded low resolution image, and the image header taken from the high resolution observation. im2 : (float point?) array The image array which stores the regridded low resolution image. nax1, nax2 : int(s) Number of pixels in each of the spatial axes. pixscale : float (?) pixel size in the input high resolution image. """ # Sanity Checks: assert hd2['NAXIS'] == im2raw.ndim == 2, 'Error: Input lores image dimension non-equal to 2.' assert hd1['NAXIS'] == im1.ndim == 2, 'Error: Input hires image dimension non-equal to 2.' # read pixel scale from the header of high resolution image pixscale = FITS_tools.header_tools.header_to_platescale(hd1) log.debug('pixscale = {0}'.format(pixscale)) # read the image array size from the high resolution image nax1,nax2 = (hd1['NAXIS1'], hd1['NAXIS2'], ) # create a new HDU object to store the regridded image hdu2 = fits.PrimaryHDU(data=im2raw, header=hd2) # regrid the image hdu2 = hcongrid_hdu(hdu2, hd1) im2 = hdu2.data.squeeze() # return variables return hdu2, im2, nax1, nax2, pixscale
def feather_simple(hires, lores, highresextnum=0, lowresextnum=0, highresscalefactor=1.0, lowresscalefactor=1.0, lowresfwhm=1*u.arcmin, return_hdu=False, return_regridded_lores=False): """ Fourier combine two data cubes Parameters ---------- highresfitsfile : str The high-resolution FITS file lowresfitsfile : str The low-resolution (single-dish) FITS file highresextnum : int The extension number to use from the high-res FITS file highresscalefactor : float lowresscalefactor : float A factor to multiply the high- or low-resolution data by to match the low- or high-resolution data lowresfwhm : `astropy.units.Quantity` The full-width-half-max of the single-dish (low-resolution) beam; or the scale at which you want to try to match the low/high resolution data return_hdu : bool Return an HDU instead of just an image. It will contain two image planes, one for the real and one for the imaginary data. return_regridded_cube2 : bool Return the 2nd cube regridded into the pixel space of the first? """ if isinstance(hires, (fits.ImageHDU, fits.PrimaryHDU)): hdu1 = hires else: hdu1 = fits.open(hires)[highresextnum] if isinstance(lores, (fits.ImageHDU, fits.PrimaryHDU)): hdu2 = lores else: hdu2 = fits.open(lores)[lowresextnum] im1 = hdu1.data.squeeze() hd1 = FITS_tools.strip_headers.flatten_header(hdu1.header) assert hd1['NAXIS'] == im1.ndim == 2 pixscale = FITS_tools.header_tools.header_to_platescale(hd1) log.debug('pixscale = {0}'.format(pixscale)) im2raw = hdu2.data.squeeze() hd2 = FITS_tools.strip_headers.flatten_header(hdu2.header) assert hd2['NAXIS'] == im2raw.ndim == 2 hdu2 = fits.PrimaryHDU(data=im2raw, header=hd2) hdu2 = hcongrid_hdu(hdu2, hd1) im2 = hdu2.data.squeeze() nax1,nax2 = (hd1['NAXIS1'], hd1['NAXIS2'], ) ygrid,xgrid = (np.indices([nax2,nax1])-np.array([(nax2-1.)/2,(nax1-1.)/2.])[:,None,None]) fwhm = np.sqrt(8*np.log(2)) # sigma in pixels sigma = ((lowresfwhm/fwhm/(pixscale*u.deg)).decompose().value) #sigma_fftspace = (1/(4*np.pi**2*sigma**2))**0.5 sigma_fftspace = (2*np.pi*sigma)**-1 log.debug('sigma = {0}, sigma_fftspace={1}'.format(sigma, sigma_fftspace)) kernel = np.fft.fftshift(np.exp(-(xgrid**2+ygrid**2)/(2*sigma**2))) # convert the kernel, which is just a gaussian in image space, # to its corresponding kernel in fourier space kfft = np.abs(np.fft.fft2(kernel)) # should be mostly real # normalize the kernel kfft/=kfft.max() ikfft = 1-kfft fft1 = np.fft.fft2(np.nan_to_num(im1*highresscalefactor)) fft2 = np.fft.fft2(np.nan_to_num(im2*lowresscalefactor)) fftsum = kfft*fft2 + ikfft*fft1 combo = np.fft.ifft2(fftsum) if return_hdu: combo_hdu = fits.PrimaryHDU(data=combo.real, header=hdu1.header) combo = combo_hdu if return_regridded_lores: return combo, hdu2 else: return combo
def feather_simple( hires, lores, highresextnum=0, lowresextnum=0, highresscalefactor=1.0, lowresscalefactor=1.0, lowresfwhm=1 * u.arcmin, return_hdu=False, return_regridded_lores=False, ): """ Fourier combine two data cubes Parameters ---------- highresfitsfile : str The high-resolution FITS file lowresfitsfile : str The low-resolution (single-dish) FITS file highresextnum : int The extension number to use from the high-res FITS file highresscalefactor : float lowresscalefactor : float A factor to multiply the high- or low-resolution data by to match the low- or high-resolution data lowresfwhm : `astropy.units.Quantity` The full-width-half-max of the single-dish (low-resolution) beam; or the scale at which you want to try to match the low/high resolution data return_hdu : bool Return an HDU instead of just an image. It will contain two image planes, one for the real and one for the imaginary data. return_regridded_cube2 : bool Return the 2nd cube regridded into the pixel space of the first? """ if isinstance(hires, (fits.ImageHDU, fits.PrimaryHDU)): hdu1 = hires else: hdu1 = fits.open(hires)[highresextnum] if isinstance(lores, (fits.ImageHDU, fits.PrimaryHDU)): hdu2 = lores else: hdu2 = fits.open(lores)[lowresextnum] im1 = hdu1.data.squeeze() hd1 = FITS_tools.strip_headers.flatten_header(hdu1.header) assert hd1["NAXIS"] == im1.ndim == 2 pixscale = FITS_tools.header_tools.header_to_platescale(hd1) log.debug("pixscale = {0}".format(pixscale)) im2raw = hdu2.data.squeeze() hd2 = FITS_tools.strip_headers.flatten_header(hdu2.header) assert hd2["NAXIS"] == im2raw.ndim == 2 hdu2 = fits.PrimaryHDU(data=im2raw, header=hd2) hdu2 = hcongrid_hdu(hdu2, hd1) im2 = hdu2.data.squeeze() nax1, nax2 = (hd1["NAXIS1"], hd1["NAXIS2"]) ygrid, xgrid = np.indices([nax2, nax1]) - np.array([(nax2 - 1.0) / 2, (nax1 - 1.0) / 2.0])[:, None, None] fwhm = np.sqrt(8 * np.log(2)) # sigma in pixels sigma = (lowresfwhm / fwhm / (pixscale * u.deg)).decompose().value log.debug("sigma = {0}".format(sigma)) kernel = np.fft.fftshift(np.exp(-(xgrid ** 2 + ygrid ** 2) / (2 * sigma ** 2))) kernel /= kernel.max() ikernel = 1 - kernel fft1 = np.fft.fft2(np.nan_to_num(im1 * highresscalefactor)) fft2 = np.fft.fft2(np.nan_to_num(im2 * lowresscalefactor)) fftsum = kernel * fft2 + ikernel * fft1 combo = np.fft.ifft2(fftsum) if return_regridded_lores: return combo, hdu2 elif return_hdu: combo_hdu = fits.PrimaryHDU(data=np.abs(combo), header=hdu1.header) else: return combo
def feather_simple(hires, lores, highresextnum=0, lowresextnum=0, highresscalefactor=1.0, lowresscalefactor=1.0, lowresfwhm=1 * u.arcmin, return_hdu=False, return_regridded_lores=False): """ Fourier combine two data cubes Parameters ---------- highresfitsfile : str The high-resolution FITS file lowresfitsfile : str The low-resolution (single-dish) FITS file highresextnum : int The extension number to use from the high-res FITS file highresscalefactor : float lowresscalefactor : float A factor to multiply the high- or low-resolution data by to match the low- or high-resolution data lowresfwhm : `astropy.units.Quantity` The full-width-half-max of the single-dish (low-resolution) beam; or the scale at which you want to try to match the low/high resolution data return_hdu : bool Return an HDU instead of just an image. It will contain two image planes, one for the real and one for the imaginary data. return_regridded_cube2 : bool Return the 2nd cube regridded into the pixel space of the first? """ if isinstance(hires, (fits.ImageHDU, fits.PrimaryHDU)): hdu1 = hires else: hdu1 = fits.open(hires)[highresextnum] if isinstance(lores, (fits.ImageHDU, fits.PrimaryHDU)): hdu2 = lores else: hdu2 = fits.open(lores)[lowresextnum] im1 = hdu1.data.squeeze() hd1 = FITS_tools.strip_headers.flatten_header(hdu1.header) assert hd1['NAXIS'] == im1.ndim == 2 pixscale = FITS_tools.header_tools.header_to_platescale(hd1) log.debug('pixscale = {0}'.format(pixscale)) im2raw = hdu2.data.squeeze() hd2 = FITS_tools.strip_headers.flatten_header(hdu2.header) assert hd2['NAXIS'] == im2raw.ndim == 2 hdu2 = fits.PrimaryHDU(data=im2raw, header=hd2) hdu2 = hcongrid_hdu(hdu2, hd1) im2 = hdu2.data.squeeze() nax1, nax2 = ( hd1['NAXIS1'], hd1['NAXIS2'], ) ygrid, xgrid = (np.indices([nax2, nax1]) - np.array([(nax2 - 1.) / 2, (nax1 - 1.) / 2.])[:, None, None]) fwhm = np.sqrt(8 * np.log(2)) # sigma in pixels sigma = ((lowresfwhm / fwhm / (pixscale * u.deg)).decompose().value) #sigma_fftspace = (1/(4*np.pi**2*sigma**2))**0.5 sigma_fftspace = (2 * np.pi * sigma)**-1 log.debug('sigma = {0}, sigma_fftspace={1}'.format(sigma, sigma_fftspace)) kernel = np.fft.fftshift(np.exp(-(xgrid**2 + ygrid**2) / (2 * sigma**2))) # convert the kernel, which is just a gaussian in image space, # to its corresponding kernel in fourier space kfft = np.abs(np.fft.fft2(kernel)) # should be mostly real # normalize the kernel kfft /= kfft.max() ikfft = 1 - kfft fft1 = np.fft.fft2(np.nan_to_num(im1 * highresscalefactor)) fft2 = np.fft.fft2(np.nan_to_num(im2 * lowresscalefactor)) fftsum = kfft * fft2 + ikfft * fft1 combo = np.fft.ifft2(fftsum) if return_hdu: combo_hdu = fits.PrimaryHDU(data=combo.real, header=hdu1.header) combo = combo_hdu if return_regridded_lores: return combo, hdu2 else: return combo