1

I want to combine two of my posts to get a running example for my electrical installation plan in TikZ.

In this post, I got the answer how to create a alphanumerical string with fixed length.

In this post, I got the answer how to derive a dynamic table and a TikZ input just from one single data list.

Now I want to combine both topics and bring the generated alphanumerical string into my single data list. From there, the \hash within the dynamic table should be the same hash value than used as my TikZ label.

MWE

\documentclass{article}
\usepackage[a4paper, margin=10mm]{geometry}
\usepackage{pgfplotstable}
\usepackage{mwe}
\pgfplotsset{compat=newest}

\ExplSyntaxOn
\sys_gset_rand_seed:n {0}
\NewExpandableDocumentCommand{\hash}{}
 {
  \__new_hash_three:e { \int_to_Base:nn { \int_rand:n { 46655 } } { 36 } } % three digits
 }
\cs_new:Nn \__new_hash_three:n
 {
  \prg_replicate:nn { 3 - \tl_count:n { #1 } } { 0 } #1
 }
\cs_generate_variant:Nn \__new_hash_three:n { e }
\ExplSyntaxOff

\begin{filecontents}{data.csv}
id, name, x-coord, y-coord, rotation
\hash, PowerSupply1, 3590, 2000, 270 %The \hash function seems to be called twice
\hash, PowerSupply2, 5590, 2500, 270
\end{filecontents}

\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}
\pgfmathtruncatemacro\CSVDataRows{\pgfplotsretval-1} 

\tikzset{
    pics/PowerSupply/.style={
        code={
            \tikzset{PowerSupply/.cd, #1}
            \node[anchor=north, inner sep=0pt] (-p)
                {\includegraphics[scale=0.09]{example-image-a}};
            \node[
                inner sep=0pt,
                anchor={90+\pgfkeysvalueof{/tikz/PowerSupply/label position}},
                rotate={-1*\pgfkeysvalueof{/tikz/PowerSupply/label position}}
            ] at (-p.south) {\tiny \pgfkeysvalueof{/tikz/PowerSupply/label}};
        }
    },
    PowerSupply/label/.initial={},
    PowerSupply/label position/.initial={0}
}
\begin{document}

\begin{center}
\pgfplotstabletypeset[
    col sep=comma,
    columns={id, name, x-coord, y-coord},
    columns/id/.style={
        column name=ID,
        string type
    },
    columns/name/.style={
        column name=Description,
        string type
    },
    columns/x-coord/.style={
        column name=X-Pos
    },
    columns/y-coord/.style={
        column name=Y-Pos,
        column type/.add={}{|}
    },
    column type/.add={|}{},
    after row={\hline},
    every head row/.style={before row=\hline},
]{data.csv}
\end{center}

\begin{figure}[h!]
\centering
\begin{tikzpicture}[x=0.01mm, y=-0.01mm]
    \node[inner sep=0pt] (ground_floor)   
        {\includegraphics[width=99.0mm, height=107.4mm]{example-image}};
    
    \begin{scope}[shift=(ground_floor.north west)]
        \foreach \row in {0,...,\CSVDataRows} {
            \pgfplotstablegetelem{\row}{x-coord}\of{\csvdata}
            \pgfmathsetmacro{\x}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{y-coord}\of{\csvdata}
            \pgfmathsetmacro{\y}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{rotation}\of{\csvdata}
            \pgfmathsetmacro{\r}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{id}\of{\csvdata}
            \pgfmathsetmacro{\i}{"\pgfplotsretval"}
            \pic[rotate=\r, transform shape] at (\x,\y) {
                PowerSupply={
                    label={\i}, % This label is different to the label in the table
                    label position={\r}
                }
            };
        }
    \end{scope}
\end{tikzpicture}
\end{figure}
\end{document}

OUTPUT Example

PROBLEM As you can see, the "shared" \hash from filecontents data list is different between the table representation and within the TikZ label. My assumption is, that the \hash function is called twice...

7
  • I am unsure why you would need to store hashes in your CSV which you then load again into your document. Why not just generating the hashes separately? You might want to store each hash in a separate macro or in some clist, so it does not change once it has been created. Feb 19 at 10:26
  • The problem really is, that you store "\hash" in the CSV and not the generated hashes. So, when the file is read (which happens indeed twice), TeX reads \hash and finally expands this. You can look into the file and you will not see any hashes in there. What you want to do is to generate hashes and store these in your CSV in the first place. Feb 19 at 10:30
  • See this nice answer for a way to solve this. Feb 19 at 10:34
  • Hmm I got your point. My idea was not to use a separate csv file, but have everything encapsulated within the LaTex file. The csv generation was just the workaround to feed two inputs (table & TikZ picture) with one single source of truth (filecontens list).
    – PascalS
    Feb 19 at 17:59
  • 1
    Actually, I like your questions. I don't use pgfplotstable that often and you stitch together a lot of interesting things! So it is nice to follow your thoughts and come up with solutions =) Feb 19 at 19:22

1 Answer 1

1

The problem in your code is that you store the string "\hash" in the CSV file and not the generated hashes. If you look into the CSV file, you won't find any hashes in there.

When the file is read in (which happens indeed twice), TeX encounters the token \hash and finally expands it. Because this expansion takes place first when the table is typeset and later again when the labels (= nodes) are typeset, the resulting hashes are not the same. In fact it is the same result as if you would have put \hash in your document four times.

From your comments I learned that you are not necessarily bound to use a CSV file. You just want to use the same data twice. You actually can just put the data inline without exporting them to a CSV. Anyways, you need to somehow make sure that the \hash commands are expanded before they are used for typsetting the table or the labels, so that the same token list (that is the expanded string) is used.

In the following example, I use \pgfplotstableread to read in the data inline. I then add a new column to the existing data using \pgfplotstablecreatecol which contains the expansion of the token list stored in the id column. In this case, the new column will then contain the expanded hashes. In the following code, I use the values from this new column.

\documentclass{article}
\usepackage[a4paper, margin=10mm]{geometry}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\ExplSyntaxOn
\sys_gset_rand_seed:n {0}
\NewExpandableDocumentCommand { \hash } { } {
    \__new_hash_three:e { \int_to_Base:nn { \int_rand:n { 46655 } } { 36 } } % three digits
}
\cs_new:Nn \__new_hash_three:n {
    \prg_replicate:nn { 3 - \tl_count:n { #1 } } { 0 } #1
}
\cs_generate_variant:Nn \__new_hash_three:n { e }
\ExplSyntaxOff

\pgfplotstableread{
    id name x-coord y-coord rotation
    \hash{} PowerSupply1 3590 2000 270 
    \hash{} PowerSupply2 5590 2500 270
}{\mydata}

\pgfplotstablecreatecol[
    create col/assign/.code={%
        \getthisrow{id}\idValue
        \edef\hashExp{\idValue}
        \pgfkeyslet{/pgfplots/table/create col/next content}\hashExp
    }
]{id-exp}{\mydata}

\pgfplotstablegetrowsof{\mydata}
\pgfmathtruncatemacro\myDataRows{\pgfplotsretval-1} 

\tikzset{
    pics/PowerSupply/.style={
        code={
            \tikzset{PowerSupply/.cd, #1}
            \node[anchor=north, inner sep=0pt] (-p)
                {\includegraphics[scale=0.09]{example-image-a}};
            \node[
                inner sep=0pt,
                anchor={90+\pgfkeysvalueof{/tikz/PowerSupply/label position}},
                rotate={-1*\pgfkeysvalueof{/tikz/PowerSupply/label position}}
            ] at (-p.south) {\tiny \pgfkeysvalueof{/tikz/PowerSupply/label}};
        }
    },
    PowerSupply/label/.initial={},
    PowerSupply/label position/.initial={0}
}
\begin{document}

\begin{center}
\pgfplotstabletypeset[
    col sep=comma,
    columns={id-exp, name, x-coord, y-coord},
    columns/id-exp/.style={
        column name=ID,
        string type
    },
    columns/name/.style={
        column name=Description,
        string type
    },
    columns/x-coord/.style={
        column name=X-Pos
    },
    columns/y-coord/.style={
        column name=Y-Pos,
        column type/.add={}{|}
    },
    column type/.add={|}{},
    after row={\hline},
    every head row/.style={before row=\hline},
]{\mydata}
\end{center}

\begin{figure}[h!]
\centering
\begin{tikzpicture}[x=0.01mm, y=-0.01mm]
    \node[inner sep=0pt] (ground_floor)   
        {\includegraphics[width=99.0mm, height=107.4mm]{example-image}};
    
    \begin{scope}[shift=(ground_floor.north west)]
        \foreach \row in {0,...,\myDataRows} {
            \pgfplotstablegetelem{\row}{x-coord}\of{\mydata}
            \pgfmathsetmacro{\x}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{y-coord}\of{\mydata}
            \pgfmathsetmacro{\y}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{rotation}\of{\mydata}
            \pgfmathsetmacro{\r}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{id-exp}\of{\mydata}
            \pgfmathsetmacro{\i}{"\pgfplotsretval"}
            \pic[rotate=\r, transform shape] at (\x,\y) {
                PowerSupply={
                    label={\i}, % This label is different to the label in the table
                    label position={\r}
                }
            };
        }
    \end{scope}
\end{tikzpicture}
\end{figure}
\end{document}

enter image description here

1
  • Made my Day! Thank you!! This is exactly what I searched for!
    – PascalS
    Feb 19 at 19:31

You must log in to answer this question.

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