Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 自动获取子地块的坐标,以便将其设置为图例的自动定位_Python_Matplotlib_Position_Legend - Fatal编程技术网

Python 自动获取子地块的坐标,以便将其设置为图例的自动定位

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],

我第一次尝试手动设置由生成的主情节的主图例的位置

下图表示联合分布协方差矩阵的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],
                          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')