我的代码如下:
\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
。