更新FITS文件WCS头时Astropy非零退出问题排查
问题排查与解决方案
核心原因分析
你的问题本质是非标准WCS关键字(TPD字段)导致WCS初始化失败:
- 非conda环境给出明确错误提示,说明WCS解析器无法识别TPD字段;
- conda环境下由于编译的
cfitsio(astropy WCS依赖的底层库)版本差异,直接触发内存访问违规错误(退出码0xC0000005),而非抛出明确异常。
TPD属于仪器/观测特定的自定义元数据字段,不属于FITS WCS标准关键字集合(标准关键字如CRVALn、CRPIXn、CDn_m、CTYPEn等),当你将裁剪后的WCS信息直接合并到原头副本时,这些非标准字段会被WCS解析器误判为WCS相关字段,引发解析错误或内存崩溃。
解决方案
方案1:过滤原头中的非标准WCS字段
复制原头文件后,先移除旧的WCS关键字和无关的自定义字段(如TPD),再合并新的WCS信息:
from astropy.io import fits from astropy.wcs import WCS # 读取原图像与WCS with fits.open('HorseHead.fits') as hdul: orig_data = hdul[0].data orig_wcs = WCS(hdul[0].header) # 复制原头文件,保留非WCS元数据 clean_header = hdul[0].header.copy() # 执行裁剪操作(示例:取100:200的二维切片) cropped_data = orig_data[100:200, 100:200] # 获取裁剪后的新WCS cropped_wcs = orig_wcs[100:200, 100:200] # 移除原头中的旧WCS关键字 for key in orig_wcs.wcs_keys: if key in clean_header: clean_header.remove(key, remove_all=True) # 手动移除TPD相关字段(如果存在) for key in clean_header: if key.startswith('TPD'): del clean_header[key] # 生成新的WCS头并合并到干净的原头中 cropped_wcs_header = cropped_wcs.to_header() clean_header.extend(cropped_wcs_header, update=True) # 现在初始化WCS不会出错 new_wcs = WCS(clean_header)
方案2:直接生成独立的WCS头
如果不需要保留原头中的全部元数据,可以直接用裁剪后的WCS生成独立头文件,再添加必要的非WCS元数据:
# 生成仅包含标准WCS关键字的头文件 cropped_wcs_header = cropped_wcs.to_header() # 添加需要保留的原头元数据(如观测日期、仪器信息等) cropped_wcs_header['OBSDATE'] = hdul[0].header.get('OBSDATE') cropped_wcs_header['INSTRUME'] = hdul[0].header.get('INSTRUME') # 初始化WCS new_wcs = WCS(cropped_wcs_header)
额外建议
- 更新Astropy版本:旧版本的WCS解析器对非标准字段的兼容性较差,执行
pip install --upgrade astropy(或conda update astropy)升级到最新版; - 检查TPD字段用途:如果TPD是需要保留的仪器元数据,确认其不属于WCS关键字后,在初始化WCS时可以通过
WCS(clean_header, relax=True)放宽解析规则,但不推荐——最好还是提前过滤无关字段避免风险。
内容的提问来源于stack exchange,提问作者niaei
相关产品推荐
相关产品推荐

