multiple-page pdf 中 matshow() 的字幕

Captions for matshow()s in multiple-page pdf

我已经解决这个问题很长时间了,但我找不到答案。

所以,我有一个包含我想要绘制的矩阵的列表(为了这个问题,我只有 2 个随机矩阵:

list = [np.random.random((500, 500)), np.random.random((500, 500))]

然后我想在 pdf 文件的单独页面中使用 matshow 绘制列表的每个元素:

with PdfPages('file.pdf') as pdf:
    plt.rc('figure', figsize=(3,3), dpi=40)
    for elem in list:
        plt.matshow(elem, fignum=1)
        plt.title("title")
        plt.colorbar()
        plt.text(0,640,"Caption")
        pdf.savefig()  # saves the current figure into a pdf page
        plt.close()

结果如下:

我的问题出在标题上。你可以看到我故意把 "Caption" 放在文档的边缘。这是因为有时我要插入的实际标题太大,无法放在一个 pdf 页面中。

那么,如何使每个 pdf 页面都可以根据标题的内容进行调整(每个页面可能有所不同)?例如,是否可以将每个页面大小设置为 A4 或 A3,然后 plot/write 每个页面中的所有内容?

我已经尝试设置 plt.figure(figsize=(X, X)) 大小为 X 的变量,但我猜它只是改变了 pdf 的分辨率。

我想我已经自己想出了这个问题的答案,它解决了我的文本有足够 space 的问题:

但是,一个完美的答案是根据我放置的标题数量使每个页面的大小动态变化。

无论如何,我的答案如下(我基本上将每一页分成 3 行的网格,上面的 2 行用于绘图,最后一行仅用于标题):

with PdfPages('file.pdf') as pdf:
    for elem in list:
        fig = plt.figure(figsize=(8.27, 11.69), dpi=100)

        grid_size = (3,1)

        plt.subplot2grid(grid_size, (0, 0), rowspan=2, colspan=1)

        plt.imshow(elem)
        plt.title("title")
        plt.colorbar()

        plt.subplot2grid(grid_size, (2, 0), rowspan=2, colspan=1)
        plt.axis('off')
        plt.text(0,1,"Caption")

        plt.tight_layout()
        pdf.savefig()
        plt.close()

在每个页面中生成以下内容:

有人能找到更好的解决方案吗? :)

您可能希望在保存文件时使用 bbox_inches="tight" 选项。这将使图形大小适应其内容。因此,只需将一些文本放在图形坐标中的 (0,0) 位置并将其与顶部对齐即可。然后这将延伸到图形的底部和外部(因此屏幕上显示的图形不会包含该文本),但是使用 savefig 的 bbox_inches="tight" 选项,保存的图形将变得足够大以包含该文本。
使用 textwrap 包还可以限制水平方向的文本。

import numpy as np; np.random.seed(1)
import textwrap 
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages

p = np.ones(12); p[0] = 7
text2 = "".join(np.random.choice(list(" abcdefghijk"),p=p/p.sum(), size=1000))
text2 = textwrap.fill(text2, width=80)
texts = ["Caption: Example", "Caption 2: " + text2 ]

lis = [np.random.random((500, 500)), np.random.random((500, 500))]

with PdfPages('file.pdf') as pdf:
    for elem,text in zip(lis,texts):
        fig = plt.figure(dpi=100)

        grid_size = (3,1)

        plt.imshow(elem)
        plt.title("title")
        plt.colorbar()

        fig.text(0,0, text, va="top")

        plt.tight_layout()
        pdf.savefig(bbox_inches="tight")
        plt.close()