如何将Matplotlib 2D补丁转为Astropy兼容的球面投影补丁?
解决方案
要实现无扭曲的球面投影椭圆(及其他自定义补丁),目前有两种标准化的原生Python方案,均基于Astropy生态,完全适配WCS变换:
1. 使用regions库(推荐,DS9 Regions原生兼容)
regions是Astropy官方维护的天文区域处理库,专门解决球面投影下的区域定义与可视化问题,支持包括椭圆在内的多种球面区域类型,完全匹配DS9的Regions功能。
步骤示例:
from astropy.io import fits from astropy.wcs import WCS from astropy.coordinates import SkyCoord import astropy.units as u from regions import SkyEllipseRegion import matplotlib.pyplot as plt # 读取FITS图像和WCS with fits.open("your_image.fits") as hdul: wcs = WCS(hdul[0].header) img_data = hdul[0].data # 创建球面椭圆区域(中心天坐标、半长轴、半短轴、方位角) # 示例:中心在(RA=10.0 deg, Dec=45.0 deg),半长轴30角分,半短轴15角分,方位角45度 center = SkyCoord(10.0, 45.0, unit="deg", frame="icrs") ellipse_region = SkyEllipseRegion( center=center, height=u.Quantity(30, "arcmin"), width=u.Quantity(15, "arcmin"), angle=u.Quantity(45, "deg") ) # 将球面区域转换为像素空间的补丁并绘制 fig = plt.figure() ax = fig.add_subplot(111, projection=wcs) ax.imshow(img_data, origin="lower", cmap="gray") ellipse_region.to_pixel(wcs).plot(ax=ax, edgecolor="red", facecolor="none", linewidth=2) plt.show()
2. 手动生成球面椭圆的像素坐标
如果需要完全自定义逻辑,可通过在天球上采样椭圆的离散点,经WCS转换为像素坐标后,用Matplotlib的Polygon补丁绘制:
步骤示例:
import numpy as np from astropy.coordinates import SkyCoord from astropy.wcs import WCS from astropy.io import fits import astropy.units as u import matplotlib.pyplot as plt from matplotlib.patches import Polygon # 读取WCS和图像 with fits.open("your_image.fits") as hdul: wcs = WCS(hdul[0].header) img_data = hdul[0].data # 定义球面椭圆参数 center = SkyCoord(10.0, 45.0, unit="deg", frame="icrs") semi_major = u.Quantity(30, "arcmin") # 半长轴 semi_minor = u.Quantity(15, "arcmin") # 半短轴 angle = u.Quantity(45, "deg") # 椭圆方位角(从北天极顺时针) # 在天球切线平面采样椭圆点 theta = np.linspace(0, 2*np.pi, 100) x = semi_major.value * np.cos(theta) * np.cos(angle.value) - semi_minor.value * np.sin(theta) * np.sin(angle.value) y = semi_major.value * np.cos(theta) * np.sin(angle.value) + semi_minor.value * np.sin(theta) * np.cos(angle.value) # 转换为天球坐标并映射到像素 ellipse_points = center.directional_offset_by(angle, u.Quantity(x, "arcmin")) ellipse_points = ellipse_points.directional_offset_by(angle + 90*u.deg, u.Quantity(y, "arcmin")) pix_x, pix_y = wcs.world_to_pixel(ellipse_points) # 创建Polygon补丁并绘制 fig = plt.figure() ax = fig.add_subplot(111, projection=wcs) ax.imshow(img_data, origin="lower", cmap="gray") ellipse_patch = Polygon(np.column_stack((pix_x, pix_y)), edgecolor="blue", facecolor="none", linewidth=2) ax.add_patch(ellipse_patch) plt.show()
关键说明:
- 普通Matplotlib补丁(如
Circle)在像素空间绘制,未考虑球面投影的畸变;上述方法均先在天球坐标系定义区域,再转换为像素坐标,因此能保证投影后无扭曲。 regions库还支持导入/导出DS9格式的Regions文件,完全满足你复刻DS9功能的需求。- 手动采样时,增加
theta的采样点数(如从100调至200)可让椭圆边缘更平滑。
内容的提问来源于stack exchange,提问作者aparajito
相关产品推荐
相关产品推荐

