TikZ:使用嵌套 foreach 循环的 groupplot 突出显示配置文件的背景

TikZ:使用嵌套 foreach 循环的 groupplot 突出显示配置文件的背景

我正在尝试使用\groupplots\pgfplotsinvokeforeach生成显示不同配置文件的动态图片。在这些配置文件中,我想用特定的背景颜色突出显示不同的范围(序列)。

这些序列位于单独的 *.csv 文件中,并带有相应的开始/结束时间和颜色代码。我无法加载这些文件,读取每一行并突出显示相应的范围。尽管如此,我的大部分代码似乎都有效,因为我得到的结果非常接近,但内部循环似乎无法正常工作。

\documentclass[tikz]{standalone}
\usepackage{filecontents}

\usepackage{siunitx} % added this line because of marmot's comment
\usepackage{pgfplots}
\usepackage{tikz}

\RequirePackage{pgfplotstable} % Allows to read tables

\pgfplotsset{compat=newest} % Ensure compatibility mode

\usepgfplotslibrary{groupplots} % Groupplots (multiple x-Axis together)
\usetikzlibrary{backgrounds} % Background Library
\usetikzlibrary{calc} % Allows extended coordinate calculations

\newcommand{\tikzsetnextfilename}[1]{\ignorespaces}

\begin{document}
    % externalise TikZ (when not in standalone) - use same filename
    \tikzsetnextfilename{\currfilebase}

    % Data table
    \pgfplotstableset{
        col sep={semicolon}
    }

    \begin{filecontents}{Profile1.csv}
        t_h;I_A;U_V
        0;0;3.584
        0.06905;-0.67;3.53
        0.1381;-0.67;3.514
        0.2072;-0.67;3.5
        0.2762;-0.67;3.484
        0.3453;-0.67;3.466
        0.4143;-0.67;3.448
        0.4834;-0.67;3.428
        0.5524;-0.67;3.412
        0.6215;-0.67;3.399
        0.6905;-0.67;3.385
        0.7596;-0.67;3.369
        0.8287;-0.67;3.35
        0.8977;-0.67;3.321
        0.9668;-0.67;3.275
        1.036;-0.67;3.231
    \end{filecontents}

    \begin{filecontents}{Sequences1.csv}
        tstart_h;tend_h;type
        0.0;0.2762;1
        0.3453;0.6215;2
        0.6905;0.8977;3
        0.9668;1.036;1
    \end{filecontents}

    \begin{filecontents}{Profile2.csv}
        t_h;I_A;U_V
        0;0;3.705
        0.07158;0;3.705
        0.1432;0;3.705
        0.2148;1.675;3.851
        0.2863;1.675;3.892
        0.3579;1.675;3.93
        0.4295;1.675;3.966
        0.5011;1.675;4.001
        0.5727;1.675;4.035
        0.6443;1.675;4.071
        0.7158;1.675;4.11
        0.7874;1.675;4.154
        0.859;1.675;4.196
        0.9306;1.33;4.2
        1.002;1.136;4.2
        1.074;0.9927;4.2
    \end{filecontents}

    \begin{filecontents}{Sequences2.csv}
        tstart_h;tend_h;type
        0.0;0.2148;2
        0.2863;0.5011;1
        0.5727;0.859;2
        0.9306;1.074;3
    \end{filecontents}

    \begin{tikzpicture}

        \pgfplotsset{
            plot coordinates/math parser=true,
            unbounded coords=jump,
            filter discard warning=false,
        %% Colormap
            colormap={sequencecolors}{
                rgb=(0.75,0,0)
                rgb=(0,0.75,0)
                rgb=(0,0,0.75)
            },
        %% Axis
            scale only axis,
            width=0.8\linewidth,
            height=2cm,
            every axis/.append style={
                line width=1pt,
                tick style={line width=0.8pt},
                grid style={dashed, black!20},
                grid=major,
            },
        %% X-Axis
            xmin=-0.1,
            xmax=1.2,
        }

    %% Primary Y-Axis
        \begin{groupplot}[
            group style={
                group size=1 by 2,
                xlabels at=edge bottom,
                xticklabels at=edge bottom,
                vertical sep=2mm
            },
            tickpos=left,
        %% X-Axis
            xlabel={$t$ in \si{\hour}},
        %% Y-Axis
            ymin=2.4,
            ymax=4.3,
        ]

            \pgfplotsinvokeforeach{1,...,2}{
                % Each Profile in seperate groupplot
                \nextgroupplot [ylabel=Seq #1] {
                    % Profile
                    \addplot [color=blue, forget plot] table [x=t_h, y=U_V] {Profile#1.csv};

                    % Seqence
                    \pgfplotstableread{Sequences#1.csv}{\sequences}
                    \pgfplotstablegetrowsof{\sequences}
                    \pgfmathsetmacro{\rows}{\pgfplotsretval-1}

                    \begin{scope} [on background layer]
                        \pgfplotsinvokeforeach{1,...,\rows}{
                            % Get row from sequences
                            \pgfplotstablegetelem{#1}{tstart_h}\of{\sequences}\edef\tailTime{\pgfplotsretval}
                            \pgfplotstablegetelem{#1}{tend_h}\of{\sequences}\edef\headTime{\pgfplotsretval}
                            \pgfplotstablegetelem{#1}{type}\of{\sequences}\edef\typeColor{\pgfplotsretval}

                            %% This is where the magic should happen, second line is only for debugging, first line does not work properly but what's wrong?
                            % \fill [color of colormap={\typeColor}, opacity=0.1] (\tailTime , \pgfkeysvalueof{/pgfplots/ymin}) rectangle (\headTime, \pgfkeysvalueof{/pgfplots/ymax});
                            \fill [color of colormap={#1}, opacity=0.1] ( {#1*0.1}, \pgfkeysvalueof{/pgfplots/ymin}) rectangle ( {(#1+1)*0.1}, \pgfkeysvalueof{/pgfplots/ymax});
                        }
                    \end{scope}
                }
            }
        \end{groupplot}

    %% Secondary Y-Axis
        \begin{groupplot}[
            group style={
                group size=1 by 2,
                xlabels at=edge bottom,
                xticklabels at=edge bottom,
                vertical sep=2mm,
                y descriptions at=edge right
            },
            grid=none,
            tickpos=right,
        %% X-Axis
            xticklabels={,,},
        %% Y-Axis
            ymin=-6,
            ymax=6,
        ]

        \pgfplotsinvokeforeach{1,...,2}{
            % Each Profile in seperate groupplot
            \nextgroupplot [ylabel=Seq #1] {
                % Profile
                \addplot [color=red, forget plot] table [x=t_h, y=I_A] {Profile#1.csv};
            }
        }
        \end{groupplot}
    \end{tikzpicture}
\end{document}

结果是:

提供的 MWE 的结果

使用附加\fill命令时,我收到了几个错误消息,例如:

filename.tex:149: Package PGF Math Error: Sorry, an internal routine of the loating point unit got an ill-formatted floating point number `130.0'. The unreadable part was near '130.0'..
filename.tex:149: Illegal unit of measure (pt inserted)

手工完成所有操作是不可能的,提供的数据只是整个数据集中很小的一部分。有没有办法处理这个问题,或者我必须在配置文件数据中使用单独的列来命名颜色代码以其他方式处理这个问题?

答案1

有两个问题。首先,#1不幸的是,内循环中的 仍然“记住”了#1外循环中的 。所以我手动修复了这个问题。其次,更重要的是,pgfplots似乎有推迟扩张的“特征”,并且\fill当它已经忘记了你在内循环中读取的值时,它会扩展命令。所以我建议使用这个代码。

\documentclass[tikz]{standalone}
\usepackage{filecontents}

\usepackage{siunitx} % added this line because of marmot's comment
\usepackage{pgfplots}
\usepackage{tikz}

\RequirePackage{pgfplotstable} % Allows to read tables

\pgfplotsset{compat=newest} % Ensure compatibility mode

\usepgfplotslibrary{groupplots} % Groupplots (multiple x-Axis together)
\usetikzlibrary{backgrounds} % Background Library
\usetikzlibrary{calc} % Allows extended coordinate calculations
\newcounter{irun}

\newcommand{\tikzsetnextfilename}[1]{\ignorespaces}

\begin{document}
    % externalise TikZ (when not in standalone) - use same filename
    \tikzsetnextfilename{\currfilebase}
    % Data table
    \pgfplotstableset{
        col sep={semicolon}
    }

    \begin{filecontents}{Profile1.csv}
        t_h;I_A;U_V
        0;0;3.584
        0.06905;-0.67;3.53
        0.1381;-0.67;3.514
        0.2072;-0.67;3.5
        0.2762;-0.67;3.484
        0.3453;-0.67;3.466
        0.4143;-0.67;3.448
        0.4834;-0.67;3.428
        0.5524;-0.67;3.412
        0.6215;-0.67;3.399
        0.6905;-0.67;3.385
        0.7596;-0.67;3.369
        0.8287;-0.67;3.35
        0.8977;-0.67;3.321
        0.9668;-0.67;3.275
        1.036;-0.67;3.231
    \end{filecontents}

    \begin{filecontents}{Sequences1.csv}
        tstart_h;tend_h;type
        0.0;0.2762;1
        0.3453;0.6215;2
        0.6905;0.8977;3
        0.9668;1.036;1
    \end{filecontents}

    \begin{filecontents}{Profile2.csv}
        t_h;I_A;U_V
        0;0;3.705
        0.07158;0;3.705
        0.1432;0;3.705
        0.2148;1.675;3.851
        0.2863;1.675;3.892
        0.3579;1.675;3.93
        0.4295;1.675;3.966
        0.5011;1.675;4.001
        0.5727;1.675;4.035
        0.6443;1.675;4.071
        0.7158;1.675;4.11
        0.7874;1.675;4.154
        0.859;1.675;4.196
        0.9306;1.33;4.2
        1.002;1.136;4.2
        1.074;0.9927;4.2
    \end{filecontents}

    \begin{filecontents}{Sequences2.csv}
        tstart_h;tend_h;type
        0.0;0.2148;2
        0.2863;0.5011;1
        0.5727;0.859;2
        0.9306;1.074;3
    \end{filecontents}

    \begin{tikzpicture}

        \pgfplotsset{
            plot coordinates/math parser=true,
            unbounded coords=jump,
            filter discard warning=false,
        %% Colormap
            colormap={sequencecolors}{
                rgb=(0.75,0,0)
                rgb=(0,0.75,0)
                rgb=(0,0,0.75)
            },
        %% Axis
            scale only axis,
            width=0.8\linewidth,
            height=2cm,
            every axis/.append style={
                line width=1pt,
                tick style={line width=0.8pt},
                grid style={dashed, black!20},
                grid=major,
            },
        %% X-Axis
            xmin=-0.1,
            xmax=1.2,
        }

    %% Primary Y-Axis
        \begin{groupplot}[
            group style={
                group size=1 by 2,
                xlabels at=edge bottom,
                xticklabels at=edge bottom,
                vertical sep=2mm
            },
            tickpos=left,
        %% X-Axis
            xlabel={$t$ in \si{\hour}},
        %% Y-Axis
            ymin=2.4,
            ymax=4.3,
        ]

            \pgfplotsinvokeforeach{1,...,2}{\setcounter{irun}{0}
                % Each Profile in seperate groupplot
                \nextgroupplot [ylabel=Seq #1] {
                    % Profile
                    \addplot [color=blue, forget plot] table [x=t_h, y=U_V] {Profile#1.csv};

                    % Seqence
                    \pgfplotstableread{Sequences#1.csv}{\sequences}
                    \pgfplotstablegetrowsof{\sequences}
                    \pgfmathtruncatemacro{\rows}{\pgfplotsretval}
                    \typeout{\rows\space rows}

                    \begin{scope} [on background layer]
                        \pgfplotsinvokeforeach{1,...,\rows}{
                            % Get row from sequences
                            \pgfplotstablegetelem{\theirun}{tstart_h}\of{\sequences}\edef\tailTime{\pgfplotsretval}
                            \pgfplotstablegetelem{\theirun}{tend_h}\of{\sequences}\edef\headTime{\pgfplotsretval}
                            \pgfplotstablegetelem{\theirun}{type}\of{\sequences}\edef\typeColor{\pgfplotsretval}
                            \stepcounter{irun}
                            \typeout{run:\space #1,\space subrun:\space\theirun/\rows:\space\typeColor\space\tailTime\space\headTime}

                            %% This is where the magic should happen, second line is only for debugging, first line does not work properly but what's wrong?
                            \edef\temp{\noexpand\fill [color of
                            colormap=14*\typeColor cm, opacity=0.1] (\tailTime ,
                            \pgfkeysvalueof{/pgfplots/ymin}) rectangle (\headTime,
                            \pgfkeysvalueof{/pgfplots/ymax});}
                            \temp %from https://tex.stackexchange.com/a/170670/121799
                            %\fill [color of colormap={#1}, opacity=0.1] ( {#1*0.1}, \pgfkeysvalueof{/pgfplots/ymin}) rectangle ( {(#1+1)*0.1}, \pgfkeysvalueof{/pgfplots/ymax});
                        }
                    \end{scope}
                }
            }
        \end{groupplot}

    %% Secondary Y-Axis
        \begin{groupplot}[
            group style={
                group size=1 by 2,
                xlabels at=edge bottom,
                xticklabels at=edge bottom,
                vertical sep=2mm,
                y descriptions at=edge right
            },
            grid=none,
            tickpos=right,
        %% X-Axis
            xticklabels={,,},
        %% Y-Axis
            ymin=-6,
            ymax=6,
        ]

        \pgfplotsinvokeforeach{1,...,2}{
            % Each Profile in seperate groupplot
            \nextgroupplot [ylabel=Seq #1] {
                % Profile
                \addplot [color=red, forget plot] table [x=t_h, y=I_A] {Profile#1.csv};
            }
        }
        \end{groupplot}
    \end{tikzpicture}
\end{document}

编辑:我修改了颜色命令,只是为了再次检查阴影是否确实被读取。使用原始设置,普通土拨鼠的眼睛无法区分颜色。

在此处输入图片描述

相关内容