[Tex/LaTex] Define a variable containing color

colortikz-pgf

We can define a variable and pass it to a module using

\pgfmathsetmacro\j{6}

Which it means j=6, How can I define a variable for a color, I mean I want to pass color to a module

\pgfmathsetmacro\colr{white}

But I encountered Unknown function 'white'. How can I solve it?!
I have the below code

\usepackage{xcolor}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{calc}
\usepackage{graphicx}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{appendix}
\usepackage{array,textcomp}
\usepackage[latin1]{inputenc}
\usetikzlibrary{bayesnet}
\usetikzlibrary{positioning}
\usepackage{color}
\usepackage{caption}
\pgfmathsetseed{5}
\makeatletter
\DeclareRobustCommand{\rvdots}{%
  \vbox{
    \baselineskip4\p@\lineskiplimit\z@
    \kern-\p@
    \hbox{.}\hbox{.}\hbox{.}
  }}
\makeatother
\tikzset{main/.style={circle, minimum size = .1cm, thick, draw =black!80, node distance = 3mm},
         connect/.style={-latex, thick},
         box/.style={rectangle, draw=black}
}
\begin{document}
  \begin{tikzpicture}[lds/.pic={j=#1,colr=#2,%<----- here is the variable
      \node[box,draw=\colr] (-Latent) {};
      \node[main,minimum size=.2cm, right=of -Latent] (-L1) {$x_1^{(\j)}$};
      \node[main,minimum size=.2cm] (-L2) [right=of -L1] {$x_2^{(\j)}$};
      \node[main,minimum size=.2cm] (-Lt) [right=5mm of -L2] {$x_T^{(\j)}$};
      \node[box,draw=white!100] (-Observed) [below=of -Latent] {};
      \node[main,fill=black,text=white,minimum size=.2cm] (-O1) [right=of -Observed,below=of -L1] {$y_1^{(\j)}$};
      \node[main,fill=black,text=white,minimum size=.2cm] (-O2) [right=of -O1,below=of -L2] {$y_2^{(\j)}$};
      \node[main,fill=black,text=white,minimum size=.2cm] (-Ot) [right=of -O2,below=of -Lt] {$y_T^{(\j)}$};
      \draw (-L1.east) edge [connect] (-L2);
      \node at (16,0) {$\dots$};
      \path (-L1.south) edge [connect] (-O1);
      \path (-L2.south) edge [connect] (-O2);
      \path (-Lt.south) edge [connect] (-Ot);
           },my text/.style={rounded corners=2pt, text width=10mm,     font=\sffamily, line width=.5pt, align=left},
      my arrow/.style={rounded corners=2pt, draw=green!15, line width=1.5mm, -{Triangle[]}}]
    \pgfmathsetmacro\j{6} 
    \def\colr{white} %<----here
    \pic(lds1) at (0,7){lds};
  \end{tikzpicture}
\end{document}

Best Answer

I don't know if the syntax you use at the beginning of the pic lds definition is legal, I never saw it like that, but my guess is that it is illegal. When you write j=#1,colr=#2 my guess is that those tokens are simply ignored by tikz (unless it is a kind of key-value syntax I'm not aware of).

Later, in your "main" tikz code you define \j, and this is the reason why when you use \j later in your code it works, but the assignment j=#1 has nothing to do with it. For the same reason, \def\colr in the "main" part of the figure should work too (in my test, it worked).

However, I think the correct syntax for passing several values to a pic (as explained for example in this answer is as follows:

\tikzset{
 pics/lds/.style 2 args={code={
 % ... here #1 and #2 can be used
 % ...
 }}
}

In your code, you should use #1 instead of \j and #2 instead of \colr. But also, if you prefer not changing your code, you can start the definition of lds pic as follows:

\tikzset{
 pics/lds/.style 2 args={code={
  \pgfmathsetmacro\j{#1}
  \def\colr{#2}
  % The remaining code is untouched
 }}

Later, to use this pic, you write: \pic(lds1) at (0,7) {lds={6}{white}};.

Complete code:

\tikzset{
main/.style={circle, minimum size = .1cm, thick, draw =black!80, node distance = 3mm},
connect/.style={-latex, thick},
box/.style={rectangle, draw=black},
pics/lds/.style 2 args={code={
      \pgfmathsetmacro\j{#1}
      \def\colr{#2}%<----- here is the variable
      \node[box,draw=\colr] (-Latent) {};
      \node[main,minimum size=.2cm, right=of -Latent] (-L1) {$x_1^{(\j)}$};
      \node[main,minimum size=.2cm] (-L2) [right=of -L1] {$x_2^{(\j)}$};
      \node[main,minimum size=.2cm] (-Lt) [right=5mm of -L2] {$x_T^{(\j)}$};
      \node[box,draw=white!100] (-Observed) [below=of -Latent] {};
      \node[main,fill=black,text=white,minimum size=.2cm] (-O1) [right=of -Observed,below=of -L1] {$y_1^{(\j)}$};
      \node[main,fill=black,text=white,minimum size=.2cm] (-O2) [right=of -O1,below=of -L2] {$y_2^{(\j)}$};
      \node[main,fill=black,text=white,minimum size=.2cm] (-Ot) [right=of -O2,below=of -Lt] {$y_T^{(\j)}$};
      \draw (-L1.east) edge [connect] (-L2);
      \node at (16,0) {$\dots$};
      \path (-L1.south) edge [connect] (-O1);
      \path (-L2.south) edge [connect] (-O2);
      \path (-Lt.south) edge [connect] (-Ot);
           }},
%my text/.style={rounded corners=2pt, text width=10mm,font=\sffamily, line width=.5pt, align=left},
%my arrow/.style={rounded corners=2pt, draw=green!15, line width=1.5mm, -{Triangle[]}}      
}

  \begin{tikzpicture}[]
    \pic(lds1) at (0,7) {lds={6}{white}};
  \end{tikzpicture}

Result:

Result

In addition, I would prefer to use \colorlet instead of \def when definig colors. This means to change \def\colr{#2} by \colorlet{colr}{#2}, and then, when the color is needed, write it with the same syntax than any of the predefined colors, i.e., for example draw=colr instead of draw=\colr.

This way you can define "mixings" based on the color received in #2, as for example: \colorlet{myforeground}{#2!30!white}, \colorlet{mybackground}{#2!30!black}.