python - 自动获取子图的坐标,以便将它们设置为图例的自动定位
问题描述
我第一次尝试手动设置Getdist 工具生成的主图的主要图例的位置。
下图表示来自具有联合分布的协方差矩阵的 1/2 sigma 置信水平。它由Getdist 工具生成。
生成此图的主要例程是:
# g.settings
g = plots.get_subplot_plotter()
g.settings.figure_legend_frame = True
g.settings.legend_fontsize = 21
g.triangle_plot([matrix1, matrix2],
names,
filled = True,
contour_colors = ['darkblue','red'],
line_args = [{'lw':2, 'color':'darkblue'},
{'lw':2, 'color':'red'}]
)
g.add_legend(['Opt. Flat. No Gamma. - cross - standard situation - Criterion taking into accound a = 200',\
'Pess. Flat. No Gamma. - cross - standard situation - Criterion taking into account a = 300' ],\
bbox_to_anchor = [1.5, 8.5])
该值1.5
似乎对应于 x 坐标(宽度)8.5
对应于图例的 y 坐标(高度)。
现在,我想自动执行此过程,而不是每次手动设置图例的位置。
我希望图例的右上角位于第一个左上框的顶部边框(就在“1sigma ± 0.0012”标题下方的顶线边框级别)。
我还希望将图例推到图的右侧(直到图右下框的右边框:标识为sigma8
"1sigma ± 0.001" title
; 注意:我希望它位于 1.0 和 0.0 xticks 之前,就在 x - 右线边界的坐标)。
在这里,我试图获取此左上框的顶部边框的全局坐标(整个图):
# First, get y coordinates of top border for first Likelihood
box1 = g.subplots[0,0]
box1_coords = box1._position.bounds
print('box1_coords = ', box1_coords)
我在执行时得到以下值:
box1_coords = (0.125, 0.7860975609756098, 0.09451219512195125, 0.09390243902439022)
如您所见,这些值似乎已标准化,所以如果我想将这些值插入到:
bbox_to_anchor = [box1_coords[0], box1_coords[1]]
正如预期的那样,这行代码为图例产生了错误的位置。
那么,我怎样才能设法自动为 bbox_to_anchor 分配好的值以获得我想要的("1sigma ± 0.0012" title
由框(由 sigma8 标识的 x 坐标"1sigma ± 0.001" title
)?
更新 1
我试图使它们适应我的情况,但问题仍然存在。这是我所做的:
# g.settings
g = plots.get_subplot_plotter()
# get the max y position of the top left axis
top_left_plot = g.subplots[0,0].axes.get_position().ymax
# get the max x position of the bottom right axis
# it is -1 to reference the last plot
bottom_right_plot = g.subplots[-1,-1].axes.get_position().xmax
我不知道为什么价值top_left_plot
和bottom_right_plot
不是好的价值。
我认为subplots[0,0]
(对于y-coordinate
图例的顶部)是指左上角的子图和subplots[-1,-1]
右下角的子图(对于x-coordinate
图例的右侧),但考虑到这一点,它不起作用。
例如 :
# g.settings
g = plots.get_subplot_plotter()
# Call triplot
g.triangle_plot([matrix1, matrix2],
names,
filled = True,
legend_labels = [],
contour_colors = ['darkblue','red'],
line_args = [{'lw':2, 'color':'darkblue'},
{'lw':2, 'color':'red'}])
g.add_legend(['Opt. Flat. No Gamma. - cross - standard situation - Criterion taking into accound a = 200',
'Pess. Flat. No Gamma. - cross - standard situation - Criterion taking into account a = 300'],
legend_loc='upper right',
bbox_to_anchor=(bottom_right_plot, top_left_plot)
)
我得到:
legend_coords y_max, x_max 0.88 0.9000000000000001
我不明白为什么这些值(似乎包含在 0.0 和 1.0 之间)没有被考虑在内g.add_legend
。
使用@mullinscr
的解决方案,我得到下图:
如果我通过强制获取图例位置的坐标:
top_left_plot = 8.3
bottom_right_plot = 1.0
这看起来像这篇文章的第一个图。但是这两个值并不像它应该的那样包含在 0.0 和 1.0 之间。
更新 2
@mullinscr
,谢谢,我关注了你的更新,总是遇到问题。如果我直接在我的脚本中应用相同的代码片段,即:
g.add_legend(['An example legend - item 1'],
legend_loc='upper right', # we want to specify the location of this point
bbox_to_anchor=(bottom_right_plot, top_left_plot),
bbox_transform=plt.gcf().transFigure, # this is the x and y co-ords we extracted above
borderaxespad=0, # this means there is no padding around the legend
edgecolor='black')
然后我得到下图:
如您所见,坐标并不是真正预期的:在x-coordinate
和上稍有偏移y-coordinate
。
如果我将您的代码片段应用于我的图例文本,我会得到:
我给你我整个脚本的链接,这可能会让你更容易看到与预期相比的错误:
解决方案
它基本上像你描述的那样工作。轴的 bbox(xmin, ymin, width, height)
以图中的分数给出,并plt.legend()
使用相同的格式,因此两者是兼容的。通过将upper right
图例的角设置为由最外轴定义的角,您可以获得干净的布局,而不必担心图例的确切大小。
import matplotlib.pyplot as plt
n = 4
# Create the subplot grid
# Alternative: fig, ax = plt.subplots(n, n); ax[i, j].remove() for j > i
fig = plt.figure()
gs = fig.add_gridspec(nrows=n, ncols=n)
ax = np.zeros((n, n), dtype=object)
for i in range(n):
for j in range(n):
if j <= i:
ax[i, j] = fig.add_subplot(gs[i, j])
# add this to make the position of the legend easier to spot
ax[0, -1] = fig.add_subplot(gs[0, -1])
# Plot some dummy data
ax[0, 0].plot(range(10), 'b-o', label='Dummy Label 4x4')
# Set the legend
y_max = ax[0][0].get_position().ymax
x_max = ax[-1][-1].get_position().xmax
fig.legend(loc='upper right', bbox_to_anchor=(x_max, y_max),
borderaxespad=0)
plt.show()
Constrained Layout
保存文件时可能会出现一些陷阱,bbox_inches='tight'
因为两者都会以意想不到的方式搞砸图例的位置。
有关图例放置的更多示例,我发现此集合 非常有用。
推荐阅读
- alfresco - 限制添加外部用户
- angular - 如何在项目中使用 Angular 库中的服务
- javascript - 内部的 HML 表仅提供包含完整数据的单个数据
- ruby-on-rails - Rails 5.2 使用 AWS 的主动存储(本地开发)
- mysql - 如何同步调用 google-bigquery 删除和插入 API?
- javascript - 如何从 lambda 函数中传递数据
- java - MySql count (*) 在 ResultSet 和 WorkBench 中返回不同的值
- events - 在 VBScript 中处理 COM 事件取消
- c++ - 什么是 C++ 中的“变量‘i’未在范围内声明”?
- java - JPA @JoinColumn 无法与 REST 一起正常工作