Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I know that a pgfplots cycle list can be created with \pgfplotscreateplotcyclelist. However, the examples given in the pgfplots manual explicitly list all the items. I am wondering if it is possible to create a cycle list by looping through a table (potentially loaded from a file). This is very useful when there are large number of \addplot and each needs a special style. Any idea how to do this? Thanks.

share|improve this question
2  
Welcome to TeX.sx, huahaiy. I've formatted your inline code by enclosing it in backticks, I hope that's okay. –  Jake Mar 25 '11 at 8:45
    
@Jake: Thanks for the bounty! –  Martin Scharrer Mar 29 '11 at 16:34
add comment

4 Answers

I've started on something, but it's not working yet. I'm posting this here in the hopes that someone with deeper understanding of LaTeX might be able to help.

The following code uses pgfplotstable to read a file and save it in a macro with each line separated by \\, which is the input format \pgfplotscreateplotcyclelist expects. However, using the macro instead of the normal \\-separated list fails with

! Undefined control sequence.
->\let \reserved@e
\relax \let \reserved@f \relax \@ifstar {\let \reserv...

I suspect it's something to do with how/if/that the macro is expanded...

\documentclass{article}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{filecontents}

\begin{filecontents}{cyclelist.txt}
green
pink
\end{filecontents}
\pgfplotstableread{cyclelist.txt}{\cyclelist}

\begin{document}

\pgfplotstabletypeset[begin table={},end table={},skip coltypes,display columns/0/.style={string type},write to macro=\listmacro,typeset=false]\cyclelist
\show\listmacro % To show that the macro contents are what \pgfplotscreateplotcyclelist expects
\begin{tikzpicture}

\pgfplotscreateplotcyclelist{newcycle}{\listmacro}
%\pgfplotscreateplotcyclelist{newcycle}{green\\pink\\} % This works fine, as expected

\begin{axis}[cycle list name=newcycle]
\addplot {x^2};
\end{axis}
\end{tikzpicture}

\end{document}
share|improve this answer
add comment

The reason why Jake's solution doesn't work is that the \listmacro isn't expanded before the pgfplotscreateplotcyclelist macro searches for the \\ separators. Therefore the whole macro is taken as one setting and the included \\ are expanded as part of the setting which causes an error (line breaks in settings don't make much sense).

So in order to make it work you have to manually expand \listmacro first and than feed it to \pgfplotscreateplotcyclelist. There are multiple ways to do this. Here a way which uses eTeX's \unexpanded inside \edef to expand the \listmacro only once, otherwise the \\ are expanded to early and cause also errors. I defined a new macro \pgfplotscreateplotcyclelistfrommacro which expands the second argument and then calls \pgfplotscreateplotcyclelist. Feel free to rename it.

Based on Jake's code:

\documentclass{article}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{filecontents}

\newcommand*{\pgfplotscreateplotcyclelistfrommacro}[2]{%
    \begingroup
    % Expands the second argument once. The `\A` is only temporary used
    % and therefore in a group
    \edef\A{\noexpand\pgfplotscreateplotcyclelist{#1}{\unexpanded\expandafter{#2}}}%
    \expandafter
    \endgroup\A
}

\begin{filecontents}{cyclelist.txt}
green
pink
purple
\end{filecontents}
\pgfplotstableread{cyclelist.txt}{\cyclelist}

\begin{document}

\pgfplotstabletypeset[begin table={},end table={},skip coltypes,display columns/0/.style={string type},write to macro=\listmacro,typeset=false]\cyclelist

\begin{tikzpicture}
\pgfplotscreateplotcyclelistfrommacro{newcycle}{\listmacro}
\begin{axis}[cycle list name=newcycle]
\addplot {x^2};
\addplot {x^4};
\addplot {x^6};
\end{axis}
\end{tikzpicture}

\end{document}
share|improve this answer
add comment

I think there are a couple of challenges which are unmet so far: a cycle list entry can have white space characters (which is also the default cell separator of pgfplots). Furthermore, one may want to choose a particular column if a table has more than one columns.

Here is a starting point which addresses these things (although perhaps not with the most elegant interface):

\documentclass[a4paper]{article}
\usepackage{filecontents}

\begin{filecontents}{P.dat}
columnname
blue,mark=*
red,mark=square
dashed,mark=o
loosely dotted,mark=+
brown!60!black,mark options={fill=brown!40},mark=otimes*
\end{filecontents}
\usepackage{pgfplots}

\usepackage{pgfplotstable}


\makeatletter
% #1: table. The table should have either ONE column or the cols
% should be separate by semicolon (see the body of this macro)
% #2: column name
% #3: name of the target cycle list
% Example:
% \pgfplotscreateplotcyclelistfromtable{P.dat}{columnname}{my cycle list name}
\def\pgfplotscreateplotcyclelistfromtable#1#2#3{%
    \begingroup
    \gdef\pgfplots@tmp{}%
    \pgfplotstableread[col sep=semicolon]{#1}\table@tmp
    \pgfplotstableforeachcolumnelement{#2}\of\table@tmp\as\table@cell{%
        \begingroup
        \toks0=\expandafter{\table@cell}%
        \ifx\pgfplots@tmp\empty
            \xdef\pgfplots@tmp{{\the\toks0}}%
        \else
            \toks1=\expandafter{\pgfplots@tmp}%
            \xdef\pgfplots@tmp{\the\toks1,{\the\toks0}}%
        \fi
        \endgroup
    }%
    \toks0={\pgfplotscreateplotcyclelist{#3}}%
    \toks1=\expandafter{\pgfplots@tmp}%
    \xdef\pgfplots@tmp{\the\toks0{\the\toks1}}%
    \endgroup
    \show\pgfplots@tmp
    \pgfplots@tmp
}%
\makeatother
\pgfplotscreateplotcyclelistfromtable{P.dat}{[index]0}{mylist}

\begin{document}

\begin{tikzpicture}
    \begin{axis}[cycle list name=mylist]
        \addplot {x};
        \addplot {x-1};
        \addplot {x-2};
        \addplot {x-3};
        \addplot {x-4};
        \addplot {x-5};
    \end{axis}
\end{tikzpicture}

\end{document}

It runs in every tex distribution, I'd say (since \toks and \xdef etc are tex primites.)

share|improve this answer
add comment

For anyone else interested in "more manageable" cycle lists, I defined the following macro in my latex pre-amble:

\def\setplotcycle{cycle list={%
{blue,mark=*},
{red,mark=square},
{green,mark=square}
}}

and included \setplotcycle in each of my plots. E.g:

\begin{axis}[\setplotcycle]

Now I can update the colours in all of my plots from just one place. Hope this helps.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.