5

In this MWE, the table data loaded from poles.dat is successfully parsed as shown in the left plot.

However, storing the same data inside a macro using \pgfplotstableread doesn't result in the same expected output.

Why is there a difference between both ways? and how to make the second approach of pgfplotstableread work like the first one of *.dat file?

\documentclass[border=1cm]{standalone}

\usepackage{pgfplots,pgfplotstable}

\pgfplotsset{compat=newest,
    poles/.style= { only marks, mark=x, mark size = 1ex, thick},
    point meta = explicit symbolic,
    visualization depends on={\thisrow{angle} \as \myangle},
    visualization depends on={value \thisrow{label} \as \mylabel},
    Label Style/.style args = {#1}{
        nodes near coords,
        every node near coord/.style = %
        {
            anchor=south, label={[#1]\myangle:{\mylabel}}
        },
    }
}

\usepackage{filecontents}
\begin{filecontents*}{poles.dat}
    Re      Im      label       angle
    -2      2       (-2,2)      270
    -2      -2      (-2,-2)     90
    -4      0       (-4,0)      60
\end{filecontents*}

\pgfplotstableread{
    Re      Im      label       angle
    -2      2       (-2,2)      270
    -2      -2      (-2,-2)     90
    -4      0       (-4,0)      60
}\mytable

\begin{document} 
    \begin{tikzpicture}
    \begin{axis}
        \addplot[Label Style={blue,fill = gray!20},poles]   table {poles.dat};
    \end{axis}
    \end{tikzpicture}
    \begin{tikzpicture}
    \begin{axis}
        \addplot[Label Style={blue,fill = gray!20},poles]   table {\mytable};
    \end{axis}
    \end{tikzpicture}
\end{document}

enter image description here

  • 1
    I guess that the remarks on the bottom of p. 58 of the pgfplots manual may be of interest here. – user121799 Nov 22 '18 at 17:45
  • @marmot , I see. So, is there any workaround to store a table data inside a macro to use it later the same way I do with that physical *.dat file? – Diaa Nov 22 '18 at 19:52
  • Yes, you can do that. I believe that this is one of the craziest things I ever did, but yes, it does work. Please let me know if you want me to spell this out. – user121799 Nov 22 '18 at 19:56
2

I found the following in the pgfplots source code.

% The normal implementation of \thisrow is not accessable here. And the
% worst is: error messages are impossible either because they are
% not executed... we resort to the associated math functions:
\def\thisrow##1{thisrow("##1")}% let us hope that math parsing is active!

Note that this solution always uses \mytable. The key was the use of \coordindex.

\documentclass[border=1cm]{standalone}

\usepackage{pgfplotstable,pgfplots}

\pgfplotsset{compat=newest,
    poles/.style= { only marks, mark=x, mark size = 1ex, thick},
    point meta = explicit symbolic,
    visualization depends on={\thisrow{angle} \as \myangle},
    %visualization depends on={value \thisrow{label} \as \mylabel},
    Label Style/.style args = {#1}{
        nodes near coords,
        every node near coord/.style = %
        {
            anchor=south, label={[#1]\myangle:{\pgfplotstablegetelem{\coordindex}{label}\of{\mytable}\pgfplotsretval}}
        },
    }
}
\newcommand{\myotherlabel}{\pgfmathparse{\thisrow{label}}\pgfmathresult}

\usepackage{filecontents}
\begin{filecontents*}{poles.dat}
    Re      Im      label       angle
    -2      2       (-2,2)      270
    -2      -2      (-2,-2)     90
    -4      0       (-4,0)      60
\end{filecontents*}

\pgfplotstableread[columns/label/.style={string}]{
    Re      Im      label       angle
    -2      2       (-2,2)      270
    -2      -2      (-2,-2)     90
    -4      0       (-4,0)      60
}\mytable

\begin{document} 
    \begin{tikzpicture}
    \begin{axis}
        \addplot[Label Style={blue,fill = gray!20},poles]   table {poles.dat};
    \end{axis}
    \end{tikzpicture}
    \begin{tikzpicture}
    \begin{axis}
        \addplot[Label Style={blue,fill = gray!20},poles]   table {\mytable};
    \end{axis}
    \end{tikzpicture}
\end{document}
| improve this answer | |
  • 3
    I am sorry, but could you please show me how this workaround can be implemented in my MWE? Thanks – Diaa Nov 22 '18 at 19:50
  • It took a while. Done now. – John Kormylo Nov 23 '18 at 16:09
  • Short and perfect workaround. Is it possible to make the table macro name (i.e. \mytable) variable and dependent of that assigned by \pgfplotstableread? – Diaa Nov 23 '18 at 18:17
  • Additionally, does your answer imply that the answer to my main question (in the title) is there is no difference between storing table data by filecontents and pgfplotstableread? It would be great if you make this answer more informative and comprehensive for the future readers by addressing the differences between both approaches. – Diaa Nov 23 '18 at 18:27
  • Obviously pgfplots handles files differently than macros. The code I found only applies when using macros. A totally different set of definitions are used when reading files directly. Note that my solution will not work if \mytable was not created. – John Kormylo Nov 24 '18 at 13:23
4

Here is a crazy workaround: write the table to a file and read it again. (Of course, in the present example this does not make sense.) However, there are situations in which it can make sense, e.g. when you create the table through macros or when you really want to skip some rows, like here.

\documentclass[border=1cm]{standalone}

\usepackage{pgfplots,pgfplotstable}

\pgfplotsset{compat=newest,
    poles/.style= { only marks, mark=x, mark size = 1ex, thick},
    point meta = explicit symbolic,
    visualization depends on={\thisrow{angle} \as \myangle},
    visualization depends on={value \thisrow{label} \as \mylabel},
    Label Style/.style args = {#1}{
        nodes near coords,
        every node near coord/.style = %
        {
            anchor=south, label={[#1]\myangle:{\mylabel}}
        },
    }
}

% from https://tex.stackexchange.com/a/445369/121799
\newcommand*{\ReadOutElement}[4]{%
    \pgfplotstablegetelem{#2}{#3}\of{#1}%
    \let#4\pgfplotsretval
}
% based on https://tex.stackexchange.com/a/307032/121799
% and https://tex.stackexchange.com/a/451326/121799
\newcommand{\GetRow}[2]{
\pgfplotstablegetcolsof{\mytable}
\pgfmathtruncatemacro{\colnumber}{\pgfplotsretval-1}
\foreach \XX in {0,...,\colnumber}
{%
\ReadOutElement{\mytable}{#1}{[index]\XX}{\tmp}%
\ifnum\XX=0%
\xdef#2{{\tmp}}%
\else%
\xdef#2{#2,{\tmp}}%
\fi%
}
}

\usepackage{filecontents}
\begin{filecontents*}{poles.dat}
    Re      Im      label       angle
    -2      2       (-2,2)      270
    -2      -2      (-2,-2)     90
    -4      0       (-4,0)      60
\end{filecontents*}

\pgfplotstableread{
    Re      Im      label       angle
    -2      2       (-2,2)      270
    -2      -2      (-2,-2)     90
    -4      0       (-4,0)      60
}\mytable

\pgfplotstablegetrowsof{\mytable}%
\pgfmathtruncatemacro{\rownum}{\pgfplotsretval-1}%
\pgfplotstablegetcolsof{\mytable}%
\pgfmathtruncatemacro{\colnum}{\pgfplotsretval-1}%
\foreach \X in {0,...,\colnum}%
{\pgfplotstablegetcolumnnamebyindex{\X}\of{\mytable}\to\pgfplotsretval%
\ifnum\X=0%
\xdef\tmp{\pgfplotsretval}%
\else%
\xdef\tmp{\tmp,\pgfplotsretval}%
\fi}
\newwrite\myoutput% from https://tex.stackexchange.com/a/290058/121799
\immediate\openout\myoutput=\jobname-tmp.dat%
\immediate\write\myoutput{\tmp}% create table header
\foreach \X in {0,...,\rownum}% rows
{\GetRow{\X}{\myrow}%
\immediate\write\myoutput{\myrow}}%
\immediate\closeout\myoutput%

\begin{document} 
    \begin{tikzpicture}
    \begin{axis}
        \addplot[Label Style={blue,fill = gray!20},poles]   table {poles.dat};
    \end{axis}
    \end{tikzpicture}
    \begin{tikzpicture}
    \begin{axis}
        \addplot[Label Style={blue,fill = gray!20},poles]   
        table[col sep=comma] {\jobname-tmp.dat};
    \end{axis}
    \end{tikzpicture}
\end{document}

enter image description here

Needless to say that one could clean up the macros. I hesitate to do that before I know all possible applications. One is to skip rows, which is important for regression plots, and another one is like here in which one uses pgfplots to do more complicated annotations. I'm wondering if there are further obvious use cases.

| improve this answer | |
  • Thanks for this surprisingly big workaround :) I will go through it comprehensively then I will get back to you. Thanks again – Diaa Nov 22 '18 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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