预编译分子以加快编译速度

预编译分子以加快编译速度

我在一个文件中有大约一百个用 chemfig 绘制的分子,我将其视为一种数据库。编译此文件大约需要五分钟。我要写一份五六十页的报告,这些分子将插入该文件中。

我想避免主文件的编译花费很长时间,因此我的问题是:是否可以在主文件中使用数据库中已编译的代码?

编辑:按照 Christian 的建议,我尝试设置 tikzexternalize 库。我明白必须将代码放在chemfigtikzpicture 环境中并使用 temp 前缀。我正在用这个字符串编译文件:pdflatex --file-line-error --synctex=1 --shell-escape ext,其中 ext 是文件的名称。

这是我的 MWE:

\documentclass[12pt,twoside,openright]{book}
\usepackage[T1]{fontenc}
\usepackage[applemac]{inputenc}
\usepackage{chemfig,chemnum,}
\usetikzlibrary{external}
\tikzexternalize[prefix=temp/, only named=true]
\begin{document}
\begin{tikzpicture}
\chemname{\chemfig{A=B-C-D}}{\cmpd{example}}
\end{tikzpicture}
\end{document}

我还没有彻底测试过它,但目前它可以正确地为每个分子创建单独的 pdf 图片文件,基本上避免了每次都进行完全重新编译。

一个小问题是它chemname不再起作用了。有什么想法吗?

答案1

您不能将externaltikzlibrary 与 chemfig 一起使用,因为它的\tikzexternal@laTeX@collect@until@end@tikzpicture宏在执行时\begin{tikzpicture}会收集所有内容直到找到\end{tikzpicture}

external当tikzlibrary 与 chemfig 一起使用时会出现一个问题,因为:

  1. 没有,\end{tikzpicture}但是\endtikpicture
  2. \begintikpicture\endtikpicture属于同一个宏。

这会导致错误。可以通过在a和\chemfig{<code>}之间包装 every 来修复此问题,但如果您有许多命令,则这需要时间。\begin{tikzpicture}\end{tikspicture}\chemfig

也可以修改 chemfig 代码使其自动执行:

\documentclass{article}
\usepackage{chemfig}
\usetikzlibrary{external}
\tikzexternalize
\makeatletter
\def\CF@chemfig@iii[#1][#2]{%
    \edef\CF@tmp@str{\noexpand\begin{tikzpicture}[remember picture,every node/.style={anchor=base,inner sep=\z@,outer sep=\z@,minimum size=\z@\ifx\@empty#2\@empty\else,#2\fi},baseline\ifx\@empty#1\@empty\else,#1\fi]}%
    \begingroup
        \everyeof{\@nil}\endlinechar\m@ne
        \CF@sanitize@catcode
        \CF@chemfig@iv
}

\def\CF@chemfig@iv#1{%
    \CF@tmp@str
        \let\CF@hook@list\@empty
        \ifx\CF@atom@sep\@empty\def\CF@atom@sep{3em}\fi
        \ifx\CF@cram@basewidth\@empty\def\CF@cram@basewidth{1.5ex}\fi
        \CF@incyclefalse
        \CF@cnt@groupnumber\z@
        \let\CF@last@action\z@% 0=d\'ebut du dessin 1=trac\'e d'un noeud 2=trac\'e d'une liaison
        \let\CF@start@offset\@empty
        \let\CF@end@offset\@empty
        \let\CF@bond@outcontentsaved\@empty
        \def\CF@cycle@anglecorrection{180/\CF@cycle@num}%
        \def\CF@default@angle{0}%
        \def\CF@default@stringangle{:0}% angle pris par d\'efaut si le champ est vide
        \def\CF@default@length{1}%
        \let\CF@default@fromatom\@empty% numero de l'atome d'o\`u partent les liaisons par d\'efaut
        \let\CF@default@toatom\@empty% num\'ero de l'atome o\`u arrivent les laisons par d\'efaut
        \let\CF@default@tikz\@empty
        \let\CF@previous@bondangle\empty
        \let\CF@joinbond\z@
        \let\CF@previous@tikz\empty
        \expandafter\assign@tonil\expandafter\CF@remain@molecule\scantokens{#1}%
        \expandafter\CF@chemfig@v\expandafter{\CF@remain@molecule}%
    \end{tikzpicture}%
    \endgroup
    \let\CF@split@state\z@
}
\def\CF@chemfig@vi{%
    \let\CF@next@action\CF@chemfig@vi% \`a priori, on reboucle
    \ifx\CF@remain@molecule\@empty
        \let\CF@next@action\empty
    \else
        \CF@seek@submol
        \expandafter\CF@seek@node\expandafter{\CF@remain@molecule}\CF@current@atomgroup\CF@remain@molecule
        \ifx\@empty\CF@current@atomgroup% pas de noeud pour commencer ?
            \def\CF@bond@outnode{n\CF@last@groupnumber-%
                 \ifx\CF@current@fromatom\@empty
                     \ifdim\CF@current@angle pt<90pt \number\CF@cnt@atomingroup
                     \else\ifdim\CF@current@angle pt>270pt \number\CF@cnt@atomingroup\else1\fi
                     \fi
                 \else\CF@current@fromatom
                 \fi}%
            \expandafter\futurelet\expandafter\CF@toks@a\expandafter\CF@gobble@tonil\CF@remain@molecule\relax\@nil
            \CF@if@firsttokin@i{-=<>~}% la suite est une liaison
                {\ifnum\CF@last@action=\tw@% c'est la deuxi\`eme liaison cons\'ecutive ?
                    \CF@insert@emptygroup\CF@remain@molecule% ins\`ere un groupe vide
                    \edef\CF@bond@outnode{\CF@bond@outnode}%
                \else
                    \ifCF@incycle\advance\CF@cnt@cycle\@ne\fi
                    \expandafter\CF@analyse@bond\expandafter{\CF@remain@molecule}\CF@bond@type
                    \edef\CF@bond@outnode{\CF@bond@outnode}%
                    \let\CF@remain@molecule\CF@remain@afterbond
                    \ifCF@incycle
                        \ifnum\CF@cnt@cycle=\CF@cycle@num\relax
                            \expandafter\expandafter\expandafter\@firstoftwo
                        \else
                            \ifnum\CF@cnt@cycle=\@ne
                                \let\CF@cycle@firsttikz\CF@current@tikz
                                \unless\ifx\CF@start@offset\@empty\let\CF@cycle@joinlast\z@\fi
                            \fi
                            \expandafter\expandafter\expandafter\@secondoftwo
                        \fi
                    \else
                        \expandafter\@secondoftwo
                    \fi
                        {\let\CF@next@action\endgroup
                        \CF@draw@bond\CF@bond@type{\CF@bond@outnode}{\CF@hook@cycle}\CF@previous@atomgroup\CF@hook@atomgroup
                        }%
                        {\node[at=(\CF@bond@outnode\ifCF@incycle\else\ifCF@macrofixedbondlength.\CF@current@angle\fi\fi),shift=(\ifcase\CF@split@state\or180-\or-\fi\CF@current@angle:\CF@current@length*\CF@atom@sep)](CF@node){};
                        \let\CF@previous@angle\CF@current@angle
                        \let\CF@last@action\tw@
                        }%
                \fi
                \ifcat\relax\detokenize\expandafter{\romannumeral-`\.\expandafter\noexpand\CF@remain@molecule}\relax
                % s'il ne reste plus rien apr\`es la liaison (sans tenir compte de l'espace devant)-> ins\`ere un groupe vide
                    \CF@insert@emptygroup\CF@remain@molecule
                \fi
                }%
                {\edef\CF@bond@outnode{\CF@bond@outnode}% \'evalue le l'atome de d\'epart de liaison
                \CF@ifx(\CF@toks@a% une parenth\`ese pour commencer ?
                    {\ifnum\CF@last@action=\tw@% il y avait une liaison juste avant ?
                        \CF@insert@emptygroup\CF@remain@molecule
                    \else
                        \expandafter\CF@grab@submol\expandafter{\CF@remain@molecule}%
                        \begingroup
                            \ifCF@incycle\let\CF@last@action\thr@@\fi% on \'etait dans un cycle
                            \CF@incyclefalse
                            \aftergroup\CF@chemfig@vi
                            \def\CF@next@action{\expandafter\CF@chemfig@v\expandafter{\CF@sub@mol}}%
                    \fi
                    }%
                    {\ifx\CF@remain@molecule\@empty
                        \let\CF@next@action\endgroup
                    \else% ce qui reste apr\`es le noeud courant n'est pas vide, ne commence pas par "-=~", ni par une parenth\`ese
                        \CF@ifx*\CF@toks@a% un cycle ?
                        {\ifnum\CF@last@action=\tw@
                            \CF@insert@emptygroup\CF@remain@molecule% ins\`ere un groupe vide
                        \else
                            \ifCF@incycle\let\CF@last@action\thr@@\fi% on \'etait dans un cycle
                            \ifnum\CF@last@action=\thr@@\let\CF@lastcycle@num\CF@cycle@num\fi
                            \CF@expafterarg@ntimes2\CF@if@firsttokmatch{\expandafter\@gobble\CF@remain@molecule}*% un 2\`e "*" ?
                                {\CF@expafterarg@ntimes2{\def\CF@remain@molecule}{\expandafter\@gobble\CF@remain@molecule}% enl\`eve la 1er \'etoile
                                \CF@expafterarg@ntimes2\CF@if@firsttokmatch{\expandafter\@gobble\CF@remain@molecule}[% un crochet ensuite ?
                                    {\expandafter\CF@cycle@parsepreamblewithoptarg\CF@remain@molecule\@nil% \begingroup inclus
                                    }%
                                    {\def\CF@cyclearc@startangle{0}\def\CF@cyclearc@endangle{360}%
                                    \let\CF@cyclearc@directtikz\@empty
                                    \expandafter\CF@cycle@parsepreamble\CF@remain@molecule\@nil% \begingroup inclus
                                    }%
                                \CF@cyclearctrue
                                }%
                                {\expandafter\CF@cycle@parsepreamble\CF@remain@molecule\@nil% \begingroup inclus
                                \CF@cyclearcfalse
                                }%
                            \CF@cnt@cycle\z@
                            \edef\CF@hook@cycle{\CF@bond@outnode}%
                            \let\CF@hook@atomgroup\CF@previous@atomgroup
                            \ifx\CF@hook@atomgroup\CF@empty@node
                                \let\CF@cycle@joinlast\@ne% joindre le dernier
                            \else
                                \let\CF@cycle@joinlast\z@
                            \fi
                            \CF@incycletrue
                            \ifnum\CF@last@action=\thr@@
                                \pgfmathparse{360/\CF@lastcycle@num-180}% c'est un cycle dans un cycle
                            \else
                                \pgfmathparse{-180/\CF@cycle@num-90+\CF@cycle@anglecorrection}%
                            \fi
                            \let\CF@initcycle@angle\pgfmathresult
                            \aftergroup\CF@chemfig@vi
                            \def\CF@next@action{\expandafter\CF@chemfig@v\expandafter{\CF@sub@mol}}%
                        \fi
                        }%
                        {\errmessage{Package \CF@package@name\space Error: something went wrong here: \detokenize\expandafter{\CF@remain@molecule}^^JIf you think it's a bug, please, send a Minimal Example to the author.}}%
                    \fi}%
                }%
        \else
            \CF@expand@second{\CF@expand@second{\CF@expand@second\CF@draw@atomgroup\CF@current@angle}\CF@current@toatom}\CF@current@atomgroup
        \fi
    \fi
    \CF@next@action
}
\makeatother

\begin{document}
\chemname{\chemfig{A=B-C-D}}{example}
\end{document}

您可以检查分子图像是否记录在<name of master file>-image0.pdf当前目录中的 pdf 文件 ( ) 中。以下是输出:

在此处输入图片描述

不过还有一个小问题...由于 a 的边界框C比其轮廓小,因此裁剪得external太紧:

在此处输入图片描述

为了解决这个问题,您可以增加inner sep并将其设置为1pt而不是\z@(即0pt):

\edef\CF@tmp@str{\noexpand\begin{tikzpicture}[remember picture,every node/.style={anchor=base,inner sep=1pt,outer sep=\z@,minimum size=\z@\ifx\@empty#2\@empty\else,#2\fi},baseline\ifx\@empty#1\@empty\else,#1\fi]}%

相关内容