如何创建带Mollweide投影的放大内嵌子图?
解决Mollweide投影主图+内嵌图的天图绘制问题
问题概述
需要制作主坐标轴与内嵌坐标轴均采用Mollweide投影的天图,主图绘制已实现,但内嵌图存在以下问题:
- 使用
ligo.skymap示例代码时,轮廓不显示且x轴反向 - 直接创建Mollweide投影内嵌图,无法设置轴范围聚焦目标天区
- 使用普通内嵌图会导致轮廓变形,不符合物理需求
现有代码
主图代码
import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl xmin = min(l) xmax = max(l) ymin = min(b) ymax = max(b) X, Y = np.meshgrid(np.linspace(xmin, xmax, 100), np.linspace(ymin, ymax, 100)) mpl.rcParams["text.usetex"] = True fig = plt.figure(1) fig.set_figheight(8) fig.set_figwidth(8) ax = plt.axes(projection='mollweide') ax.grid() # skypost为天区位置概率密度数据 plt.contour(X, Y, skypost, colors='blue', levels=[5, 50, 95])
尝试过的内嵌图代码
axesinset = plt.axes( [0.0, 0.2, 0.25, 0.25], projection='astro degrees zoom', center='110d +20d', radius='10 deg' ) plt.sca(axesinset) axesinset.contour(X, Y, skypost, colors='blue', levels=[5, 50, 95]) axesinset.grid()
可行解决方案
核心思路:直接创建Mollweide投影的内嵌轴,将所有坐标转换为弧度(符合Mollweide投影的要求),手动设置轴范围聚焦目标天区。
完整代码示例
import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl # 加载经纬度数据l、b和天区概率密度数据skypost(此处省略加载逻辑) xmin = min(l) xmax = max(l) ymin = min(b) ymax = max(b) X, Y = np.meshgrid(np.linspace(xmin, xmax, 100), np.linspace(ymin, ymax, 100)) # 主图绘制 mpl.rcParams["text.usetex"] = True fig = plt.figure(1) fig.set_figheight(8) fig.set_figwidth(8) ax = plt.axes(projection='mollweide') ax.grid() # 转换为弧度后绘制主图轮廓(Mollweide投影要求输入弧度) ax.contour(np.radians(X), np.radians(Y), skypost, colors='blue', levels=[5, 50, 95]) # 内嵌图绘制 # 1. 创建Mollweide投影的内嵌轴,参数为[左, 下, 宽, 高](归一化坐标) axesinset = plt.axes([0.0, 0.2, 0.25, 0.25], projection='mollweide') axesinset.grid() # 2. 定义目标天区的中心和半径(转换为弧度) center_l = 110 # 目标中心经度(度) center_b = 20 # 目标中心纬度(度) radius = 10 # 天区半径(度) center_l_rad = np.radians(center_l) center_b_rad = np.radians(center_b) radius_rad = np.radians(radius) # 3. 设置内嵌轴的显示范围,聚焦目标天区 axesinset.set_xlim(center_l_rad - radius_rad, center_l_rad + radius_rad) axesinset.set_ylim(center_b_rad - radius_rad, center_b_rad + radius_rad) # 4. 绘制内嵌图轮廓,同样转换为弧度 axesinset.contour(np.radians(X), np.radians(Y), skypost, colors='blue', levels=[5, 50, 95]) # 可选:调整内嵌轴刻度大小,避免重叠 axesinset.tick_params(labelsize=8) plt.show()
关键说明
- 坐标单位转换:matplotlib的Mollweide投影要求输入坐标为弧度而非角度,所有经纬度数据(包括网格和轴范围)都需要用
np.radians()转换,这是之前轮廓不显示的核心原因。 - 内嵌轴范围设置:直接使用
set_xlim()和set_ylim()传入弧度范围,即可实现目标天区的聚焦,无需依赖第三方投影。 - 避免投影冲突:放弃
astro degrees zoom投影,改用原生Mollweide投影,确保内嵌图与主图投影一致,避免轮廓变形和轴反向问题。
内容的提问来源于stack exchange,提问作者Not Sure
相关产品推荐
相关产品推荐

