Matplotlib 如何在OpenTURNS中设置图形外部的图例?

Matplotlib 如何在OpenTURNS中设置图形外部的图例?,matplotlib,openturns,Matplotlib,Openturns,我想用OpenTURNS创建高斯样本对数似然的等高线图。每个等高线映射到一个函数值,该函数值由绘图图例指示。问题是图例在某种程度上隐藏了轮廓:如何设置绘图,使图例不隐藏内容 这里有一个例子。我创建了一个正态分布,对应于年龄在20到79岁之间的男性的身高(见“美国人口普查局统计摘要”) 表209.2012)。然后我从这个分布生成一个样本。我定义了对数似然函数,它接受输入向量(mu,sigma),并返回包含输出对数似然的一维向量。我可以使用此函数的draw方法创建等高线图 import opentu

我想用OpenTURNS创建高斯样本对数似然的等高线图。每个等高线映射到一个函数值,该函数值由绘图图例指示。问题是图例在某种程度上隐藏了轮廓:如何设置绘图,使图例不隐藏内容

这里有一个例子。我创建了一个
正态
分布,对应于年龄在20到79岁之间的男性的身高(见“美国人口普查局统计摘要”) 表209.2012)。然后我从这个分布生成一个样本。我定义了对数似然函数,它接受输入向量(mu,sigma),并返回包含输出对数似然的一维向量。我可以使用此函数的
draw
方法创建等高线图

import openturns as ot
import openturns.viewer as otv

mu = 1.763
sigma = 0.0680
N = ot.Normal(mu, sigma)
sample_size = 100
sample = N.getSample(sample_size)

def loglikelihood_gauss(X):
    """Compute the log-likelihood of a Gaussian sample."""
    mu, sigma = X
    N = ot.Normal(mu, sigma)
    log_pdf = N.computeLogPDF(sample)
    sample_size = sample.getSize()
    log_likelihood = log_pdf.computeMean() * sample_size
    return log_likelihood

# Contour plot
logLikelihoodFunction = ot.PythonFunction(2, 1, loglikelihood_gauss)
ot.ResourceMap_SetAsUnsignedInteger("Contour-DefaultLevelsNumber", 5)
graph = logLikelihoodFunction.draw([1.65, 0.04], [1.85, 0.15], [50]*2)
graph.setXTitle(r"$\mu$")
graph.setYTitle(r"$\sigma$")
graph.setTitle("Log-Likelihood.")
view = otv.View(graph)
这将产生:


如何设置绘图以使图例不隐藏等高线?

第一个技巧是使用
legend
matplotlib函数的
bbox\u to\u anchor
选项。这是可能的,因为所有OpenTURNS图形都来自Python层的Matplotlib。第二个技巧是基于
getFigure
方法从
视图
对象中获取图形。如果没有进一步的代码,将生成第二个图例,该图例位于正确的位置,但会复制该图例。第三个技巧是通过将内容设置为空字符串来隐藏旧的图例

logLikelihoodFunction = ot.PythonFunction(2, 1, loglikelihood_gauss)
ot.ResourceMap_SetAsUnsignedInteger("Contour-DefaultLevelsNumber", 5)
graph = logLikelihoodFunction.draw([1.65, 0.04], [1.85, 0.15], [50]*2)
graph.setXTitle(r"$\mu$")
graph.setYTitle(r"$\sigma$")
graph.setTitle("Log-Likelihood.")
legends = graph.getLegends()
graph.setLegendPosition("")
view = otv.View(graph)
figure = view.getFigure()
figure.legend(legends, bbox_to_anchor=(1.1, 0.9))

功能非常好!我经常为图例太大的图表感到尴尬。您可以使用以下方法改进脚本:

graph.setLegendPosition('')
而不是:

graph.setLegends([""] * 5)

它避免了您在图表中计算可绘制图形的数量。

不幸的是,如果您混合使用不同类型的可绘制图形,则效果不佳:

import openturns as ot
import openturns.viewer as otv

f = ot.SymbolicFunction(["x", "y"], ["x^4+y^4-8*(x^2+y^2)"])
graph = f.draw([-4.0]*2, [4.0]*2)
graph.setLegendPosition("bottomleft")
graph.add(ot.Curve([[-4.0]*2, [4.0]*2], "red", "dashed", 1.0, "line"))
graph.add(ot.Cloud([[0.0]*2], "black", "fcircle", "point"))
legends = graph.getLegends()
view = otv.View(graph)
figure = view.getFigure()
figure.legend(legends, bbox_to_anchor=(1.0, 1.0))
在生成的图形上,您可以看到新图例已将点和线的标签与前两个isovalues的标签分开。获取图例标签的正确方法是:

_, legends = view._ax[0].get_legend_handles_labels()