# Build PGF/TikZ matrix from CSV file

I want to automatically build a PGF/TikZ based drawing based on some external data that is read using csvsimple. My main issue at the moment is that most of the nodes are part of a matrix, mainly to setup a consistent spacing. Asssembling the contents of \matrix{csv-stuff-goes-here} didn't get me very far, so I tried to use \NewEnviron to define a custom matrix environment. The first examples looked promising:

\documentclass{article}
\usepackage{environ}
\usepackage{tikz}

\begin{document}

% working example
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\matrix{
\draw (0,0) circle (4mm); & \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); & \node (n2) {world}; \\
};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

% this works as well
\NewEnviron{TheMatrix}{\matrix[ampersand replacement=\&]{\BODY};}
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); \& \node (n2) {world}; \\
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

\end{document}


Now I wanted to introduce the csvsimple package - and failed miserably. MNWE:

\documentclass{article}
\usepackage{environ}
\usepackage{filecontents}
\usepackage{csvsimple}
\usepackage{tikz}

\begin{filecontents*}{mystuff.csv}
mynode;mytext
n1;Hello
n2;World
\end{filecontents*}

\begin{document}

% working example
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\matrix{
\draw (0,0) circle (4mm); & \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); & \node (n2) {world}; \\
};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

% this works as well
\NewEnviron{TheMatrix}{\matrix[ampersand replacement=\&]{\BODY};}
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); \& \node (n2) {world}; \\
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

% now let's try it from a CSV file
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (\mynode) {\mytext}; \\
}
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

\end{document}


The reported error is

pdflatex.exe> ! Missing } inserted.
pdflatex.exe> <inserted text>
pdflatex.exe>                 }
pdflatex.exe> l.40   \end{TheMatrix}


I have no idea why the system assumes there's abracket missing and how to find out what actually went wrong. I've tried to turn on some additional tracing with

\tracinggroups=1
\tracingnesting=2


but I have no idea how to get any meaning from the output. What is going on here and how do I debug things like this?

• There could be some trickery to build up a \BODY-like macro from the CSV contents and to parse that afterwards inside a \matrix, but maybe another approach instead of \matrix is preferrable? – Thomas F. Sturm Jan 22 '15 at 16:18
• I don't know why but adding double backslash (I don't know how to write it here) before \end{TheMatrix} worked for me. – Ignasi Jan 22 '15 at 16:22
• @ThomasF.Sturm I've converted the comment in answer to better show what I did. – Ignasi Jan 22 '15 at 16:34

Here is a CSV approach with some trickery. The CSV file is read and its content put inside a macro \BODY. This \BODY is used inside the matrix later.

This may not work, if the CSV content contains macros or umlauts since everything is expanded before it is added to \BODY.

\documentclass{article}
\usepackage{environ}
\usepackage{filecontents}
\usepackage{csvsimple,etoolbox}
\usepackage{tikz}

\begin{filecontents*}{mystuff.csv}
mynode;mytext
n1;Hello
n2;World
\end{filecontents*}

\begin{document}

% working example
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\matrix{
\draw (0,0) circle (4mm); & \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); & \node (n2) {world}; \\
};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

% this works as well
\NewEnviron{TheMatrix}{\matrix[ampersand replacement=\&]{\BODY};}
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); \& \node (n2) {world}; \\
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

\def\BODY{}
% now let's try it from a CSV file
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\eappto\BODY{\noexpand\draw (0,0) circle (4mm); \noexpand\& \noexpand\node (\mynode) {\mytext}; \noexpand\\}
}
\matrix[ampersand replacement=\&]{\BODY};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

\end{document}


This is not an answer, but I didn't know how to include \\ inside a comment. I've inserted \\ before \end{TheMatrix} in last example and worked. Why? I've no idea, just luck.

\documentclass{article}
\usepackage{environ}
\usepackage{filecontents}
\usepackage{csvsimple}
\usepackage{tikz}

\begin{filecontents*}{mystuff.csv}
mynode;mytext
n1;Hello
n2;World
\end{filecontents*}

\begin{document}

% working example
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\matrix{
\draw (0,0) circle (4mm); & \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); & \node (n2) {world}; \\
};
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

% this works as well
\NewEnviron{TheMatrix}{\matrix[ampersand replacement=\&]{\BODY};}
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}
\draw (0,0) circle (4mm); \& \node (n1) {Hello}; \\
\draw (0,0) circle (2mm); \& \node (n2) {world}; \\
\end{TheMatrix}
\draw[thick, draw=black] (n1) -- (n2);
\end{tikzpicture}

% now let's try it from a CSV file
\begin{tikzpicture}[every matrix/.style = {column sep = 0.8 cm, row sep = 0.2 cm}]
\begin{TheMatrix}

• Seems, I have underestimated the combination of environ and the TikZ parser :-) – Thomas F. Sturm Jan 22 '15 at 16:34