1
% Density Show Test
\pgfmathdeclarefunction{DensityShowTest}{2}{%
\pgfmathparse{dim("#1")==3}%
\ifnum\pgfmathresult=1%
  \pgfmathparse{1000*#2}%
  \pgfmathparse{"\pgfmathprintnumber[fixed, precision=2]{\pgfmathresult}"}%
\else%
   \pgfmathparse{#2==-1 ? "?" : "\pgfmathprintnumber[fixed, precision=2]{#2}"}% 
\fi}
% usage:
% \pgfmathparse{DensityShowTest("gas", 0.0008)}\pgfmathresult 

I have a pgfmathdeclarefunction DensityShowTest, that tests whether the \Phase is equal to 'gas', then the value \Density has to be multiplicated by 1000 (else not).

If the \Phase equal to 'unknown', the \Density is equal to '-1' (which means unknown as well).

And the value of the Density (if not "?") has to be rounded to 2 digits (in all cases); which seems to be problematic.

The problem I have is, that I cannot write out that function; it must have something to do with the part \pgfmathprintnumber[fixed, precision=2]{\pgfmathresult}

enter image description here

Comment: Everything would be much easier if TikZ had an arithmetic rounding function, but the rounded version of a number has to be reserved for the written output at TikZ...

\documentclass[]{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\pgfplotstableread[col sep = semicolon, header=true]{
Z;     Symbol;     Phase;     Density;    EXPECTED OUTPUT
1;     H;             gas;     0.0000899; 0.09
3;     Li;             solid;  0.53;      0.53 
118; Og;           unknown;  -1;          ?
}{\psetable}

% Density Show Test
\pgfmathdeclarefunction{DensityShowTest}{2}{%
\pgfmathparse{dim("#1")==3}%
\ifnum\pgfmathresult=1%
  \pgfmathparse{1000*#2}%
  \pgfmathparse{"\pgfmathprintnumber[fixed, precision=2]{\pgfmathresult}"}%
\else%
   \pgfmathparse{#2==-1 ? "?" : "\pgfmathprintnumber[fixed, precision=2]{#2}"}% 
\fi}
% usage:
% \pgfmathparse{DensityShowTest("gas", 0.0008)}\pgfmathresult 

\def\Filename{densityshowtest.txt}
\newwrite\MyPSE
\immediate\openout\MyPSE=\Filename

\begin{document}
\foreach \row in {0,...,2}{%%
% In:   
\pgfplotstablegetelem{\row}{Z}\of{\psetable}
\xdef\Z{\pgfplotsretval}
\pgfplotstablegetelem{\row}{Symbol}\of{\psetable}
\xdef\Symbol{\pgfplotsretval}
%% Phase
\pgfplotstablegetelem{\row}{Phase}\of{\psetable}
\xdef\Phase{\pgfplotsretval}
% Density Test
\pgfplotstablegetelem{\row}{Density}\of{\psetable}%
\xdef\Density{\pgfplotsretval}%
\pgfmathsetmacro\DensityShowTest{DensityShowTest("\Phase", \Density)}
% OUT:
% This works:
\noindent \Z;~~~\Symbol;~~\Density; ~~\Phase; ~~\DensityShowTest \\
%
%  Problem here  =======================
%
% This works not: ======================
%\immediate\write\MyPSE{\Z; \Symbol; \Density; \Phase; \DensityShowTest}
}%%
\immediate\closeout\MyPSE

% So this does not work too: 
\pgfplotstableread[col sep=semicolon, header=true,]{\Filename}{\mytable}
\pgfplotstabletypeset[string type]{\mytable}
\end{document}
4
  • Code passed through \write must be fully expandable to be fully expanded. I'd guess that \pgfmathprintnumber isn't expandable.
    – Skillmon
    May 30, 2021 at 18:32
  • So I have to use: \fpeval{round(#2,2)}
    – cis
    May 30, 2021 at 18:51
  • No, but you have to change your DensityShowTest function (it can't work the way you're using it).
    – Skillmon
    May 30, 2021 at 18:51
  • “Everything would be much easier if TikZ had an arithmetic rounding function” There is a round function. May 30, 2021 at 20:02

2 Answers 2

2

You can try to eagerly format the result within the function using \pgfmathprintnumberto. Note that this is really not how these functions should be used.

\documentclass[]{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\pgfplotstableread[col sep = semicolon, header=true]{
Z;     Symbol;     Phase;     Density
1;     H;             gas;          0.0000899
3;     Li;             solid;        0.53
118; Og;           unknown;  -1
}{\psetable}

% Density Show Test
\pgfmathdeclarefunction{DensityShowTest}{2}{%
\ifnum\pdfstrcmp{#1}{gas}=0
  \pgfmathparse{1000*#2}%
  \pgfmathprintnumberto[fixed, precision=2]{\pgfmathresult}{\pgfmathresult}%
\else%
  \pgfmathparse{#2==-1 ? "\unexpanded{\def\pgfmathresult{?}}" : "\unexpanded{\pgfmathprintnumberto[fixed, precision=2]{#2}{\pgfmathresult}}"}%
  \pgfmathresult % evaluate the result to perform formatting
\fi
}
% usage:
% \pgfmathparse{DensityShowTest("gas", 0.0008)}\pgfmathresult 

\def\Filename{densityshowtest.txt}
\newwrite\MyPSE
\immediate\openout\MyPSE=\Filename

\begin{document}
\foreach \row in {0,...,2}{%%
% In:   
\pgfplotstablegetelem{\row}{Z}\of{\psetable}
\xdef\Z{\pgfplotsretval}
\pgfplotstablegetelem{\row}{Symbol}\of{\psetable}
\xdef\Symbol{\pgfplotsretval}
%% Phase
\pgfplotstablegetelem{\row}{Phase}\of{\psetable}
\xdef\Phase{\pgfplotsretval}
% Density Test
\pgfplotstablegetelem{\row}{Density}\of{\psetable}%
\xdef\Density{\pgfplotsretval}%
\pgfmathparse{DensityShowTest("\Phase", \Density)}%
\xdef\DensityShowTest{\pgfmathresult}%
% OUT:
% This works:
\noindent \Z;~~~\Symbol;~~\Density; ~~\Phase; ~~\DensityShowTest \\
%
%  Problem here  =======================
%
%  This works not: ======================
\immediate\write\MyPSE{\Z; \Symbol; \Density; \Phase; \DensityShowTest}
}%%
\immediate\closeout\MyPSE

% So this does not work too: 
\pgfplotstableread[col sep=semicolon, header=true,]{\Filename}{\mytable}
\pgfplotstabletypeset[string type]{\mytable}
\end{document}

enter image description here

13
  • Aha. But there seems to be a mistake in the first decision, the output at gas should here be 0.09 (not 0). I had have said the values.
    – cis
    May 30, 2021 at 20:45
  • See the new colum 'EXPECTED OUTPUT' too.
    – cis
    May 30, 2021 at 20:50
  • In fact: it doesn't work that way. With the first \pgfmathprintnumberto he rounds the initial value, not the value 1000*#2.
    – cis
    May 31, 2021 at 16:37
  • @cis To be honest, I have no idea what this is supposed to do at all. For example what do you expect the result of dim("#1") to be? You know that dim will only work for arrays? Yet you are passing a string so the result will probably be 0 all the time. May 31, 2021 at 19:40
  • Maybe a strange method with that dim, but dim("gas") = 3 and this is the one and only case, so this part works for me.
    – cis
    May 31, 2021 at 20:12
1

The following doesn't use a pgfmath function, as you want to return strings and the like, that's not what these functions are made for.

It'll do what you want (I guess):

Edit: former version didn't strip the math mode from the results of \pgfmathprintnumberto.

\documentclass[]{article}

\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\pgfplotstableread[col sep = semicolon, header=true]
  {
    Z;     Symbol;     Phase;     Density
    1;     H;             gas;          0.0000899
    3;     Li;             solid;        0.53
    118; Og;           unknown;  -1
  }
  {\psetable}

\makeatletter
\newcommand\cisstrcmp[2]
  {%
    \begingroup
      \edef\tmpa{\detokenize{#1}}%
      \edef\tmpb{\detokenize{#2}}%
      \expandafter
    \endgroup
    \ifx\tmpa\tmpb
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }
\makeatother
\newcommand*\parseDensityShowTest
  {%
    \expandafter\cisstrcmp\expandafter{\Phase}{gas}%
      {%
        \pgfmathparse{1000*\Density}%
        \pgfmathprintnumberto[fixed, precision=2]\pgfmathresult\DensityShowTest
      }
      {%
        \pgfmathparse{\Density==-1}%
        \ifnum\pgfmathresult=1
          \def\DensityShowTest{"?"}%
        \else
          \pgfmathprintnumberto[fixed, precision=2]{\Density}\DensityShowTest
        \fi
      }%
    \stripensuremath\DensityShowTest
  }
\makeatletter
\newcommand*\stripensuremath[1]
  {%
    \edef#1%
      {%
        \unexpanded\expandafter\expandafter\expandafter
          {\expandafter\@secondoftwo#1}%
      }%
  }
\makeatother

\def\Filename{densityshowtest.txt}
\newwrite\MyPSE
\immediate\openout\MyPSE=\Filename

\begin{document}
\foreach \row in {0,...,2}
  {%%
    % In:   
    \pgfplotstablegetelem{\row}{Z}\of{\psetable}%
    \let\Z\pgfplotsretval
    \pgfplotstablegetelem{\row}{Symbol}\of{\psetable}%
    \let\Symbol\pgfplotsretval
    %% Phase
    \pgfplotstablegetelem{\row}{Phase}\of{\psetable}%
    \let\Phase\pgfplotsretval
    % Density Test
    \pgfplotstablegetelem{\row}{Density}\of{\psetable}%
    \let\Density\pgfplotsretval
    \parseDensityShowTest
    % OUT:
    % This works:
    %\noindent \Z;~~~\Symbol;~~\Density; ~~\Phase; ~~\DensityShowTest \\
    %
    %  Problem here  =======================
    %
    % This works not: ======================
    \immediate\write\MyPSE{\Z; \Symbol; \Density; \Phase; \DensityShowTest}
  }%%
\immediate\closeout\MyPSE

% So this does not work too: 
\pgfplotstableread[col sep=semicolon, header=true,]{\Filename}{\mytable}
\pgfplotstabletypeset[string type]{\mytable}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .