You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的字典迭代机制。

临时修复方法

  1. 手动指定title参数:避免工具自动生成标题时修改字典键,修改脚本如下:
from pyraf.iraf import onedspec, rspectext
onedspec
rspectext(input='test.dat', output='spectrum', dtype='interp', title='Test Spectrum')
  1. 降级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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 18:55:18