裁剪适合文件后坐标不保存
Coordinates are not conserved after cropping fits file
考虑以下代码(下载 test.fits):
from astropy.io import fits
from photutils.utils import cutout_footprint
# Read fits file.
hdulist = fits.open('test.fits')
hdu_data = hdulist[0].data
hdulist.close()
# Some center and box to crop
xc, yc, xbox, ybox = 267., 280., 50., 100.
# Crop image.
hdu_crop = cutout_footprint(hdu_data, (xc, yc), (ybox, xbox))[0]
# Add comment to header
prihdr = hdulist[0].header
prihdr['COMMENT'] = "= Cropped fits file")
# Write cropped frame to new fits file.
fits.writeto('crop.fits', hdu_crop, prihdr)
原始(左)和裁剪(右)图像如下所示:
画面中央的星星的 (ra, dec) equatorial coordinates 是:
Original frame: 12:10:32 +39:24:17
Cropped frame: 12:12:07 +39:06:50
为什么裁剪框的坐标不一样?
这是解决此问题的两种方法,使用两种不同的方法。
from astropy.io import fits
from photutils.utils import cutout_footprint
from astropy.wcs import WCS
from astropy.nddata.utils import Cutout2D
import datetime
# Read fits file.
hdulist = fits.open('test.fits')
hdu = hdulist[0].data
# Header
hdr = hdulist[0].header
hdulist.close()
# Some center and box to crop
xc, yc, xbox, ybox = 267., 280., 50., 100.
# First method using cutout_footprint
# Crop image.
hdu_crop = cutout_footprint(hdu, (xc, yc), (ybox, xbox))[0]
# Read original WCS
wcs = WCS(hdr)
# Cropped WCS
wcs_cropped = wcs[yc - ybox // 2:yc + ybox // 2, xc - xbox // 2:xc + xbox // 2]
# Update WCS in header
hdr.update(wcs_cropped.to_header())
# Add comment to header
hdr['COMMENT'] = "= Cropped fits file ({}).".format(datetime.date.today())
# Write cropped frame to new fits file.
fits.writeto('crop.fits', hdu_crop, hdr)
# Second method using Cutout2D
# Crop image
hdu_crop = Cutout2D(hdu, (xc, yc), (xbox, ybox), wcs=WCS(hdr))
# Cropped WCS
wcs_cropped = hdu_crop.wcs
# Update WCS in header
hdr.update(wcs_cropped.to_header())
# Add comment to header
hdr['COMMENT'] = "= Cropped fits file ({}).".format(datetime.date.today())
# Write cropped frame to new fits file.
fits.writeto('crop.fits', hdu_crop.data, hdr)
坐标发生了变化,因为您对图像进行了切片,但并未更改 WCS 信息(尤其是参考像素值)。
一种方法是使用 astropy.WCS
:
from astropy.wcs import WCS
wcs = WCS(hdulist[0].header)
wcs_cropped = wcs[280-50 : 280+50 , 267-25 : 267+25]
然后将更新后的 wcs 复制到您的页眉中:
prihdr.update(wcs_cropped.to_header())
保存文件之前。
我不确定 cutout_footprint
做了什么,所以您可能需要在创建 wcs_cropped
时更改切片索引。
astropy.nddata
中有一个名为 Cutout2D
的便利功能,它默认更新 WCS
。
photutils.utils.cutout_footprint只切掉像素,不更新用于像素坐标和世界坐标转换的WCS
另一个答案,因为它需要一个额外的包:ccdproc
especially the class CCDData
,它基于 astropy.nddata.NDData
:
它简化了文件的读取:
from ccdproc import CCDData
ccd = CCDData.read(filename, unit='erg/cm**2/s/AA')
必须指定单位,因为 header 单位与 astropy.units
模块不兼容。
关于 CCDData
的重要一点是您(大部分)不需要照顾 units
、wcs
、header
和 masks
,它们被保存为属性,最基本的操作相应地保存(和更新)它们。例如切片:
xc, yc, xbox, ybox = 267., 280., 50., 100.
ccd_cropped = ccd[int(yc - ybox // 2) : int(yc + ybox // 2),
int(xc - xbox // 2) : int(xc + xbox // 2)]
这个切片ccd_cropped
已经更新了WCS信息,所以你可以简单地继续处理它(就像再次保存它一样):
ccd_cropped.write('cropped.fits')
而且它应该有正确更新的坐标。切片部分实际上也可以使用 astropy.nddata.NDDataRef
,只有 read
和 write
部分在 ccdproc.CCDData
中明确实现
考虑以下代码(下载 test.fits):
from astropy.io import fits
from photutils.utils import cutout_footprint
# Read fits file.
hdulist = fits.open('test.fits')
hdu_data = hdulist[0].data
hdulist.close()
# Some center and box to crop
xc, yc, xbox, ybox = 267., 280., 50., 100.
# Crop image.
hdu_crop = cutout_footprint(hdu_data, (xc, yc), (ybox, xbox))[0]
# Add comment to header
prihdr = hdulist[0].header
prihdr['COMMENT'] = "= Cropped fits file")
# Write cropped frame to new fits file.
fits.writeto('crop.fits', hdu_crop, prihdr)
原始(左)和裁剪(右)图像如下所示:
画面中央的星星的 (ra, dec) equatorial coordinates 是:
Original frame: 12:10:32 +39:24:17
Cropped frame: 12:12:07 +39:06:50
为什么裁剪框的坐标不一样?
这是解决此问题的两种方法,使用两种不同的方法。
from astropy.io import fits
from photutils.utils import cutout_footprint
from astropy.wcs import WCS
from astropy.nddata.utils import Cutout2D
import datetime
# Read fits file.
hdulist = fits.open('test.fits')
hdu = hdulist[0].data
# Header
hdr = hdulist[0].header
hdulist.close()
# Some center and box to crop
xc, yc, xbox, ybox = 267., 280., 50., 100.
# First method using cutout_footprint
# Crop image.
hdu_crop = cutout_footprint(hdu, (xc, yc), (ybox, xbox))[0]
# Read original WCS
wcs = WCS(hdr)
# Cropped WCS
wcs_cropped = wcs[yc - ybox // 2:yc + ybox // 2, xc - xbox // 2:xc + xbox // 2]
# Update WCS in header
hdr.update(wcs_cropped.to_header())
# Add comment to header
hdr['COMMENT'] = "= Cropped fits file ({}).".format(datetime.date.today())
# Write cropped frame to new fits file.
fits.writeto('crop.fits', hdu_crop, hdr)
# Second method using Cutout2D
# Crop image
hdu_crop = Cutout2D(hdu, (xc, yc), (xbox, ybox), wcs=WCS(hdr))
# Cropped WCS
wcs_cropped = hdu_crop.wcs
# Update WCS in header
hdr.update(wcs_cropped.to_header())
# Add comment to header
hdr['COMMENT'] = "= Cropped fits file ({}).".format(datetime.date.today())
# Write cropped frame to new fits file.
fits.writeto('crop.fits', hdu_crop.data, hdr)
坐标发生了变化,因为您对图像进行了切片,但并未更改 WCS 信息(尤其是参考像素值)。
一种方法是使用 astropy.WCS
:
from astropy.wcs import WCS
wcs = WCS(hdulist[0].header)
wcs_cropped = wcs[280-50 : 280+50 , 267-25 : 267+25]
然后将更新后的 wcs 复制到您的页眉中:
prihdr.update(wcs_cropped.to_header())
保存文件之前。
我不确定 cutout_footprint
做了什么,所以您可能需要在创建 wcs_cropped
时更改切片索引。
astropy.nddata
中有一个名为 Cutout2D
的便利功能,它默认更新 WCS
。
photutils.utils.cutout_footprint只切掉像素,不更新用于像素坐标和世界坐标转换的WCS
另一个答案,因为它需要一个额外的包:ccdproc
especially the class CCDData
,它基于 astropy.nddata.NDData
:
它简化了文件的读取:
from ccdproc import CCDData
ccd = CCDData.read(filename, unit='erg/cm**2/s/AA')
必须指定单位,因为 header 单位与 astropy.units
模块不兼容。
关于 CCDData
的重要一点是您(大部分)不需要照顾 units
、wcs
、header
和 masks
,它们被保存为属性,最基本的操作相应地保存(和更新)它们。例如切片:
xc, yc, xbox, ybox = 267., 280., 50., 100.
ccd_cropped = ccd[int(yc - ybox // 2) : int(yc + ybox // 2),
int(xc - xbox // 2) : int(xc + xbox // 2)]
这个切片ccd_cropped
已经更新了WCS信息,所以你可以简单地继续处理它(就像再次保存它一样):
ccd_cropped.write('cropped.fits')
而且它应该有正确更新的坐标。切片部分实际上也可以使用 astropy.nddata.NDDataRef
,只有 read
和 write
部分在 ccdproc.CCDData