[Tex/LaTex] Referencing TikZ matrix nodes and drawing

tikz-matrixtikz-pgf

I'm struggling with a matrix where I want to put drawings into the cells, but would still like to reference the cells as it is possible with (text) nodes, e.g. for annotation.

I know that I can achieve this by putting text nodes and inside the text put another \tikz and draw (2nd row in the example). However, putting a text node into the tikz picture with the sole purpose of having another TikZ picture inside feels a terrible waste. Is there a more elegant way?

I tried to use nodes in empty cells = true, but the cells with drawings inside are not empty, they just don't have a node. So that doesn't help.

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usetikzlibrary{decorations.pathreplacing}
\begin{document}
\begin{tikzpicture}
\newcommand{\punkt}{\fill (0, 0) circle (1mm);}
\newcommand{\tpunkt}{{\tikz\fill (0, 0) circle (1mm);}}
\matrix (m) [matrix of nodes,
    nodes={rectangle,draw, fill=yellow}
]{
    \punkt  & \punkt \\
    \tpunkt & \tpunkt\\
};

\draw[decorate, decoration = brace] (m-2-2.south east) -- node [below] {foo} (m-2-1.south west);
% doesn't work, because nodes m-1-1 and m-1-2 do not exist:
% \draw[decorate, decoration = brace] (m-1-1.north west) -- node [above] {bar} (m-1-2.north east);
\end{tikzpicture}
\end{document}

To clarify a bit what I'm after:

  • the circles are not just circles in the real diagram, and there are different combinations of objects in the real diagram. That makes @cacamailg's answer even less elegant (and too complicated to keep the overview) than putting \tikz{} drawings into text nodes.
  • is there a way to hand the name tikz would give to the node to the drawing macro (\punkt{*tikz-node-name*}?

  • the |style| notation doesn't help, neither, because no node is generated if I have drawing commands in the cell.

  • I start thinking whether defining custom shapes that include the drawing commands is the solution.


Edit 2: the real example.

real example

Link to the .tex file

Best Answer

OK, there is a lot going on here, but hopefully the comments go someway to making it clear how I've achieved this. I use a lot of nested style definitions, which possibly may make things tricky to follow but hopefully the style names give some indication of what they do. I also use a lot of nested \foreach loops for no other reason than I found it easier than using a matrix.

Some apologies in advance for mangling the German words in the style definitions.

\documentclass[border=5pt]{standalone}
\usepackage{tikz}

% pifont for tick and cross.
\usepackage{pifont}

% Only need the matrix library for delimiters.
\usetikzlibrary{matrix,fit}
\usetikzlibrary{shapes.geometric}


% Define some colors.
\colorlet{Klasse A}{red}
\colorlet{Klasse B}{blue}
\colorlet{probe color}{Klasse A}
\colorlet{correct color}{Klasse A}
\colorlet{incorrect color}{Klasse A}
\colorlet{testproben}{gray!20}

\def\vmark{}

\tikzset{
    tight fit/.style={inner sep=0pt, outer sep=0pt},
    probe color/.code={\colorlet{probe color}{#1}},
    correct color/.code={\colorlet{correct color}{#1}},
    incorrect color/.code={\colorlet{incorrect color}{#1}},
    probe/.style args={#1-#2}{%
        outer sep=0pt,
        shape=rectangle,
        probe #1-#2/.try,
        execute at begin node={%
            % Hide the testproben spike in a style rather than
            % clutter up the main code.
            \begin{tikzpicture}[x=2.75pt,y=1.5pt, scale=0.625]
                \path [draw=probe color] plot [smooth] coordinates {(0,0) 
                (1,2) (2,10) (3,1) (4,3) (5,1) (6,4) (7,0)};
            \end{tikzpicture}}  
    },
    vorhesage/.style args={#1-#2}{
        shape=circle,
        draw=correct color,
        text=white,
        font=\bf\small,
        vorhesage #1-#2/.try,
        incorrect vorhesage #1-#2/.try,
        minimum size=0.625cm    
    },
    surrogat/.style={
        shape=regular polygon,
        regular polygon sides=3,
        minimum height=1cm,
        draw
    }
}


\tikzset{
    % The styles applied to specified testproben and (correct) vorhesage
    testproben/.style args={#1-#2}{
        probe #1-#2/.style={
            fill=testproben
        },
        vorhesage #1-#2/.style={
            fill=correct color,
            execute at begin node=\def\vmark{\ding{51}}% A tick
        }
    },
    % The styles applied to specified testproben and (incorrect) vorhesage
    testproben */.style args={#1-#2}{
        probe #1-#2/.style={
            fill=testproben
        },
        incorrect vorhesage #1-#2/.style={
            fill=incorrect color,
            draw=correct color,
            very thick,
            execute at begin node=\def\vmark{\ding{55}}% A cross
        }
    },
    Daten A/.style={
        A/.try,
        probe color=Klasse A,
    },
    Daten B/.style={
        B/.try,
        probe color=Klasse B,
        shift={(5,0)}
    },
    Vorhesage A/.style={
        A/.try,
        correct color=Klasse A,
        incorrect color=Klasse B,
    },
    Vorhesage B/.style={
        B/.try,
        correct color=Klasse B,
        incorrect color=Klasse A,
        shift={(5,0)}
    },      
    iteration 1/.style={
        % Define the testproben (and vorhesagen) for iteration 1
        A/.style={
            testproben={1-4}, % testproben row 1, column 4
            testproben={2-3}, testproben={2-5},
            testproben *={3-1}, testproben={3-2},
        },
        B/.style={
            testproben={1-2}, testproben={1-3},
            testproben *={2-1},
            testproben={3-4}
        },
    },
    iteration 2/.style={
        A/.style={
            testproben={1-1}, testproben={1-4},testproben={1-5},
            testproben={2-2},
            testproben={3-5}
        },
        B/.style={
            testproben={1-2}, testproben={2-1},
            testproben={3-1}, testproben={3-3}
        }
    },
    iteration 3/.style={
        A/.style={
            testproben={1-5}, testproben={1-4},
            testproben={2-2}, testproben={2-2},
            testproben *={3-1}
        },
        B/.style={
            testproben={1-2}, 
            testproben={2-1},
            testproben={3-3}, testproben={3-4}
        },
    }
}

\begin{document}

\begin{tikzpicture}[x=0.75cm, y=0.75cm, >=stealth]

\foreach \itr in {1,2,3}{
    % Install the A and B styles for this iteration.
    % The A and B styles define the testproben for Klasse A
    % and Kasse B.
    \tikzset{iteration \itr/.try}
    \foreach \g in {1,2,3}{
        \ifcase\g
        \or
            % Draw the probes
            \foreach \K/\I/\J in {A/3/5, B/3/4}{%
                % Install the Daten \K style.
                % For Daten Klasse A this sets the probe color to blue
                % For Daten Klasse B this sets the probe color to red
                % and shifts everything along.
                % In both cases the relevant style (A or B) is `executed'
                % defining which probes are testproben.
                \tikzset{Daten \K/.try}
                \foreach \i in {1, ..., \I}{%
                    \foreach \j in {1, ..., \J}{%
                        \node (probe \itr-\K-\i-\j) at (\j, -\itr*3.5-\i) 
                           [probe=\i-\j] {};
                    }
                }
                % Define a node that fits around all the nodes for this
                % particular Daten Klasse.
                \node [tight fit,fit=(probe \itr-\K-1-1) 
                (probe \itr-\K-\I-\J)] 
                    (iteration \itr\space daten \K){};
            }
        \or
            % Now draw the Surrogats (Surrogaten?)
            \foreach \I in {1,2,3}{
                \tikzset{shift=(probe \itr-B-1-4.east)}
                \node (surrogat \itr-\I) at (1.125,1-\I) [surrogat] {};
                \draw [ultra thick, ->] 
                    (surrogat \itr-\I.west) ++(-0.625,0) -- ++(0.5,0);
                \draw [ultra thick, ->] 
                    (surrogat \itr-\I.east) ++(0.125,0) -- ++(0.5,0);
            }
        \or
            % Finally the Forcasts
            %
            % Shift things along a but from the surrogats.
            \tikzset{shift={(surrogat \itr-1)}, shift=(0:0.5)}
            \foreach \K/\I/\J in {A/3/5, B/3/4}{
                % This is the same as for the Daten Klasse,
                % execept tis time the vorhesage proben are drawn.
                \tikzset{Vorhesage \K/.try}
                \foreach \i in {1, ..., \I}{
                    \foreach \j in {1, ..., \J}{
                        \node (vorhesage \itr-\K-\i-\j) at (\j, -\i+1) 
                        [vorhesage=\i-\j] {\vmark};
                    }
                },
                % Draw a node around each set of vorhesage nodes.
                \node [tight fit, 
                   fit=(vorhesage \itr-\K-1-1) (vorhesage \itr-\K-\I-\J)] 
                (iteration \itr\space vorhesage \K){};
            }               
        \fi%
    }
}

% Now add the labels and delimiters.

\foreach \itr in {1,2,3}{
    \node [tight fit, fit={(iteration \itr\space daten A)}, left 
    delimiter=\{, label={[xshift=-0.5cm]left:\itr. 
    Iteration}] {};
}
\foreach \K in {A, B}{

    \node [tight fit, fit={(iteration 1 daten \K)}, above 
    delimiter=\{,label={[yshift=0.5cm]90:Daten Klassen \K}] {};

    \node [tight fit, fit={(iteration 1 vorhesage \K)}, above 
        delimiter=\{,label={[yshift=0.5cm, align=center]90:{Vorhesage 
        \\Proben \K}}] {};
}

\node [fill=testproben, rounded corners=1ex, below=0.25cm, anchor=north west]  
(testprobe)
    at (probe 3-A-3-1.south east){Testprobe};

\draw [very thick, ->, rounded corners=1ex]
    (testprobe.west) -| (probe 3-A-3-1.south);

\node [below=0.25cm, anchor=north west]  
(trainingsprobe)
    at (probe 3-A-3-4.south east){Trainingsprobe};

\draw [very thick, ->, rounded corners=1ex]
    (trainingsprobe.west) -| (probe 3-A-3-4.south);

\node [below=1cm, anchor=north east]  
(surrogatsmodelle)
    at (surrogat 3-3.south west){$i=3\times k=3$ Surrogatsmodelle};

\draw [very thick, ->, rounded corners=1ex]
    (surrogatsmodelle.east) -| (surrogat 3-3.south);

\node [below=0.5cm, align=left, anchor=north west] (eingeordnet)
    at (vorhesage 3-A-3-1.south east){Testprobe aus Klasse \textcolor{Klasse 
    A}{A} wird \\als Klasse \textcolor{Klasse B}{B} eingeordnet};

\draw [very thick, ->, rounded corners=1ex]
    (eingeordnet.west) -| (vorhesage 3-A-3-1.south);

\end{tikzpicture}

\end{document}

enter image description here