Pyraf rspectext报RuntimeError:字典迭代时键变更问题求助
问题:Pyraf中rspectext工具报错及替代方案
问题详情
尝试用Pyraf的rspectext工具将双列ASCII光谱文件转FITS,设置dtype='interp'时触发如下报错:
Traceback (innermost last): File "<CL script CL1>", line 1, in <module> File "<CL script onedspec.rspectext>", line 54, in rspectext iraf.hedit(Vars.specout, 'title', Vars.title, add=yes, addonly=no,PYdel=no,update=yes,verify=no,show=no) RuntimeError: dictionary keys changed during iteration
- 已更新所有组件,IRAF原生环境中
rspectext运行正常 - Pyraf中其他命令(如
continuum、splot)可正常使用 - 测试脚本:
from pyraf.iraf import onedspec,rspectext onedspec rspectext(input='test.dat',output='spectrum',dtype='interp')
- 测试数据(双列:波长、流量):
5530.01708984375 0.9749500155448914 5530.0498046875 0.9674800038337708 5530.0830078125 0.9679499864578247 5530.1162109375 0.968280017375946 5530.1474609375 0.9703999757766724 5530.18115234375 0.9549300074577332 5530.21435546875 0.9670699834823608 5530.2470703125 0.9639800190925598 5530.2802734375 0.953029990196228 5530.31298828125 0.9535700082778931 5530.34619140625 0.9583899974822998 5530.37890625 0.9467300176620483 5530.412109375 0.9565500020980835
- 环境:Python 3.10.6、Pyraf 2.2.0、IRAF 2.17、Ubuntu 22.04.1 LTS 64位
报错原因
这是Pyraf 2.2.0与Python 3.10的兼容性问题:Python 3.7+对字典迭代过程中修改键的操作做了严格限制,而rspectext内部调用hedit时,处理Vars字典的逻辑触发了这个限制。IRAF原生环境不受影响是因为其未使用Python的字典迭代机制。
临时修复方法
- 手动指定title参数:避免工具自动生成标题时修改字典键,修改脚本如下:
from pyraf.iraf import onedspec, rspectext onedspec rspectext(input='test.dat', output='spectrum', dtype='interp', title='Test Spectrum')
- 降级Python版本:将Python降到3.8或3.9,Pyraf 2.2.0对这两个版本的兼容性更好。
纯Python替代方案
1. ASCII转FITS(用astropy)
无需依赖Pyraf/IRAF,直接用astropy实现:
import numpy as np from astropy.io import fits # 读取ASCII数据 wavelength, flux = np.loadtxt('test.dat', unpack=True) # 创建FITS主HDU hdu = fits.PrimaryHDU(data=flux) # 添加波长轴元数据(符合天文FITS规范) hdu.header.update({ 'CRVAL1': wavelength[0], # 第一个像素的波长值 'CDELT1': wavelength[1] - wavelength[0], # 波长间隔 'CRPIX1': 1, # 参考像素位置 'CTYPE1': 'WAVE', # 轴类型:波长 'CUNIT1': 'Angstrom', # 波长单位 'TITLE': 'Converted Spectrum' }) # 保存FITS文件 hdulist = fits.HDUList([hdu]) hdulist.writeto('spectrum.fits', overwrite=True)
2. 光谱归一化(基于astropy+numpy)
用多项式拟合连续谱实现归一化:
import numpy as np from astropy.io import fits from astropy.modeling import models, fitting # 读取FITS数据(或直接用之前读取的wavelength、flux) hdulist = fits.open('spectrum.fits') flux = hdulist[0].data wavelength = hdulist[0].header['CRVAL1'] + np.arange(len(flux)) * hdulist[0].header['CDELT1'] hdulist.close() # 拟合连续谱(可根据光谱复杂度调整多项式阶数) poly_init = models.Polynomial1D(degree=3) fitter = fitting.LevMarLSQFitter() continuum_model = fitter(poly_init, wavelength, flux) # 计算归一化流量 normalized_flux = flux / continuum_model(wavelength) # 保存归一化后的FITS文件 hdu = fits.PrimaryHDU(data=normalized_flux) hdu.header.update(hdulist[0].header) # 继承原表头信息 hdu.header['NOTE'] = 'Normalized by polynomial continuum fit' hdulist = fits.HDUList([hdu]) hdulist.writeto('normalized_spectrum.fits', overwrite=True)
内容的提问来源于stack exchange,提问作者Erasmo Trentin
相关产品推荐
相关产品推荐

