Tikzexternalize 不会使用自写绘图命令进行更新

Tikzexternalize 不会使用自写绘图命令进行更新

编辑2:

所以问题在于,tikzpicture在生成哈希之前,环境中的代码没有被扩展.md5。因此,内容不会随着不同的输入而改变。

现在,我有一个想法,.md5为我的命令的输入创建一个自己的哈希值,然后将其存储在单独的文件中。

\newwrite\tempfile%
\immediate\openout\tempfile=./\csvPlotOutputDir/\csvPlotLabel._md5%
\immediate\write\tempfile{\pdfmdfivesum{#1}}%
\immediate\closeout\tempfile%

这似乎很有效。当选项被修改时,它会改变哈希值。现在我正在寻找一种方法来评估该文件中的更改。


编辑1:

运行时latexmk.md5会为每个外部化图生成一个文件。但是,在我更改\csvplot[]{}命令和编译的某些选项后,它不会重新创建。

因此,如果我更改选项列表中的某些内容,文件的内容.md5实际上不会改变。为什么会这样?当我清理辅助文件并使用更改重新编译时,编译文档中的输出是不同的。


我编写了自己的软件包,用于使用不同的设置绘制 .csv 文件。例如,我可以选择使用简单的列名列表绘制 .csv 的某些列,并将其作为参数传递给我的命令。

但是,我也想使用 Tikz externalize,并且我通常使用 latexmk 进行编译。因为我想使用尽可能多的 CPU 核心,所以我使用 externalization 选项[mode=list and make]

因此,编译流程如下:

latexmk -pdf file.tex
make -j 4 -f file.makefile
latexmk -g -pdf file.tex

我没有遇到任何问题,一次最多可以外部化四幅图像。我也可以毫无问题地获得 .pdf 输出。

使用我自己编写的绘制 .csv 文件的函数,我无法让 tikzexternalize 更新图形。它检测不到任何变化。如果您不使用该mode=list and make选项,情况也是如此。因此,下面的 MWE 不包括它,以便于访问。

下面你会看到一个 MWE,它并不是真正最小的,因为包已经变大了。原则上,我在一个groupplot环境中绘图,其中有两个循环迭代 .csv 文件的不同列。第一个循环用于作为 x 轴的列,第二个循环用于作为 y 轴的列。这些循环是嵌套的。


最后,完整代码如下:

不带选项的要编译的主要 .tex 文件 (csvtest.txt) mode=list and make。其中包含一个绘图的手动声明,如果我更改某些内容(例如,它应该从中提取数据的列),该声明会更新。

\documentclass{article}
\usepackage[default]{csvtoolbox}

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

\begin{document}

    \csvplot[%
        %output dir = fig,  % this allows you to choose the output folder for the .pdf
        label = f1, % this also defines the name of the externalized figure file name -> f1.pdf
        x columns = {x},% 
        y columns = {a, b},%
    ] {data.csv}

    \begin{figure}
        \begin{tikzpicture}
            \begin{groupplot}
                \nextgroupplot
                \addplot table[x=x, y=x, col sep=comma]{data.csv};
            \end{groupplot}
        \end{tikzpicture}
    \end{figure}

\end{document}

以下是我编写的用于绘制.csv 文件的包。

\NeedsTeXFormat{LaTeX2e}%
\ProvidesPackage{csvtoolbox}[2017/05/17 CSV Plot]%

\RequirePackage{etoolbox}%
\RequirePackage{pgfplots}%
\RequirePackage{tikz}%
\RequirePackage{pgfkeys}%
\RequirePackage{float}%
\RequirePackage{hyperref}%
\RequirePackage{tikzscale}%

\pgfplotsset{compat=newest}%
\usepgfplotslibrary{groupplots}%

\DeclareOption{default}{%
    \pgfplotsset{csvPlotStyle/.style=%
        {%
        cycle list name=black white,%
        grid=both,%
        grid style={dashed, gray},%
        }%
    }%
    \pgfkeys{
        % Switch to /csvplot key subset
        /csvplot/.is family, /csvplot,%
        % User options
        def/.style = {%
            axis rows = 1,%
            axis columns = 1,%,
            legend pos = north east,%
            height = \textwidth,%
            width = \textwidth,%
            x columns = x,%
            y columns = y,%
            style = csvPlotStyle,%
            caption = ,%
            label = ,%
            align = top,%
            output dir =.%
        }%
    }%
}%
%
\ExecuteOptions{default}%
\ProcessOptions\relax%
%
% Set up the keys
\pgfkeys{
    % Switch to /csvplot key subset
    /csvplot,%
    %% definitions
    axis rows/.estore in = \csvPlotAxisRows,%
    axis columns/.estore in = \csvPlotAxisCols,%
    output dir/.estore in = \csvPlotOutputDir,%
    legend pos/.estore in = \csvLegPos,%
    height/.estore in = \csvPlotHeight,%
    width/.estore in = \csvPlotTotalWidth,%
    x columns/.estore in = \csvPlotXCol,%
    y columns/.estore in = \csvPlotYCol,%
    style/.estore in = \csvPlotStyle,%
    caption/.estore in = \csvPlotCaption,%
    label/.estore in = \csvPlotLabel,%
    align/.style = {alignments/#1/.get = \csvPlotAlignment},%
    % dictionary for alignment of figure
    alignments/.cd,%
        top/.initial = t,%
        here/.initial = h,%
        bottom/.initial = b,%
        force/.initial = H,%
        page/.initial = p,%
}
%
\newcommand{\csvplot}[2][]{%
    \pgfkeys{/csvplot, def, #1}%
    \tikzsetnextfilename{./\csvPlotOutputDir/\csvPlotLabel}%
    % Expand figure options
    \def\efigure{\begin{figure}}\expandafter\efigure\expandafter[\csvPlotAlignment]%
    \centering%
    \begin{tikzpicture}%
        \begin{groupplot} [%
            \csvPlotStyle,%
            height=1/\csvPlotAxisRows*\csvPlotHeight,%
            width=1/\csvPlotAxisCols*\csvPlotTotalWidth,%
            legend pos=\csvLegPos,%
            group style = {group size = \csvPlotAxisCols\space by \csvPlotAxisRows},%
            ]%
            % Plot loop: All x/y columns for multiple plots in one axis
            \edef\XIterate{%
                \noexpand\pgfplotsforeachungrouped \noexpand\x in {\csvPlotXCol}%
            }
            \edef\YIterate{%
                \noexpand\pgfplotsforeachungrouped \noexpand\y in {\csvPlotYCol}%
            }
            \XIterate {%
                \YIterate {%
                    \eappto\PlotList{%
                        \noexpand\nextgroupplot%
                        \noexpand\addplot table[x=\x, y=\y, col sep=comma] {#2};%
                        \noexpand\addlegendentry{\y}%
                    }%
                }%
            }%
            \PlotList%
        \end{groupplot}%
    \end{tikzpicture}%
    \caption{\csvPlotCaption}%
    \label{\csvPlotLabel}%
    \end{figure}
}%

最后,绘制一些数据(data.csv)

a,b,x,y
1,2,3,4
5,6,8,1
9,2,4,5
5,5,1,9

谢谢您的意见!

答案1

我终于找到了解决方案。我.md5根据传递给命令的选项生成一个单独的哈希文件。在命令中,哈希文件生成如下:

\newwrite\tempfile%
\immediate\openout\tempfile=./\csvPlotOutputDir/\csvPlotLabel.md5_%
\immediate\write\tempfile{\pdfmdfivesum{#1}}%
\immediate\closeout\tempfile%

然后,我tikzexternalize通过添加以下内容来依赖此文件的内容

\tikzpicturedependsonfile{./\csvPlotOutputDir/\csvPlotLabel.md5_}%

以下是供参考的完整csvtoolbok.sty文件:

\NeedsTeXFormat{LaTeX2e}%
\ProvidesPackage{csvtoolbox}[2017/05/17 CSV Plot]%

\RequirePackage{etoolbox}%
\RequirePackage{pgfplots}%
\RequirePackage{tikz}%
\RequirePackage{pgfkeys}%
\RequirePackage{float}%
\RequirePackage{hyperref}%
\RequirePackage{tikzscale}%

\pgfplotsset{compat=newest}%
\usepgfplotslibrary{groupplots}%

\DeclareOption{default}{%
    \pgfplotsset{csvPlotStyle/.style=%
        {%
        cycle list name=color,%
        grid=both,%
        grid style={dashed, gray},%
        }%
    }%
    \pgfkeys{
        % Switch to /csvplot key subset
        /csvplot/.is family, /csvplot,%
        % User options
        def/.style = {%
            axis rows = 1,%
            axis columns = 1,%,
            output dir =.,%
            legend pos = outer south,%
            height = \textwidth,%
            width = \textwidth,%
            plot data x/y = x/y,%
            common style = csvPlotStyle,%
            caption = ,%
            label = ,%
            align = top,%
        }%
    }%
}%
%
\ExecuteOptions{default}%
\ProcessOptions\relax%
% Define outer south legend style
\pgfplotsset{
    every axis x label/.append style={
        alias=current axis xlabel
    },
    legend pos/outer south/.style={
        /pgfplots/legend style={
            at={%
                (%
                \@ifundefined{pgf@sh@ns@current axis xlabel}%
                {xticklabel cs:0.5}%
                {current axis xlabel.south}%
                )%
            },
            anchor=north
        }
    }
}
%
% Set up the keys
\pgfkeys{
    % Switch to /csvplot key subset
    /csvplot,%
    %% definitions
    axis rows/.estore in = \csvPlotAxisRows,%
    axis columns/.estore in = \csvPlotAxisCols,%
    output dir/.estore in = \csvPlotOutputDir,%
    legend pos/.estore in = \csvLegPos,%
    height/.estore in = \csvPlotHeight,%
    width/.estore in = \csvPlotTotalWidth,%
    plot data x/y/.estore in = \csvPlotXYCol,%
    common style/.estore in = \csvPlotStyle,%
    caption/.estore in = \csvPlotCaption,%
    label/.estore in = \csvPlotLabel,%
    align/.style = {alignments/#1/.get = \csvPlotAlignment},%
    % dictionary for alignment of figure
    alignments/.cd,%
        top/.initial = t,%
        here/.initial = h,%
        bottom/.initial = b,%
        force/.initial = H,%
        page/.initial = p,%
}
%
\newcommand{\csvplot}[2][]{%
    \pgfkeys{/csvplot, def, #1}%
    %
    \newwrite\tempfile%
    \immediate\openout\tempfile=./\csvPlotOutputDir/\csvPlotLabel.md5_%
    \immediate\write\tempfile{\pdfmdfivesum{#1}}%
    \immediate\closeout\tempfile%
    %
    \tikzsetnextfilename{./\csvPlotOutputDir/\csvPlotLabel}%
    \tikzpicturedependsonfile{./\csvPlotOutputDir/\csvPlotLabel.md5_}%
    % Expand figure options
        \def\efigure{\begin{figure}}\expandafter\efigure\expandafter[\csvPlotAlignment]%
        \centering%
        \begin{tikzpicture}%
            \begin{groupplot} [%
                \csvPlotStyle,%
                height=1/\csvPlotAxisRows*\csvPlotHeight,%
                width=1/\csvPlotAxisCols*\csvPlotTotalWidth,%
                legend pos=\csvLegPos,%
                group style = {group size = \csvPlotAxisCols\space by \csvPlotAxisRows},%
                ]%
                % Plot loop: All x/y columns for multiple plots in one axis
                \edef\XYIterate{%
                    \noexpand\pgfplotsforeachungrouped \noexpand\x/\noexpand\y in {\csvPlotXYCol}%
                }%
                \XYIterate {%
                    \eappto\PlotList{%
                        \noexpand\nextgroupplot%
                        \noexpand\addplot table[x=\x, y=\y, col sep=comma] {#2};%
                        \noexpand\addlegendentry{\y}%
                    }%
                }%
                \PlotList%
            \end{groupplot}%
        \end{tikzpicture}%
        \caption{\csvPlotCaption}%
        \label{\csvPlotLabel}%
        \end{figure}%
    %
}%

相关内容