Matrix with labels nested in braces

In today's I have too much free time episode we will attack a question posted without a MWE. Absence of a MWE gives us the right to go as esoteric as possible hence here is one Tweak this, tweak that possibility.

\documentclass[tikz]{standalone}
\usetikzlibrary{matrix,trees}

\begin{document}
\begin{tikzpicture}[level distance=7mm,
level 1/.style={sibling distance=8mm},
level 2/.style={sibling distance=4mm},
]
\matrix (m) [mymatrix/.style={execute at empty cell=
\ifnum\pgfmatrixcurrentrow<5
\ifnum\pgfmatrixcurrentcolumn>4
\node\bgroup$0$\egroup;\fi
\else
\ifnum\pgfmatrixcurrentcolumn<5
\node\bgroup$0$\egroup;\fi
\fi
},mymatrix,
right delimiter={]},left delimiter={[}]{
&&&&&&&\\
&&&&&&&\\
&&&&&&&\\
&&&&&&&\\
&&&&&&&\\
&&&&&&&\\
&&&&&&&\\
&&&&&&&\\
};
\begin{scope}[edge from parent path=
{(\tikzparentnode.south) .. controls +(0,-0.2) and +(0,0.2)
.. (\tikzchildnode.north)}]
\node at ([yshift=1.5cm]m.67) {$A$}
child {node {$1$}
child {node {S}}
child {node {I}}}
child {node {$2$}
child {node {S}}
child {node {I}}
};
\node at ([yshift=1.5cm]m.113) {$B$}
child {node {$1$}
child {node {S}}
child {node {I}}}
child {node {$2$}
child {node {S}}
child {node {I}}
};
\end{scope}

\begin{scope}[edge from parent path=
{(\tikzparentnode.east) .. controls +(0.2,0) and +(-0.2,0)
.. (\tikzchildnode.west)},level distance=6mm,
level 1/.style={sibling distance=9.2mm},
level 2/.style={sibling distance=4.5mm}]
\node at ([xshift=-1.6cm]m.152) {$A$}[grow=right]
child {node {$1$}
child {node {S}}
child {node {I}}}
child {node {$2$}
child {node {S}}
child {node {I}}
};
\node at ([xshift=-1.6cm]m.-152) {$B$}[grow=right]
child {node {$1$}
child {node {S}}
child {node {I}}}
child {node {$2$}
child {node {S}}
child {node {I}}
};
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here


Here's another option using the blkarray package for the matrix and \tikzmark for the braces (using decoration=brace):

\documentclass{article}
\usepackage{mathtools}
\usepackage{blkarray}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}

\newcommand{\tikzmark}[1]{%
  \tikz[overlay,remember picture,baseline] \node [anchor=base] (#1) {};}

% for horizontal braces
% \myhbrace{<mark>}{<mark>}{<label>}
\newcommand\myhbrace[3]{%
\draw[decorate,decoration={brace,raise=5pt}]   
  (#1.north) -- node[yshift=13pt] {#3} (#2.north);}

% for vertical braces
% \myvbrace{<mark>}{<mark>}{<label>}
\newcommand\myvbrace[3]{%
  \draw[decorate,decoration={brace,raise=6pt,mirror}] 
    ([yshift=3pt]#1.north east) -- node[xshift=-15pt] {#3} ([yshift=3pt]#2.south east);}

\begin{document}

 \[
\begin{blockarray}{ccccccccc}
& \tikzmark{a}S & I\tikzmark{b} & \tikzmark{c}S & I\tikzmark{d} & \tikzmark{e}S 
  & I\tikzmark{f} & \tikzmark{g}S & I\tikzmark{h} \\
\begin{block}{l[cccccccc]}
\\[-1.2ex]
\tikzmark{m}S &  & & & & 0 & 0& 0 & 0 \\[.3ex]
\tikzmark{n}I &  & & & & 0 & 0& 0 & 0 \\[.3ex]
\tikzmark{o}S &  & & & & 0 & 0& 0 & 0 \\[.3ex]
\tikzmark{p}I &  & & & & 0 & 0& 0 & 0 \\[.3ex]
\tikzmark{q}S & 0 & 0 & 0 & 0 & & & & \\[.3ex]
\tikzmark{r}I & 0 & 0 & 0 & 0 & & & & \\[.3ex]
\tikzmark{s}S & 0 & 0 & 0 & 0 & & & & \\[.3ex]
\tikzmark{t}I & 0 & 0 & 0 & 0 & & & & \\[1ex]
\end{block}
\end{blockarray}
\]

\begin{tikzpicture}[overlay,remember picture,baseline]
\myhbrace{a}{b}{$\tikzmark{i}1$}
\myhbrace{c}{d}{$2\tikzmark{j}$}
\myhbrace{e}{f}{$\tikzmark{k}1$}
\myhbrace{g}{h}{$2\tikzmark{l}$}
\myhbrace{i}{j}{$A$}
\myhbrace{k}{l}{$B$}

\myvbrace{m}{n}{$\tikzmark{u}1$}
\myvbrace{o}{p}{$\tikzmark{v}2$}
\myvbrace{q}{r}{$\tikzmark{w}1$}
\myvbrace{s}{t}{$\tikzmark{x}2$}
\myvbrace{u}{v}{$A$}
\myvbrace{w}{x}{$B$}

\node[yshift=15pt,font=\small] at (m|-k) {$i=$};
\node[yshift=2.5pt,font=\small] at (m|-k) {$j=$};
\node[yshift=4pt,font=\small] at (m|-a) {$k=$};
\end{tikzpicture}

\end{document}

enter image description here

The code has to be processed three times for the elements to stabilize.


Continuing on in percusse's tradition, here is a slight improvement on the version provided by Gonzalo Medina.

I have used the collcell package to automate the insertion of the appropriate \tikzmark into the matrix. This makes the matrix a bit more easier to read as it is not cluttered with all the numerous \tikzmarks required for this application to yield:

enter image description here

Notes:

  • I have added an optional first parameter to the \myhbrace and \myvbrace to allow one to specify the parameters for the \draw command.
  • Other than the above change, and the manual drawing of the matrix border (see Further Enhancements below), the calls to the two brace commands are one to one equivalent to Gonzalo's, with the name changed to something more meaningful (since they are automatically inserted).
  • Two new column types are defined here. The first column (and only the first) must use the F column type. This allows me to recognize when a new row is started. All others must use the C column type.
  • Unlike most of the other applications of \tikzmark, this actually requires three (not two) runs. First two to determine the locations, and the third to do the drawing.
  • I have used newtoggle from the etoolbox package as I prefer that syntax versus the \newif syntax. But if you don't want to include an additional package it should be pretty straightforward to adapt this to use \newif or some other conditional methods
  • Similarly, I used the xstring package for numerical comparrison, and again this could be done without this package if that was an issue.

Further Enhancements:

  • I am not happy about the fact that I had to manually draw the matrix border. It turns out that the matrix macros do not seem to allow the use of \newcolumntype. I only realized this when I was done with everything else, so was too far into it to not finish it!!

Code:

\documentclass{article}
\usepackage{mathtools}
\usepackage{blkarray}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.pathreplacing}

\usepackage{collcell}
\usepackage{etoolbox}
\usepackage{xstring}

% The "F" column type is to ONLY be used for the first column
\newcolumntype{F}{>{\collectcell\NewRowData}{c}<{\endcollectcell}}
\newcolumntype{C}{>{\collectcell\NewColumnData}{c}<{\endcollectcell}}

\newcounter{RowCount}
\newcounter{ColumnCount}
\newtoggle{DoneWithHeader}
\togglefalse{DoneWithHeader}
\newcommand{\DoneWithHeader}{\global\toggletrue{DoneWithHeader}}

\newcommand*{\NewColumnData}[1]{%
    \stepcounter{ColumnCount}%
    \iftoggle{DoneWithHeader}{}{%
        \tikzmark{Col \arabic{ColumnCount} Left}%
    }{}%
    #1%
    \iftoggle{DoneWithHeader}{}{%
        \tikzmark{Col \arabic{ColumnCount} Right}%
    }%
}%
\newcommand*{\NewRowData}[1]{%
    \IfEq{\arabic{ColumnCount}}{0}{}{\DoneWithHeader}%
    \setcounter{ColumnCount}{-1}% start a new row ==> at first column
    %
    \iftoggle{DoneWithHeader}{%
        \stepcounter{RowCount}%
        \tikzmark{Row \arabic{RowCount}}%
    }{}%
    \NewColumnData{#1}%
}%



\newcommand{\tikzmark}[1]{%
  \tikz[overlay,remember picture,baseline] \node [anchor=base] (#1) {};}

% for horizontal braces
% \myhbrace[<draw options>]{<mark>}{<mark>}{<label>}
\newcommand\myhbrace[4][]{%
\draw[decorate,decoration={brace,raise=5pt}, #1]   
  (#2.north) -- node[yshift=13pt] {#4} (#3.north);}

% for vertical braces
% \myvbrace[<draw options>]{<mark>}{<mark>}{<label>}
\newcommand\myvbrace[4][]{%
  \draw[decorate,decoration={brace,raise=6pt,mirror}, #1] 
    ([yshift=3pt]#2.north east) -- node[xshift=-15pt] {#4} ([yshift=3pt]#3.south east);}

\begin{document}

\[
\begin{array}{FCCCCCCCC}
    & S   & I & S & I & S & I & S & I \\
    S &   &   &   &   & 0 & 0 & 0 & 0 \\[.3ex]
    I &   &   &   &   & 0 & 0 & 0 & 0 \\[.3ex]
    S &   &   &   &   & 0 & 0 & 0 & 0 \\[.3ex]
    I &   &   &   &   & 0 & 0 & 0 & 0 \\[.3ex]
    S & 0 & 0 & 0 & 0 &   &   &   &   \\[.3ex]
    I & 0 & 0 & 0 & 0 &   &   &   &   \\[.3ex]
    S & 0 & 0 & 0 & 0 &   &   &   &   \\[.3ex]
    I & 0 & 0 & 0 & 0 &   &   &   &   \\[1ex]
\end{array}
\]

\begin{tikzpicture}[overlay,remember picture,baseline]
\myhbrace[violet, thick]{Col 1 Left}{Col 2 Right}{$\tikzmark{Col 1-2}1$}
\myhbrace[violet, thick]{Col 3 Left}{Col 4 Right}{$2\tikzmark{Col 3-4}$}
\myhbrace[violet, thick]{Col 5 Left}{Col 6 Right}{$\tikzmark{Col 5-7}1$}
\myhbrace[violet, thick]{Col 7 Left}{Col 8 Right}{$2\tikzmark{Col 7-8}$}
\myhbrace[orange, thick]{Col 1-2}{Col 3-4}{$A$}
\myhbrace[orange, thick]{Col 5-7}{Col 7-8}{$B$}

\myvbrace[red,  thick]{Row 1}{Row 2}{$\tikzmark{Row 1-2}1$}
\myvbrace[red,  thick]{Row 3}{Row 4}{$\tikzmark{Row 3-4}2$}
\myvbrace[red,  thick]{Row 5}{Row 6}{$\tikzmark{Row 5-6}1$}
\myvbrace[red,  thick]{Row 7}{Row 8}{$\tikzmark{Row 7-8}2$}
\myvbrace[blue, thick]{Row 1-2}{Row 3-4}{$A$}
\myvbrace[blue, thick]{Row 5-6}{Row 7-8}{$B$}

\node[yshift=15pt, font=\small] at (Row 1 |- Col 5-7)    {$i=$};
\node[yshift=2.5pt,font=\small] at (Row 1 |- Col 5-7)    {$j=$};
\node[yshift=4pt,  font=\small] at (Row 1 |- Col 1 Left) {$k=$};

% Draw the lines for the matrix
\newcommand*{\XShift}{0.3em}
\newcommand*{\YShift}{0.5ex}

\coordinate (topLeft) at (Col 1 Left);
\coordinate (botLeft) at (topLeft |- Row 8);

\coordinate (topRight) at (Col 8 Right);
\coordinate (botRight) at (topRight |- Row 8);

\draw [black, line width=1.2pt]% Left matrix line
    ([shift={(0.3*\XShift,-\YShift)}]topLeft) --
    ([shift={(-\XShift,-\YShift)}]topLeft)  |- ([shift={(-\XShift,-1.5*\YShift)}]botLeft) 
    -- ++(1.3*\XShift,0);

\draw [black, line width=1.2pt]% Right matrix line
    ([shift={(-0.3*\XShift,-\YShift)}]topRight) --
    ([shift={( \XShift,-\YShift)}]topRight) |- ([shift={( \XShift,-1.5*\YShift)}]botRight)
    -- ++(-1.3*\XShift,0);
\end{tikzpicture}
\end{document}

Tags:

Matrices