如何使用 FPDF 和 Streamlit 将子图保存为 PDF

How to save subplot as PDF using FPDF and Streamlit

我有一个要保存为 PDF 的子图。我正在尝试在 Streamlit 应用程序中执行此操作并创建我正在使用 FPDF 库的 PDF。 子图工作没有任何问题。问题是我无法将其另存为 PDF,因为会显示一条错误消息,指出我要保存的图形未定义。 这就是我创建包含子图的图形的方式:

fig1, (ax1, ax2) = plt.subplots(1, 2)

hip_angle, _, _ = angle_calculation(merged)
hip_angle_2, _, _ = angle_calculation(merged_2)

sub_plotting(freq_left, hip_angle_2, 'Hip angle - Left leg', ax1)
sub_plotting(freq_right, hip_angle, 'Hip angle - Right leg', ax2)
ax1.set_xlabel('Gait phase %')
ax2.set_xlabel('Gait phase %')
ax1.set_ylabel('Angle (degrees)')
ax2.set_ylabel('Angle (degrees)')
ax1.set_xticks(np.arange(0, 110, step=10))
ax2.set_xticks(np.arange(0, 110, step=10))
ax1.set_ylim([-20, 50])
ax2.set_ylim([-20, 50])

ax1.set_aspect('auto')
ax2.set_aspect('auto')

fig1.set_figheight(8)
fig1.set_figwidth(18)
st.pyplot(fig1)

# Here I am just creating a button to download the figure

fig = 'Hip angle.png'
plt.savefig(fig)
with open(fig, "rb") as f:
    btn = st.download_button(
        label="Descarregar imagem",
        data=f,
        file_name=fig,
        mime="image/png")

这就是我用来尝试保存 PDF 中的图形的方法。

checkbox = st.checkbox('Name', value='')
if checkbox:
    name = st.text_input('Nome do utente', value=' ')

    st.download_button(
        label="Descarregar relatório",
        data=create_pdf(fig1),
        file_name="Relatório.pdf",
        mime="application/pdf",
    )

正如我提到的,有一个错误指出 fig1 未定义。 这是我用来创建 PDF 模板的函数。

def create_pdf(figure1):

    pdf = FPDF()
    pdf.add_page()

    figure = io.BytesIO()
    figure1.savefig(figure, format="png")
    saved_fig = tempfile.NamedTemporaryFile()

    with open(f"{saved_fig.name}.png", 'wb') as sf:
        sf.write(figure.getvalue())

    pdf.set_xy(30, 50)
    pdf.image(figure1, w=140, h=110)
    figure.close()

    return bytes(pdf.output())

这是一个适用于 pdf 下载的简化代码。我们首先基于 png 文件创建 pdf 文件。创建后,我们将其用于下载。

代码
import matplotlib.pyplot as plt
import streamlit as st 
from fpdf import FPDF


def create_pdf(img_fn, pdf_fn):
    """
    Create pdf written to pdf_fn with the image file img_fn.
    """
    pdf = FPDF()
    pdf.add_page()

    # Save to pdf
    pdf.set_xy(30, 50)
    pdf.image(img_fn, w=140, h=110)
    pdf.output(pdf_fn)


def main():
    x = [1, 2, 3, 4, 5, 6]
    y = [1, 5, 3, 5, 7, 8]

    fig1, (ax1, ax2) = plt.subplots(1, 2)

    ax1.plot(x, y)
    ax2.scatter(x, y)

    st.pyplot(fig1)

    # Save to png
    img_fn = 'Hip angle.png'
    fig1.savefig(img_fn)

    # Prepare file for download.
    dfn = 'angle.png'
    with open(img_fn, "rb") as f:
        st.download_button(
            label="Descarregar imagem",
            data=f,
            file_name=dfn,
            mime="image/png")

    # pdf download
    checkbox = st.checkbox('Name', value='')
    if checkbox:
        pdf_fn = 'mypdf.pdf'
        create_pdf(img_fn, pdf_fn)

        with open(pdf_fn, 'rb') as h_pdf:
            st.download_button(
                label="Descarregar relatório",
                data=h_pdf,
                file_name="Relatório.pdf",
                mime="application/pdf",
            )


if __name__ == '__main__':
    main()
输出

下载的 png 输出:

已下载 pdf 输出