如何用Plotly实现Aitoff投影天图叠加散点?转图报错求解
如何用Plotly实现Aitoff投影的天文散点图
问题背景
需要在仪表板中插入一张Aitoff投影的天图,叠加从数据库获取的散点数据,参考类似Matplotlib Aitoff投影和天文坐标散点的效果。尝试用Matplotlib生成图后转Plotly失败,使用px.scatter_geo也不符合需求,运行代码时报错:ValueError: 为'data'属性接收到无效元素。
之前的尝试代码:
@app.callback( Output('aitoff', 'children'), Input('my-table', 'data') ) def add_row(data): df_grpah = pd.DataFrame(data) ra = coord.Angle(df_grpah["ra"], unit=u.hour) # 创建Angle对象 ra = ra.wrap_at(180*u.degree) dec = coord.Angle(df_grpah['dec'],unit=u.deg) print("Ra: ", ra.degree) print("Dec: ", dec.degree) fig = plt.figure(figsize=(8,6)) ax = fig.add_subplot(111, projection="aitoff") ax.scatter(ra.radian, dec.radian) ax.grid(True) figure = go.Figure(fig) return [ html.Div(children=[dcc.Graph(figure=figure, className="card")]) ]
用到的坐标数据:
Ra: [ 73.6305 56.868975 -81.49779 -28.375005 -52.832145 145.95 -175.296 -151.65 101.85 -154.5 -175.821 ] Dec: [-72.5771 26.622 23.530393 38.21 89.348426 14.7899 -28.042 30.27 25.28 17.76 -4.3204 ]
解决方案
1. 报错原因
你之前的代码报错是因为go.Figure()不能直接接收Matplotlib的fig对象作为参数,两者的图形结构完全不同,无法直接转换。
2. 用Plotly直接实现Aitoff投影散点图
Plotly本身没有内置Aitoff投影,但可以通过手动转换坐标模拟实现,步骤如下:
步骤1:坐标转换(和Matplotlib逻辑一致)
先将RA(赤经)转换为弧度并做180度环绕处理,Dec(赤纬)直接转弧度。注意需要反转RA的方向,因为Aitoff投影中RA从右到左递增,和常规笛卡尔轴方向相反。
步骤2:用Plotly散点图模拟Aitoff投影
使用go.Scatter绘制转换后的坐标,自定义网格和轴标签匹配Aitoff样式。
完整代码示例:
import plotly.graph_objects as go import pandas as pd from astropy import coord, units as u @app.callback( Output('aitoff', 'children'), Input('my-table', 'data') ) def add_row(data): df_graph = pd.DataFrame(data) # 处理坐标:和Matplotlib一致的转换逻辑 ra = coord.Angle(df_graph["ra"], unit=u.hour) ra = ra.wrap_at(180*u.degree) dec = coord.Angle(df_graph['dec'], unit=u.deg) # 转换为弧度,反转RA方向匹配Aitoff投影布局 ra_rad = -ra.radian dec_rad = dec.radian # 创建Plotly图形 fig = go.Figure() # 添加散点数据 fig.add_trace(go.Scatter( x=ra_rad, y=dec_rad, mode='markers', marker=dict(size=8, color='darkblue') )) # 自定义布局,模拟Aitoff投影样式 fig.update_layout( width=800, height=600, xaxis=dict( title='赤经 (RA)', tickmode='array', tickvals=[-3.14, -1.57, 0, 1.57, 3.14], ticktext=['180°', '90°', '0°', '270°', '180°'], gridcolor='lightgray', gridwidth=1 ), yaxis=dict( title='赤纬 (Dec)', tickmode='array', tickvals=[-1.57, -0.785, 0, 0.785, 1.57], ticktext=['-90°', '-45°', '0°', '45°', '90°'], gridcolor='lightgray', gridwidth=1 ), title='Aitoff投影天文散点图', plot_bgcolor='white' ) return [ html.Div(children=[dcc.Graph(figure=fig, className="card")]) ]
3. 补充说明
- 可以结合
astropy的坐标转换工具,确保天文坐标处理的准确性。 - Plotly的
scatter_geo主要面向地理坐标,无法直接支持天文Aitoff投影,手动转换坐标是更可行的方案。
内容的提问来源于stack exchange,提问作者Marm90
相关产品推荐
相关产品推荐

