tkz、tikz-grph、tikzexternalize 和 pythontex

tkz、tikz-grph、tikzexternalize 和 pythontex

我的代码如下:

\documentclass{minimal}

\usepackage{amsmath}
\usepackage{tikz}
\usepackage{tkz-graph}
\usepackage{pythontex}

\usetikzlibrary{external}
\tikzexternalize[]

\begin{pycode}
def gen_pop(arg_str):
    pop = list(arg_str)
    print('\\begin{{matrix}}& & {0} & &\\\\{1} & {2} & {3} & {4} & {5}\\end{{matrix}}'.format(pop[5], pop[0], pop[1], pop[2], pop[3], pop[4]))
\end{pycode}

\newcommand{\pop}[1]{
    \pyc{gen_pop('#1')}
}

\begin{document}
    \begin{tikzpicture}[yscale=1,xscale=1]
        \GraphInit[vstyle=Empty]
        \SetGraphUnit{2}
        \Vertex[L=$\pop{100000}$]{100000}
        \EA[L=$\pop{010000}$](100000){010000}
        \EA[L=$\pop{000001}$](010000){000001}
        \EA[L=$\pop{001000}$](000001){001000}
        \EA[L=$\pop{000100}$](001000){000100}
        \EA[L=$\pop{000010}$](000100){000010}

        \Vertex[L=$\pop{110000}$,a=-63.43,d=2.23]{110000}
        \EA[L=$\pop{011000}$](110000){011000}
        \EA[L=$\pop{001001}$](011000){001001}
        \EA[L=$\pop{001100}$](001001){001100}
        \EA[L=$\pop{000110}$](001100){000110}

        % ....

        \Edges(100000,110000)\Edges(010000,110000)\Edges(010000,011000)\Edges(001000,011000)
        \Edges(000100,001100)\Edges(001000,001001)\Edges(000001,001001)\Edges(000100,000110)
        \Edges(000010,000110)

        % ...
    \end{tikzpicture}
\end{document}

我稍微缩短了一点,但它应该会产生一些不平凡的东西。我的构建命令按顺序排列(pythontex 需要运行两次):

"C:\Program Files\MiKTeX 2.9\miktex\bin\x64\pdflatex" ?ame" -parse-first-line -shell-escape -enable-write18 -interaction=nonstopmode; 
"c:\program files\miktex 2.9\scripts\pythontex\pythontex.py" ?ame"; 
"C:\Program Files\MiKTeX 2.9\miktex\bin\x64\pdflatex" ?ame" -parse-first-line -shell-escape -enable-write18 -aux-directory="C:\tmp" -synctex=1 -interaction=nonstopmode

问题是tikzexternalize没有捕捉到所做的更改pythontex。它没有显示节点标签(即由 python 代码生成的矩阵),因此它只显示外部化 pdf 中的边。是否可以使用 pythontex 将其外部化?

如果我尝试通过使用\pop{}正确的 LaTeX 代码替换宏来解决上述问题,则会出现另一个问题,如下所示:

% ...
%1
\Vertex[L=$\begin{matrix}&&0&&\\1&0&0&0&0\end{matrix}$]{100000}
\EA[L=$\begin{matrix}&&0&&\\0&1&0&0&0\end{matrix}$](100000){010000}
\EA[L=$\begin{matrix}&&1&&\\0&0&0&0&0\end{matrix}$](010000){000001}
\EA[L=$\begin{matrix}&&0&&\\0&0&1&0&0\end{matrix}$](000001){001000}
\EA[L=$\begin{matrix}&&0&&\\0&0&0&1&0\end{matrix}$](001000){000100}
\EA[L=$\begin{matrix}&&0&&\\0&0&0&0&1\end{matrix}$](000100){000010}
% ...

然后它抱怨说

Use of \tikz@@scope@env doesn't match its definition. ...rix}&&0&&\\1&0&0&0&0\end{matrix}$]{100000}

如果没有外部化,一切都会按预期工作。除了像使用 python 一样生成整行\EA[L=$\pop{001001}$](011000){001001}也会导致上述错误。似乎 pythontex 很好地封装了矩阵代码,以至于 tikz 可以处理它。但如果直接在那里输入它,它就不起作用了。

无论如何,我将非常感谢任何帮助!

答案1

鉴于他们目前的工作方式,似乎没有一种简单的方法可以实现pythontex合作。除非绝对必要,否则tikzexternalize最好避免。tikzexternalize

pythontex将所有代码保存到外部文件,处理代码,然后在下次编译时将输出带回来。它使用\jobname与计数器结合的版本跟踪哪个输出与哪个命令一起使用。 tikzexternalize使用自定义重新编译每个图片的文档,\jobname其中除了当前tikzpicture环境之外的所有内容都被“禁用”。所以第一个问题是tikzexternalize发生了变化\jobname,这意味着pythontex找不到任何东西。可以用类似这样的方法修复:

\makeatletter
\tikzifexternalizing{
  \def\pytx@jobname{\tikzexternalrealjob}
  \def\pytx@outdir{pythontex-files-\tikzexternalrealjob}
}{}
\makeatother

这应该在 之后\tikzexternalize

这样就可以pythontex找到输出(如果有的话)。但现在的问题是,它的内容在某种程度上对主文档而言是“不可见的”。因此,主文档实际上从未处理过命令tikzexternalize,也从未生成输出。tikzpicture\pyc

要解决该问题,您需要在环境tikzpicture中生成整个pycode然后打印它。这应该会让您回到错误\tikz@@scope@env。由于默认pythontex方法在没有的情况下也有效tikzexternalize,您可以尝试复制它。这将涉及在宏中保存去标记化的版本\begin{matrix}...\end{matrix},然后\scantokens在使用时使用重新标记它。可能还有其他方法可以做到这一点;这就是所做的pythontex,似乎有效。的相关部分pythontex.sty是的定义\pytx@SVMCR。不幸的是,所有这些都会使事情变得比没有的情况复杂得多tikzexternalize

相关内容