What's the best way to produce a matrix with labels that are nested in braces, like this:

4 Answers
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}

- 157,807
-
4
-
+1 just for the unknown (at least for me)
execute at empty cell. – Claudio Fiandrino Oct 24 '12 at 06:29
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}

The code has to be processed three times for the elements to stabilize.
- 11,466
- 505,128
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:

Notes:
- I have added an optional first parameter to the
\myhbraceand\myvbraceto allow one to specify the parameters for the\drawcommand. - 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
Fcolumn type. This allows me to recognize when a new row is started. All others must use theCcolumn 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
newtogglefrom theetoolboxpackage as I prefer that syntax versus the\newifsyntax. But if you don't want to include an additional package it should be pretty straightforward to adapt this to use\newifor some other conditional methods - Similarly, I used the
xstringpackage 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}
- 223,288
-
Maybe put it inside a
\begin{bmatrix} ... \end{bmatrix}or\left[ \right]to draw the delimiters with a few\!here and there? – percusse Oct 24 '12 at 10:07 -
@percusse: It seems that the
matrixenvironment do not allow for the use of\newcolumntype. I also did try the\left[ \right]but that required me to tweak the spacing in between the columns as it would only be applied to the sub-matrix. – Peter Grill Oct 24 '12 at 19:00
Here is a way to construct that matrix with {NiceMatrix} of nicematrix.
\documentclass{article}
\usepackage{nicematrix}
\begin{document}
\setcounter{MaxMatrixCols}{12}
\renewcommand{\arraystretch}{1.2}
$\begin{NiceMatrix}
& & &\Block{1-4}{A}&&&&\Block{1-4}{B}\
& & &\Block{1-2}{1}&&\Block{1-2}{2}&&\Block{1-2}{1}&&\Block{1-2}{2}\
& & &S&I&S&I&S&I&S&I\
\Block{4-1}{A}
&\Block{2-1}{1}&S& & & & &0&0&0&0\
& &I& & & & &0&0&0&0\
&\Block{2-1}{2}&S& & & & &0&0&0&0\
& &I& & & & &0&0&0&0\
\Block{4-1}{B}
&\Block{2-1}{1}&S&0&0&0&0\
& &I&0&0&0&0\
&\Block{2-1}{2}&S&0&0&0&0\
& &I&0&0&0&0\
\CodeAfter
\SubMatrix[{4-4}{11-11}]
\OverBrace{2-4}{3-7}{}[shorten]
\OverBrace{2-8}{3-11}{}[shorten]
\OverBrace{3-4}{3-5}{}[shorten]
\OverBrace{3-6}{3-7}{}[shorten]
\OverBrace{3-8}{3-9}{}[shorten]
\OverBrace{3-10}{3-11}{}[shorten]
\SubMatrix{{}{4-2}{7-2}{.}
\SubMatrix{{}{8-2}{11-2}{.}
\SubMatrix{{}{4-3}{5-3}{.}[extra-height=-3pt]
\SubMatrix{{}{6-3}{7-3}{.}[extra-height=-3pt]
\SubMatrix{{}{8-3}{9-3}{.}[extra-height=-3pt]
\SubMatrix{{}{10-3}{11-3}{.}[extra-height=-3pt]
\end{NiceMatrix}$
\end{document}
You need several compilations.
- 40,250

\documentclass{article}to\end{document}with bare essentials, say with matrix typed in etc. is sufficient. We don't ask for much. You can also check for other questions for examples. – percusse Oct 24 '12 at 19:36