如何将含Galactocentric系SkyCoord的Astropy QTable保存为FITS文件?
创建Galactocentric坐标系的SkyCoord对象:
c_end = SkyCoord( x=xf, y=yf, z=zf, v_x=vxf, v_y=vyf, v_z=vzf, frame='galactocentric' )
尝试将其存入Astropy QTable并写入FITS文件:
tab = QTable([c_end, ...], names = ['skycoord', ...]) tab.write('name.fits', format = 'fits')
触发以下错误:
yaml.representer.RepresenterError: ('cannot represent an object', <ICRS Coordinate: (ra, dec) in deg
(266.4051, -28.936175)>)
这个ICRS坐标是银心位置,即使转换为ICRS系后保存仍报错。可复现的最小示例代码:
from astropy.coordinates import SkyCoord from astropy.table import QTable import astropy.units as u xf, yf, zf = 8.3, 0.0, 0.02 vxf, vyf, vzf = -11.1, 232.24, 7.25 c_end = SkyCoord( x=xf*u.kpc, y=yf*u.kpc, z=zf*u.kpc, v_x=vxf*u.km/u.s, v_y=vyf*u.km/u.s, v_z=vzf*u.km/u.s, frame='galactocentric' ) tab = QTable([[c_end]], names=['skycoord']) try: tab.write('name_fail.fits', format='fits', overwrite=True) print("Wrote FITS successfully.") except Exception as e: print("Failed to write FITS:", e)
运行后输出:
Failed to write FITS: ('cannot represent an object', <ICRS Coordinate: (ra, dec) in deg
(266.4051, -28.936175)>)
错误原因
Galactocentric坐标系的SkyCoord对象内部包含银心的ICRS坐标参考点(galcen_coord属性),当QTable写入FITS时,会尝试用YAML序列化列的元数据,而这个ICRS坐标对象无法被YAML正常序列化,从而触发错误。
解决方法
方法1:拆分SkyCoord为单独的物理量列
将SkyCoord的位置和速度分量拆分为单独的带单位列存入QTable,避免直接存储SkyCoord对象:
from astropy.coordinates import SkyCoord from astropy.table import QTable import astropy.units as u xf, yf, zf = 8.3, 0.0, 0.02 vxf, vyf, vzf = -11.1, 232.24, 7.25 c_end = SkyCoord( x=xf*u.kpc, y=yf*u.kpc, z=zf*u.kpc, v_x=vxf*u.km/u.s, v_y=vyf*u.km/u.s, v_z=vzf*u.km/u.s, frame='galactocentric' ) # 拆分分量为单独列 tab = QTable({ 'x': c_end.x, 'y': c_end.y, 'z': c_end.z, 'v_x': c_end.v_x, 'v_y': c_end.v_y, 'v_z': c_end.v_z }) tab.write('name_success.fits', format='fits', overwrite=True) print("Wrote FITS successfully.")
后续读取时可重新组合为SkyCoord对象:
tab_read = QTable.read('name_success.fits') c_read = SkyCoord( x=tab_read['x'], y=tab_read['y'], z=tab_read['z'], v_x=tab_read['v_x'], v_y=tab_read['v_y'], v_z=tab_read['v_z'], frame='galactocentric' )
方法2:使用serialize_method='data'参数跳过元数据序列化
在写入FITS时,指定serialize_method='data',让Astropy只序列化数据部分,不处理元数据中的复杂对象:
from astropy.coordinates import SkyCoord from astropy.table import QTable import astropy.units as u xf, yf, zf = 8.3, 0.0, 0.02 vxf, vyf, vzf = -11.1, 232.24, 7.25 c_end = SkyCoord( x=xf*u.kpc, y=yf*u.kpc, z=zf*u.kpc, v_x=vxf*u.km/u.s, v_y=vyf*u.km/u.s, v_z=vzf*u.km/u.s, frame='galactocentric' ) tab = QTable([[c_end]], names=['skycoord']) try: # 添加serialize_method参数 tab.write('name_success.fits', format='fits', overwrite=True, serialize_method='data') print("Wrote FITS successfully.") except Exception as e: print("Failed to write FITS:", e)
注意:此方法写入的FITS文件,后续读取时SkyCoord的框架元数据(如galcen_coord)会使用默认值,而非原始对象的设置。如果需要保留精确的框架参数,建议使用方法1。
内容的提问来源于stack exchange,提问作者Gwald4

