外部化 PGF

外部化 PGF

我有一堆使用 Matplotlib 的 PGF 后端制作的图表。为了避免在样式发生变化时使用 Matplotlib 重新生成所有这些图表,我更喜欢\input直接在文档中使用 PGF 文件。这很好,但这意味着 arXiv 不允许我的 16 MB 源。

有没有办法可以像处理 TikZ 文件一样将 PGF 文件外部化?我真的想避免重新生成所有图,因为这非常耗时。

答案1

一种解决方法是生成一个单独的 PDF pgfpicture,每页一个,然后将输入替换为\includegraphicsstandalone该类使这变得简单,例如:

\documentclass{standalone}
\usepackage{pgf}
\standaloneenv{pgfpicture}
\begin{document}
\input{onefigure.pgf}
\input{anotherfigure.pgf}
\end{document}

将其保存为 egfigs.tex并进行编译。在您的手稿中,将\includegraphics[page=1]{figs}其替换为\input{onefigure},其他的类似操作。当然,如果愿意的话,您可以为每个图创建一个 PDF。

答案2

我遇到了同样的问题,并编写了自己的包来自动处理它。你可以找到它这里。如果您不想安装该软件包,您可以将此代码放入您的序言中:

\makeatletter
\edef\@figdir{_pgfcache}

\catcode`\#=11
\catcode`\|=6
\newcommand{\@basicpgfpreamble}[1]{%
    \unexpanded{%
        \documentclass{standalone}^^J
        \usepackage{pgf}^^J
        \let\oldpgfimage\pgfimage^^J
        \renewcommand{\pgfimage}[2][]{\oldpgfimage[#1]{|1/#2}}^^J
    }%
}
\catcode`\#=6
\catcode`\|=12

\let\@pgfpreamble\@basicpgfpreamble

\newcommand{\setpgfpreamble}[1]{%
    \renewcommand{\@pgfpreamble}[1]{\@basicpgfpreamble{##1}\unexpanded{#1}}
}

\newcounter{@pgfcounter}
\newwrite\@pgfout
\newread\@pgfin

\newcommand{\importpgf}[3][]{%
    \IfFileExists{#2/#3}{}{\errmessage{importpgf: File #2/#3 not found}}%
    \edef\@figfile{\jobname-\the@pgfcounter}%
    \providecommand{\@writetempfile}{}%
    \renewcommand{\@writetempfile}[1]%
    {%
        \immediate\openout\@pgfout=##1%
        \immediate\write\@pgfout{\@pgfpreamble{#2}}%
        \immediate\write\@pgfout{\string\begin{document}}%
        \immediate\openin\@pgfin=#2/#3%
        \begingroup\endlinechar=-1%
            \loop\unless\ifeof\@pgfin%
                \readline\@pgfin to \@fileline%
                \ifx\@fileline\@empty\else%
                    \immediate\write\@pgfout{\@fileline}%
                \fi%
            \repeat%
        \endgroup%
        \immediate\closein\@pgfin%
        \immediate\write\@pgfout{\string\end{document}}%
        \immediate\closeout\@pgfout%
    }%
    \def\@compile%
    {%
        \immediate\write18{pdflatex -interaction=batchmode -output-directory="\@figdir" \@figdir/\@figfile.tex}%
    }%
    \IfFileExists{\@figdir/\@figfile.pdf}%
    {%
        \@writetempfile{\@figdir/tmp.tex}%
        \edef\@hashold{\pdfmdfivesum file {\@figdir/\@figfile.tex}}%
        \edef\@hashnew{\pdfmdfivesum file {\@figdir/tmp.tex}}%
        \ifnum\pdfstrcmp{\@hashold}{\@hashnew}=0%
            \relax%
        \else%
            \@writetempfile{\@figdir/\@figfile.tex}%
            \@compile%
        \fi%
    }%
    {%
        \@writetempfile{\@figdir/\@figfile.tex}%
        \@compile%
    }%
    \IfFileExists{\@figdir/\@figfile.pdf}%
    {\includegraphics[#1]{\@figdir/\@figfile.pdf}}%
    {\errmessage{Error during compilation of figure #2/#3}}%
    \stepcounter{@pgfcounter}%
}
\makeatother

这为您提供了两个命令,\setpgfpreamble并且\importpgf.\importpgf执行两件事:

  1. 检查名为 的文件夹中是否已存在图形的预编译 PDF 版本_figurecache(您可能需要创建此文件夹)。如果是,它只会使用 包含该 PDF \includegraphics。如果没有,它会调用pdflatex编译图形,然后包含它。如果图形的来源发生变化(通过文件的 MD5 校验和检查),也会重新编译图形。

  2. 它会修补\pgfimagePGF 图形中的命令,因此您可以包含使用 Matplotlib 创建的栅格化部分,即使它们位于子文件夹中(如上所述这里)。

您可以像这样使用命令:

\importpgf{path/to/file}{myfigure.pgf}

使用\setpgfpreamble,您可以定义编译 PGF 图像所需的附加包(例如字体或数学包):

\setpgfpreamble{%
    \usepackage{libertine}
    \usepackage{amsmath}
    \usepackage{siunitx}
}

唯一的依赖项是standalonepgf包。如果您有大量图形,第一次编译将需要很长时间,但后续编译将快得多。

注意事项:它可能不太便携(仅在您使用 PDFLaTeX 时才有效;pdflatex可执行文件必须在您的路径上;并且您必须使用 进行编译-shell-escape)。此外,错误检查是有限的,因此如果您遇到麻烦,请检查文件夹中的日志_figurecache以查找错误(您可能忘记包含 包\setpgfpreamble)。

答案3

这是一个不太好的解决方案,可能在任何情况下都行不通。其思路是先用环境替换pgfpicture环境tikzpicture,然后使用外部化。

为此,您可以:

  1. 使用包在宏中读取您的文件catchfile
  2. patchcmd使用来修补此宏etoolbox以替换pgfpicturetikzpicture
  3. 把所有这些都放入一个\mypgfimport设置的宏中\tikzsetfigurename

以下是代码:

% ------------------------------------
% example file blablatest.pgf
\begin{filecontents}{blablatest.pgf}
\begin{pgfpicture}
\pgfpathsvg{M 0 0 l 20 0 0 20 -20 0 q 10 0 10 10
t 10 10 10 10 h -50 z}
\pgfusepath{stroke}
\end{pgfpicture}
\end{filecontents}
% ------------------------------------
\documentclass[border=7mm]{standalone}
\usepackage{catchfile}
\usepackage{etoolbox}
\usepackage{tikz}
\usepgflibrary{svg.path}
\usetikzlibrary{external}\tikzexternalize

\def\mypgfimport#1{%
  \tikzsetfigurename{#1}
  \CatchFileDef{\tempmacro}{#1.pgf}{}%
  \patchcmd{\tempmacro}{\begin{pgfpicture}}{\begin{tikzpicture}[red]}{}{}%
  \patchcmd{\tempmacro}{\end{pgfpicture}}{\end{tikzpicture}}{}{}%
  \tempmacro%
}

\begin{document}
  \mypgfimport{blablatest}
\end{document}

在此处输入图片描述

相关内容