7

Say I have two csv files representing the real and imaginary part of a complex matrix. I would like to nicely display this matrix in LaTeX. The difficulty is to correctly round numbers and not displaying them if they are rounded to 0.

For example, 1.0000000e+00 and 5.0000000e-01 should give 1+0.5i and 5.0000000e-01 and 0.0000000e+00 should not display the imaginary part (ie 0.5).

I started with these questions: Aligning complex numbers in centre of table with siunitx and Combine columns of a csv but couldn't come up with a satisfying solution.

Here is the start!

\documentclass{article}
\usepackage{pgfplotstable}

\begin{filecontents}{blah_real.csv}
  re1              re2
  1.0000000e+00    1.0000000e+00
  5.0000000e-01    5.0000000e-01
  0.0000000e+00    0.0000000e+00
  5.0000000e-01    5.0000000e-01
\end{filecontents}

\begin{filecontents}{blah_im.csv}
  0.0000000e+00   0.0000000e+00
  5.0000000e-01   5.0000000e-01
  1.0000000e+00   1.0000000e+00
  5.0000000e-01   5.0000000e-01
\end{filecontents}


\begin{document}

\newcommand{\complex}[1]{%
  \pgfplotstableread[col sep=space, trim cells=true]{#1_real.csv}\real
  \pgfplotstableread[col sep=space, trim cells=true, header=false]{#1_im.csv}\imaginary

  \pgfplotstablecreatecol[copy column from table={\imaginary}{[index] 0}]{im1}{\real}
  \pgfplotstablecreatecol[copy column from table={\imaginary}{[index] 1}]{im2}{\real}


  \pgfplotstabletypeset[
  columns/complex1/.style={string type, column name={}},
  create on use/complex1/.style={%
    create col/assign/.code={%
      \edef\value{%
        \noexpand
        \pgfmathprintcomplexnumber[fixed zerofill]{\thisrow{re1}}{\thisrow{im1}}}
      \pgfkeyslet{/pgfplots/table/create col/next content}\value
    }
  },
  columns/complex2/.style={string type, column name={}},
  create on use/complex2/.style={%
    create col/assign/.code={%
      \edef\value{%
        \noexpand
        \pgfmathprintcomplexnumber[fixed zerofill]{\thisrow{re2}}{\thisrow{im2}}}
      \pgfkeyslet{/pgfplots/table/create col/next content}\value
    }
  },
  columns={complex1, complex2}
  ]{\real}
}

\makeatletter

\def\pgfmathprintcomplexnumber{%
  % \protect allows to supply \pgfmathprintnumber inside of latex
  % captions. The \csname yields \relax in case protect is undefined.
  \pgf@texdist@protect\pgfmathprintcomplexnumber@protected
}%
\def\pgfmathprintcomplexnumber@protected{%
  \pgfutil@ifnextchar[%
  {\pgfmathprintcomplexnumber@OPT}%
  {\pgfmathprintcomplexnumber@noopt}%
}

\def\pgfmathprintcomplexnumber@noopt#1#2{%
  \begingroup
  \pgfmathprintnumber@{#1}%
  \let\pgfmathresultreal\pgfmathresult
  \pgfmathfloatparsenumber{\pgfmathresult}
  \pgfmathfloatifflags{\pgfmathresult}{0}{
    \let\pgfmathresultreal\empty
    \pgfqkeys{/pgf/number format}{showpos=false}%
  }{
    \pgfqkeys{/pgf/number format}{showpos=true}%
  }%
  \pgfmathprintnumber@{#2}%
  \let\pgfmathresultim\pgfmathresult
  \pgfmathfloatparsenumber{\pgfmathresult}
  \pgfmathfloatifflags{\pgfmathresult}{0}{%
    \let\pgfmathresultim\empty
  }{
    \edef\pgfmathresultim{\pgfmathresultim i}
  }%
  \ifpgfmathprintnumber@assumemathmode
  \pgfmathresultreal\pgfmathresultim
  \else
  \pgfutilensuremath{\pgfmathresultreal\pgfmathresultim}%
  \fi
  \endgroup
}%

\def\pgfmathprintcomplexnumber@OPT[#1]#2#3{%
  \begingroup
  \pgfqkeys{/pgf/number format}{#1}%
  \pgfmathprintnumber@{#2}%
  \let\pgfmathresultreal\pgfmathresult
  \pgfmathfloatparsenumber{\pgfmathresult}
  \pgfmathfloatifflags{\pgfmathresult}{0}{
    \let\pgfmathresultreal\empty
    \pgfqkeys{/pgf/number format}{showpos=false}%
  }{
    \pgfqkeys{/pgf/number format}{showpos=true}%
  }%
  \pgfmathprintnumber@{#3}%
  \let\pgfmathresultim\pgfmathresult
  \pgfmathfloatparsenumber{\pgfmathresult}

  \pgfmathfloatifflags{\pgfmathresult}{0}{%
    \let\pgfmathresultim\empty
  }{%
    \edef\pgfmathresultim{\pgfmathresultim i}
  }%
  \ifpgfmathprintnumber@assumemathmode
  \pgfmathresultreal\pgfmathresultim
  \else
  \pgfutilensuremath{\pgfmathresultreal\pgfmathresultim}%
  \fi
  \endgroup
}%

\makeatother

\complex{blah}

\end{document}

Any idea how to do this?

EDIT: Almost working example but I still have 0.00+1.00i and the plus sign is closer to the imaginary part...

EDIT2: \pgfmathprintcomplexnumber largely inspired by \pgfmathprintnumber. Remaining problem: 1i might be displayed

5

Naturally, you need to apply conditions of sorts "if number = 0 ... else ... endif".

This can be accomplished if you

  1. use \pgfmathfloatparsenumber to get intermediate results in float format
  2. use \pgfmathfloatifflags to check if the numbers is zero, positive, negative, not-a-number, inf, -inf.

Here is an example (I simplified the "combine different tables" part as it is unrelated to the task to format complex numbers):

\documentclass{standalone}
\usepackage{pgfplotstable}

\begin{document}

\pgfplotstabletypeset[
    columns/complex1/.style={string type, column name={}},
    create on use/complex1/.style={%
      create col/assign/.code={%
        \pgfmathfloatparsenumber{\thisrow{Re}}%
        \let\valueRe=\pgfmathresult
        \pgfmathfloatparsenumber{\thisrow{Im}}%
        \let\valueIm=\pgfmathresult
        \pgfmathfloatifflags{\valueRe}{0}{%
            % Ah: re = 0.0
            \def\valueRe{}%
        }{%
            \edef\valueRe{\noexpand\pgfmathprintnumber[fixed zerofill]{\valueRe}}%
        }%
        %\show\valueRe
        \pgfmathfloatifflags{\valueIm}{0}{%
            % Ah - im = 0.0
            \def\valueIm{}%
        }{%
            \edef\valueIm{\noexpand\pgfmathprintnumber[showpos,fixed zerofill]{\valueIm}i}%
        }%
        %\show\valueIm
        \toks0=\expandafter{\valueRe}%
        \toks1=\expandafter{\valueIm}%
        % we cannot use \edef\value{\valueRe\valueIm} as this would
        % expand \pgfmathprintnumber - which is not expandable.
        % Writing \the<tokenregister> expands the content of
        % <tokenregister> exactly once:
        \edef\value{\the\toks0 \the\toks1 }%
        %\show\value
        \pgfkeyslet{/pgfplots/table/create col/next content}\value
      }
    },
    %debug,
    columns={complex1},
]{
  Re                Im
  1.0000000e+00     0.0000000e+00
  5.0000000e-01     5.0000000e-01
  0.0000000e+00     1.0000000e+00
  5.0000000e-01     5.0000000e-01
}

\end{document}

enter image description here

References: quoting from the tikz manual pgfmanual.pdf:

\pgfmathfloatifflags{ floating point number }{ flag }{ true-code }{ false-code }
    Invokes { true-code } if the flag of { floating point number } equals { flag } and { false-code } other-
    wise.
    The argument { flag } can be one of
    0 to test for zero,
    1 to test for positive numbers,
    + to test for positive numbers,
    2 to test for negative numbers,
    - to test for negative numbers,
    3 for "not-a-number",
    4 for +infty,
    5 for -infty.

The token-register magic is explained in my document mentioned in Where do I start LaTeX programming?


The following part of the answer is about alignment. It appeared to be useful at first glance, but it is actually unnecessarily complicated because alignment could easily be done by simply typesetting "Re" and "Im" separately. Nevertheless, it works and might be useful to see how this stuff can be adopted.

Consider this part as "exercise for the advanced user".

Here is a modification (in only two places, in \edef\value and in column type) which aligns the results between real and imaginary part:

\documentclass{standalone}
\usepackage{pgfplotstable}

\begin{document}

\pgfplotstabletypeset[
    columns/complex1/.style={string type, column type={r@{}l},column name={}},
    create on use/complex1/.style={%
      create col/assign/.code={%
        \pgfmathfloatparsenumber{\thisrow{Re}}%
        \let\valueRe=\pgfmathresult
        \pgfmathfloatparsenumber{\thisrow{Im}}%
        \let\valueIm=\pgfmathresult
        \pgfmathfloatifflags{\valueRe}{0}{%
            % Ah: re = 0.0
            \def\valueRe{}%
        }{%
            \edef\valueRe{\noexpand\pgfmathprintnumber[fixed zerofill]{\valueRe}}%
        }%
        %\show\valueRe
        \pgfmathfloatifflags{\valueIm}{0}{%
            % Ah - im = 0.0
            \def\valueIm{}%
        }{%
            \edef\valueIm{\noexpand\pgfmathprintnumber[showpos,fixed zerofill]{\valueIm}i}%
        }%
        %\show\valueIm
        \toks0=\expandafter{\valueRe}%
        \toks1=\expandafter{\valueIm}%
        % we cannot use \edef\value{\valueRe\valueIm} as this would
        % expand \pgfmathprintnumber - which is not expandable.
        % Writing \the<tokenregister> expands the content of
        % <tokenregister> exactly once:
        \edef\value{\the\toks0 & \the\toks1 }%
        %\show\value
        \pgfkeyslet{/pgfplots/table/create col/next content}\value
      }
    },
    %debug,
    columns={complex1},
]{
  Re                Im
  1.0000000e+00     0.0000000e+00
  5.0000000e-01     5.0000000e-01
  0.0000000e+00     1.0000000e+00
  5.0000000e-01     5.0000000e-01
}

\end{document}

enter image description here

| improve this answer | |
  • Great, thanks! I finally wrote \pgfmathprintcomplexnumber inspired by \pgfmathprintnumber! It would be good to have this function in pgf – thisirs Oct 5 '13 at 12:00

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.