Python 自动获取子地块的坐标,以便将其设置为图例的自动定位
我第一次尝试手动设置由生成的主情节的主图例的位置 下图表示联合分布协方差矩阵的1/2西格玛置信水平。它是由中国制造的 生成此图的主要例程是:Python 自动获取子地块的坐标,以便将其设置为图例的自动定位,python,matplotlib,position,legend,Python,Matplotlib,Position,Legend,我第一次尝试手动设置由生成的主情节的主图例的位置 下图表示联合分布协方差矩阵的1/2西格玛置信水平。它是由中国制造的 生成此图的主要例程是: # g.settings g = plots.get_subplot_plotter() g.settings.figure_legend_frame = True g.settings.legend_fontsize = 21 g.triangle_plot([matrix1, matrix2],
# 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”标题标识);注意:我希望它位于1.0和0.0 xtick之前,正好在右线边框的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_的良好值分配给_锚,以获得我想要的(由“1sigma±0.0012”标题标识的左上框顶部边框水平的y坐标)并将其从右侧推到右下框的右边框(由带有“1sigma±0.001”的sigma8标识的x坐标)标题
)
更新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\u left\u plot
和bottom\u right\u plot
的值不是好的
我认为子图[0,0]
(对于图例的顶部y坐标
)指的是左上方的子图,而子图[-1,-1]
指的是右下方的子图(对于图例的右侧x坐标
),但考虑到这一点,它不起作用
例如:
# 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
我不明白为什么在g.add\u legend
中不考虑这些值(似乎包含在0.0和1.0之间)
使用@mullinsr
的解决方案,我得到了下图:
如果我通过强制获取图例位置的坐标:
top_left_plot = 8.3
bottom_right_plot = 1.0
这看起来像这篇文章的第一个人物。但这两个值并不像它应该的那样包含在0.0和1.0之间
更新2
@mullinsr
,谢谢,我一直关注您的更新,总是遇到问题。如果我在脚本中直接应用相同的代码段,即:
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坐标
和y坐标
的轻微移动
如果我将您的代码片段应用于我的图例文本,我会得到:
我为您提供了我整个脚本的链接,与预期相比,这将更容易让您看到错误:
它基本上按照您描述的那样工作。轴的b框(xmin,ymin,width,height)
以图形的分数表示,并且plt.legend()
使用相同的格式,因此两者兼容。通过将图例的右上角设置为最外层轴定义的角,可以获得干净的布局,而不必担心图例的确切大小
导入matplotlib.pyplot作为plt
n=4
#创建子地块栅格
#备选方案:图,ax=plt.子批次(n,n);ax[i,j]。删除j>i的()
图=plt.图()
gs=图添加网格规范(nrows=n,ncols=n)
ax=np.zeros((n,n),dtype=object)
对于范围(n)中的i:
对于范围(n)内的j:
如果j它基本上按照您描述的那样工作。轴的b框(xmin,ymin,width,height)
以图形的分数表示,并且plt.legend()
使用相同的格式,因此两者兼容。通过将图例的右上角设置为最外层轴定义的角,可以获得干净的布局,而不必担心图例的确切大小
导入matplotlib.pyplot作为plt
n=4
#创建子地块栅格
#备选方案:图,ax=plt.子批次(n,n);ax[i,j]。删除j>i的()
图=plt.图()
gs=图添加网格规范(nrows=n,ncols=n)
ax=np.zeros((n,n),dtype=object)
对于范围(n)中的i:
对于范围(n)内的j:
如果j这是我的答案,它与@scleronomic的答案是一样的,但我会指出一些在解决这个问题时绊倒我的东西
下面是我复制所需定位的代码,我尝试为您创建相同的子地块布局,但通过matplotlib而不是getdist——尽管结果相同
正如您所发现的,诀窍在于提取第一个和最后一个轴(左上角和右下角)的位置数据以供参考。使用的bounds方法返回:x0、y0、轴的宽度和高度(参见文档)。然而,我们想要的是最大的x和y,因此我们的图例角位于右上角。这可以通过使用xmax和ymax方法实现:
axes.flatten()[-1].get_position().xmax
axes.flatten()[0].get_position().ymax
一旦我们有了这些变量,就可以像您所做的那样,将它们传递到add_legend()
函数的bbox\u to\u anchor
参数中。但是,如果我们也使用loc='upper right'
,它会告诉matplotlib我们希望图例的右上角固定到右上角。最后,我们需要设置borderaxespad=0
,否则图例将无法显示
import matplotlib.pyplot as plt
# code to layout subplots as in your example:
# --------------------------------------------
g, axes = plt.subplots(nrows=7, ncols=7,figsize=(10,10))
unwanted = [1,2,3,4,5,9,10,11,12,13,17,
18,19,20,25,26,27,33,34,41]
for ax in axes.flatten():
ax.plot([1,2], [1,2])
ax.set_yticks([])
ax.set_xticks([])
for n, ax in enumerate(axes.flatten()):
if n in unwanted:
ax.remove()
# Code to answer your question:
# ------------------------------
# get the max y position of the top left axis
top_left_plot = axes.flatten()[0].get_position().ymax
# get the max x position of the bottom right axis
# it is -1 to reference the last plot
bottom_right_plot = axes.flatten()[-1].get_position().xmax
# I'm using the matplotlib so it is g.legend() not g.add_legend
# but g.add_legend() should work the same as it is a wrapper of th ematplotlib func
g.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'],
loc='upper right', # we want to specify the location of this point
bbox_to_anchor=(bottom_right_plot, top_left_plot), # this is the x and y co-ords we extracted above
borderaxespad=0, # this means there is no padding around the legend
edgecolor='black') # I set it black for this example
plt.show()
bbox_transform=plt.gcf().transFigure
import getdist
from getdist import plots, MCSamples
from getdist.gaussian_mixtures import GaussianND
covariance = [[0.001**2, 0.0006*0.05, 0], [0.0006*0.05, 0.05**2, 0.2**2], [0, 0.2**2, 2**2]]
mean = [0.02, 1, -2]
gauss=GaussianND(mean, covariance)
g = plots.get_subplot_plotter(subplot_size=3)
g.triangle_plot(gauss,filled=True)
top_left_plot = g.subplots.flatten()[0].get_position().ymax
bottom_right_plot = g.subplots.flatten()[-1].get_position().xmax
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')