TikZ-外部化 PGF 图像(例如来自 matplotlib)

TikZ-外部化 PGF 图像(例如来自 matplotlib)

我正在尝试从文件(在我的情况下由 matplotlib 创建)中包含 PGF 图形,并将它们与 TikZ-externalizing 工作流程相结合。

首先,包含 PGF 图形的好处是,标签、图例等文本使用包含 .tex 文件的字体设置进行渲染。使用的好处tikzexternalize是,在 tex 编译期间会创建 tikz 图形的 PDF,这样 (a) 耗时的 tikz 图形“构建”只需完成一次,并且 (b) 例如,发布者只需要查看和使用 tikz 图形的 PDF 版本(他们通常没有安装完整的 tikz 版本)。

我理解 PGF 是一个较低级别的框架,tikz 就是基于此框架构建的,这可能会导致一些问题。尽管如此,pgf-manual 似乎暗示上述过程原则上应该是可行的。正如之前所问过的(外部化 pgfpicture),但没有解决方案就被关闭了,我想发布一个 MWE 并发起讨论 :smile:

\documentclass{article}
\usepackage{filecontents}
\usepackage{tikz}

\begin{filecontents*}{img.pgf}
    \begingroup%
        \makeatletter%
        \begin{pgfpicture}%
            \pgfpathrectangle{\pgfpointorigin}{\pgfqpoint{3cm}{2cm}}%
            \pgfusepath{use as bounding box, clip}%
            \begin{pgfscope}%
                \pgfpathmoveto{\pgfpointorigin}%
                \pgfpathlineto{\pgfpoint{2cm}{2cm}}%
                \pgfusepath{stroke}%
            \pgftext[x=1cm,y=1cm]{\color{red}\large\selectfont 123456789}%
            \end{pgfscope}%
        \end{pgfpicture}%
        \makeatother%
    \endgroup%
\end{filecontents*}


\usetikzlibrary{external}
\tikzexternalize[mode=list and make]


\begin{document}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    The first version is based on a simple tikz text and drawing and works OK:

    \begin{figure}[h]
        \centering
        \begin{tikzpicture}
            \draw[thick,rounded corners=8pt] (0,0) -- (2,2);
            \node at (1,1){\color{red}\large\selectfont 123456789};
        \end{tikzpicture}
        \caption{... using tikz}
    \end{figure}

    \vspace{4em}

    The second version uses the pgf file that was written using \texttt{filecontents}:

    \begin{figure}[h]
        \centering
        % uncomment the tikzpicture environment for using "externalizing"
        %\begin{tikzpicture}
            \input{img.pgf}
        %\end{tikzpicture}
        \caption{... using a PGF image}
    \end{figure}
\end{document}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

将代码复制到文件中mwe.tex,然后使用

  1. pdflatex -shell-escape mwe.tex
  2. make -f mwe.makefile
  3. pdflatex -shell-escape mwe.tex

这创建了文件 one.pdf,对于所有进一步的编译运行,将直接包含该文件,而不是编译 tikzpicture。PDFmwe.pdf还显示包含的 PGF 图看起来不错。但是,当您取消注释tikzpicture第二个图的环境时,在以下过程中会出现错误make -f mwe.makefile

(./img.pgf
! TeX capacity exceeded, sorry [input stack size=5000].
\pgf@selectfontorig ->\pgf@selectfontorig 
                                          \nullfont 
l.10 ...   \pgftext[x=1cm,y=1cm]{\color{red}\large
                                                  \selectfont 123456789}% 

现在,问题是如何解决这个问题——或者如何在不手动更改/替换代码或文件的情况下调整整个工作流程?谢谢!

答案1

更新后续跟进。使用 externalize 创建两个 pdf 图形。

我将分享我的设置及其结果。(使用 MiKTeX 和 Windows)

(1)FIGURES在工作目录中创建一个子目录。

(2)添加到你的序言中

% **********************************************************
\tikzexternalize[%
up to date check={simple},
prefix=./FIGURES/]% Folder needs to be created before compiling

\tikzset{external/system call={%
        pdflatex \tikzexternalcheckshellescape
        -halt-on-error -shell-escape -interaction=batchmode
        -jobname "\image" "\texsource"}}
% **********************************************************

(3)跑步

pdflatex.exe -synctex=1 -interaction=nonstopmode -shell-escape MWE.tex

(4)这是运行后的文件树。在我的系统中,它运行两次

pdflatex: security risk: running with elevated privileges This is pdfTeX, Version 3.141592653-2.6-1.40.22 (MiKTeX 21.3)

第一次举报

===== 'mode=convert with system call': Invoking 'pdflatex -shell-escape -halt-on-error -shell-escape -interaction=batchmode -jobname "./FIG
URES/MWE-figure0" "\def\tikzexternalrealjob{MWE}\input{MWE}"' ========
(img.tex
pdflatex: security risk: running with elevated privileges
This is pdfTeX, Version 3.141592653-2.6-1.40.22 (MiKTeX 21.3)
entering extended mode
===== 'mode=convert with system call': Invoking 'pdflatex -shell-escape -halt-on-error -shell-escape -interaction=batchmode -jobname "./FIG
URES/MWE-figure1" "\def\tikzexternalrealjob{MWE}\input{MWE}"' ========
)

第二次

===== Image './FIGURES/MWE-figure0' is up-to-date. ======
(img.tex
===== Image './FIGURES/MWE-figure1' is up-to-date. ======
)

X

(5)这是输出。

是

(6)这是文件MWE.tex

    %%% File MWE.tex

% !TeX TS-program = pdflatex

\documentclass{article}
%%\usepackage{filecontents} % not needed anymore <<<<
\usepackage{tikz}   
\usetikzlibrary{external}

\begin{filecontents*}[overwrite]{img}
            \pgfpathrectangle{\pgfpointorigin}{\pgfqpoint{3cm}{2cm}}%
            \pgfusepath{use as bounding box, clip}%
            \begin{pgfscope}%
                \pgfpathmoveto{\pgfpointorigin}%
                \pgfpathlineto{\pgfpoint{2cm}{2cm}}%
                \pgfusepath{stroke}%
                \pgftext[x=1cm,y=1cm]{\color{red}\large\selectfont 123456789P}%
            \end{pgfscope}% 
\end{filecontents*}

% ********************************************************** added <<<<<<<<<<<<<<<<<<<<<<<
\tikzexternalize[%
up to date check={simple},
prefix=./FIGURES/]% Folder needs to be created before compiling

\tikzset{external/system call={%
        pdflatex \tikzexternalcheckshellescape
        -halt-on-error -shell-escape -interaction=batchmode
        -jobname "\image" "\texsource"}}
% **********************************************************

\begin{document}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    The first version is based on a simple tikz text and drawing and works OK:
    
    \begin{figure}[h]
        \centering
        \begin{tikzpicture}
            \draw[thick,rounded corners=8pt] (0,0) -- (2,2);
            \node at (1,1){\color{red}\large\selectfont 123456789T};
        \end{tikzpicture}
        \caption{... using tikz}
    \end{figure}
    
    \vspace{4em}
    
    The second version uses the pgf file that was written using \texttt{filecontents}:
    
    \begin{figure}[h]
        \centering  
        \begin{tikzpicture}     
            \input{img} % PGF file from matplotli
        \end{tikzpicture}
        \caption{... using a PGF image}
    \end{figure}

\end{document}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

答案2

错误是由于pgfpicture在环境中有环境而导致tikzpicture的。幸运的是,你可以通过定义一个节点来规避这个问题,即

\begin{tikzpicture}
  \node {\input{img}};
\end{tikzpicture}

一切都应该顺利编译。您可以使用以下命令自动执行此操作、删除多余的填充并改进外部化文件名:

\newcommand{\inputpgf}[1]{%
  \tikzsetnextfilename{#1}%
  \begin{tikzpicture}%
  \node[inner sep=0pt] {\input{#1.pgf}};
  \end{tikzpicture}
}

img.pgf然后,您可以通过导入和外部化图像\inputpgf{img}。如果img.pgf位于某个子目录中,您可以使用import包来避免更改文件内的路径:

\newcommand{\importpgf}[2]{%
  \tikzsetnextfilename{#1/#2}%
  \begin{tikzpicture}%
  \node[inner sep=0pt] {\import{#1}{#2.pgf}};
  \end{tikzpicture}
}

您可以figures/img.pgf通过 导入和外部化图像\importpgf{figures}{img}

请注意,Simon Dispa 的答案中的几乎所有更改都是无关紧要的。唯一相关的建议是pgfpictureimg.tex文件中删除环境。但这意味着编辑 matplotlib 输出,这相当繁琐,似乎并不受欢迎。

相关内容