[Tex/LaTex] How to import data from a CSV file in a figure caption using csvsimple

captionscsvcsvsimple

I have made a pretty report that gets all the data from CSV files data.csv like this :

Images,Infos,Bayer,BilineaireA,BilineaireB,TeinteA,TeinteB,ContourA,ContourB,Forme

img1(illusion),Temps (en ms),0,4,5,7,6,6,7,442
img1(illusion),Erreur MSE,152.44,34.44,34.44,24.04,24.04,24.06,25.99,32.90
img1(illusion),Erreur DeltaE,17.70,4.92,4.92,4.58,4.58,4.39,4.30,5.24
img1(illusion),Erreur PSNR (en dB),26.30,32.76,32.76,34.32,34.32,34.32,33.98,32.96

img2(points1),Temps (en ms),0,1,4,3,3,2,3,123
img2(points1),Erreur MSE,6.28,3.83,3.83,3.24,3.28,2.69,2.36,2.56
img2(points1),Erreur DeltaE,0.79,1.09,1.09,0.72,0.72,0.63,0.34,0.60
img2(points1),Erreur PSNR (en dB),40.15,42.30,42.30,43.02,42.97,43.83,44.41,44.05
...

I've written many macros like the one below which reads the MSE error for an image #1 generated using a given algorithm #2 (be gentle, it's the first time I write my own macro !) :

\newcommand{\MSE}[2]{%
\csvreader[ head to column names,%
            before filter=\ifthenelse{ \equal{\Images}{#1} }{%
                          \ifthenelse{ \equal{\Infos}{Erreur MSE} }{\csvfilteraccept}{\csvfilterreject}%
                           }{\csvfilterreject}]% 
          {data.csv}{}{#2}%
}

Nevertheless, it seems that I can't use my macros inside captions of figures (and subfigures too). Here is a minimal example that fails :

\begin{filecontents*}{data.csv}
Images,Infos,Bayer,BilineaireA,BilineaireB,TeinteA,TeinteB,ContourA,ContourB,Forme

img1(illusion),Temps (en ms),0,4,5,7,6,6,7,442
img1(illusion),Erreur MSE,152.44,34.44,34.44,24.04,24.04,24.06,25.99,32.90
img1(illusion),Erreur DeltaE,17.70,4.92,4.92,4.58,4.58,4.39,4.30,5.24
img1(illusion),Erreur PSNR (en dB),26.30,32.76,32.76,34.32,34.32,34.32,33.98,32.96
\end{filecontents*}
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{csvsimple}

\newcommand{\MSE}[2]{%
\csvreader[ head to column names,%
            before filter=\ifthenelse{ \equal{\Images}{#1} }{%
                          \ifthenelse{ \equal{\Infos}{Erreur MSE} }{\csvfilteraccept}{\csvfilterreject}%
                           }{\csvfilterreject}]% 
          {data.csv}{}{#2}%
}

\begin{document}
\listoffigures
\begin{figure}
    \centering
    My Image
    \caption{A caption \MSE{img1(illusion)}{\BilineaireA} }
\end{figure}
\end{document}

I can read ! TeX capacity exceeded. If I put my command inside a minipage environment, I get the following error :

Argument of \@caption has an extra }

Thank you for your help !

Best Answer

An error message such as

Argument of \@caption has an extra }

usually means that a command in the argument of \caption needs protection. In this case the command is surely \MSE. Thus

\caption{A caption \protect\MSE{img1(illusion)}{\BilineaireA}}

might solve the problem.

However, in this particular application \protect is not sufficient. We need something that contains the value we need, so a different road can be taken. Define a similar \MSEset macro, that takes also an optional argument (default value \MSEresult:

\begin{filecontents*}{data.csv}
Images,Infos,Bayer,BilineaireA,BilineaireB,TeinteA,TeinteB,ContourA,ContourB,Forme

img1(illusion),Temps (en ms),0,4,5,7,6,6,7,442
img1(illusion),Erreur MSE,152.44,34.44,34.44,24.04,24.04,24.06,25.99,32.90
img1(illusion),Erreur DeltaE,17.70,4.92,4.92,4.58,4.58,4.39,4.30,5.24
img1(illusion),Erreur PSNR (en dB),26.30,32.76,32.76,34.32,34.32,34.32,33.98,32.96
\end{filecontents*}
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{csvsimple}

\newcommand{\MSE}[2]{%
\csvreader[ head to column names,%
            before filter=\ifthenelse{ \equal{\Images}{#1} }{%
                          \ifthenelse{ \equal{\Infos}{Erreur MSE} }{\csvfilteraccept}{\csvfilterreject}%
                           }{\csvfilterreject}]% 
          {data.csv}{}{#2}%
}
\newcommand{\MSEset}[3][\MSEresult]{%
\csvreader[ head to column names,%
            before filter=\ifthenelse{ \equal{\Images}{#2} }{%
                          \ifthenelse{ \equal{\Infos}{Erreur MSE} }{\csvfilteraccept}{\csvfilterreject}%
                           }{\csvfilterreject}]% 
          {data.csv}{}{\xdef#1{#3}}%
}
\newbox{\remibox}

\begin{document}
\listoffigures
\begin{figure}
    \centering
    My Image
\MSEset{img1(illusion)}{\BilineaireA}
    \caption{A caption \MSEresult}
\end{figure}
\end{document}

You set the macro before typing the \caption and use \result to stand for the value. You can also say

\MSEset[\MSEresultA]{img1(illusion)}{\BilineaireA}

or any control sequence you want if you need more than one of these numbers. Take care of using control sequence names that are not used elsewhere (a common prefix such as MSE should do).

This will print the correct value also in the List of Figures, should you need it.