【问题标题】:How to set the legends outside of the graphics in OpenTURNS?如何在 OpenTURNS 的图形之外设置图例?
【发布时间】:2021-03-17 22:27:25
【问题描述】:

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

这是一个例子。我创建了一个Normal 分布,对应于 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)

这会产生:

如何设置绘图使图例不隐藏轮廓?

【问题讨论】:

    标签: matplotlib openturns


    【解决方案1】:

    第一个技巧是使用legend matplotlib 函数的bbox_to_anchor 选项。这是可能的,因为所有 OpenTURNS 图形都来自 Python 层的 Matplotlib。第二个技巧是从View 对象中获取图形,基于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))
    

    保存图形时,图例可能会被裁剪。可能需要使用bbox_inches 选项:

    figure.savefig("filename.png", bbox_inches="tight")
    

    【讨论】:

      【解决方案2】:

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

      graph.setLegendPosition('')
      

      代替:

      graph.setLegends([""] * 5)
      

      它避免了你计算你在图中的drawables的数量。

      【讨论】:

        【解决方案3】:

        不幸的是,如果你混合不同类型的可绘制对象,它就不能很好地工作:

        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))
        

        在结果图中,您会看到新的图例已将点的标签和线的标签与前两个等值的标签颠倒了。获取图例标签的正确方法是:

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

        【讨论】:

          猜你喜欢
          • 2019-06-18
          • 2019-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-10
          相关资源
          最近更新 更多