# Any package for matrix diagram?

Do you know if there is any LaTeX package available to create charts like these?

(Source)

-
Looks like a job for tikz and the matrix library – Ludovic C. Oct 1 '13 at 8:10
Check this answer, it's looks similar to what you want. – m0nhawk Oct 1 '13 at 11:26
An good go package should do that for you:-) – Marc van Dongen Oct 1 '13 at 12:47
I revised my answer to use a tabular for the "MUST, SHOULD, MAYBE" label, since it looks cleaner and has better alignment. – Steven B. Segletes Oct 1 '13 at 13:47

With a little work, I could eliminate the stray rule points on the right and bottom of the graph, I think. But they may not bother you, as is.

EDIT: Since the answer was accepted, I thought I out to expand a little on the explanation. My goal was to both to make the output look in the style of what the OP requested, and to make the user's input as easy as possible.

I chose stackengine to do the heavy lifting, since this problem requires many different features of that package. I created the unit grid by stacking two \rules on each other. I created the colored dots by \stackinseting a colored bullet over top of the unit grid. I created the final grid by stacking the content under the 90-degree rotated name labels along the top.

When all was said and done in the preamble, the mode of input is extremely efficient. The grid itself took far less typing than the "Must, Should, Maybe" label in the upper corner. For example, the actual grid was created with

\Shortstack{%
\hname{entry}\R\B\G\X\\
\hname{lobby}\G\B\X\R\\
\hname{reception}\X\R\B\G\\
}%


where the \X denotes an empty grid cell and the \R, \B, and \G macros giving red, blue and green bullets, respectively. Here is the solution:

\documentclass{article}
\usepackage{fixltx2e}
\usepackage[usestackEOL]{stackengine}[2013-09-25]
\usepackage{xcolor, graphicx}
\newsavebox{\Rbox}\newsavebox{\Bbox}\newsavebox{\Gbox}\newsavebox{\Xbox}
\def\thk{.5pt}                     % RULE THICKNESS
\def\gsize{.4cm}                 % GRID SIZE
\def\hnamesize{1.8cm}       % WIDTH OF HORIZONTAL-NAME BLOCK
\def\grid{\stackinset{c}{}{c}{}{\rule{\thk}{\gsize}}{\rule{\gsize}{\thk}}}
\sbox\Rbox{\stackinset{c}{.2pt}{c}{-.8pt}{\scalebox{2}{\color{red}$\bullet$}}{\grid}}
\sbox\Bbox{\stackinset{c}{.2pt}{c}{-.8pt}{\scalebox{1.75}{\color{blue}$\bullet$}}{\grid}}
\sbox\Gbox{\stackinset{c}{.2pt}{c}{-.8pt}{\scalebox{1.5}{\color{green}$\bullet$}}{\grid}}
\sbox\Xbox{\grid}
\def\R{\usebox{\Rbox}}\def\B{\usebox{\Bbox}}
\def\G{\usebox{\Gbox}}\def\X{\usebox{\Xbox}}
\newcommand*\hname[2][P]{\makebox[\hnamesize][l]{\tiny\sffamily%
\raisebox{-.3\ht\strutbox}{\uppercase{#2}}%
\if x#1\else\rule{\hnamesize-\widthof{\uppercase{#2}}}{\thk}\fi}}
\newcommand*\vname[1]{%
\makebox[\gsize]{\rotatebox{90}{\tiny\sffamily\uppercase{#1}}}%
}
\setstackgap{S}{0pt}
\def\stackalignment{l}
\begin{document}
\stackinset{l}{-2.5ex}{t}{}{%
\renewcommand\arraystretch{0.7}
\begin{tabular}{c@{}l}
\abovebaseline[-2pt]{\scalebox{2}{\color{red}$\bullet$}} &
\color{red}\footnotesize\sffamily MUST\\
\abovebaseline[-2pt]{\scalebox{1.75}{\color{blue}$\bullet$}} &
\color{blue}\scriptsize\sffamily SHOULD\\
\abovebaseline[-2pt]{\scalebox{1.5}{\color{green}$\bullet$}} &
\color{green}\tiny\sffamily MAYBE\\
\end{tabular}
}{%
\stackunder{%
}{%
\Shortstack{%
\hname{entry}\R\B\G\X\\
\hname{lobby}\G\B\X\R\\
\hname{reception}\X\R\B\G\\
}%
}%
}
\end{document}


-
great, thank you! – muffel Oct 1 '13 at 12:00
@muffel You're welcome. I should have mentioned that the rule thickness, grid size, and horizontal-name field-width are all easily changeable with the \defs near the top. Bullet sizes can be changed with the argument to the \scaleboxes, though additional l-r adjustments in the \stackinset might be necessary if you do. – Steven B. Segletes Oct 1 '13 at 12:11

Looks like a job for pgfplots using a scatter plot with symbolic coordinates and a grid. Here is what I came up with so far:

\documentclass{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
legend style={
legend pos=outer north east,
},
xticklabel pos=right,
y dir =reverse,
x tick label style={rotate=90},
grid=major,
width=5cm,
height=5cm
]
ytick = data,
\addplot[only marks,red,mark size = 5pt] coordinates {
(Lobby,Entry)
(Reception,Entry)
};
};
(Entry,Entry)
(Lobby,Reception)
};
\end{axis}
\end{tikzpicture}
\end{document}


-

This MWE uses Asymptote. The matrix is assumed to be symmetric. Two kind of commands are used to fill the columns of the matrix: both used first parameter as the mark index (smlId, midId or bigId) and second as the column number, but while the first one uses a list of rows to mark, the other one uses a list of pairs of the form (<first row>, <count>).

For example, m.markCol(smlId,5,7,18); marks rows 7 and 18 in column 5 with the small marker, and m.markCol(bigId,1,(2,5),(8,2)); marks sequence of 5 rows starting from 2 and 2 rows starting from 8 in column 1 with the big marker.

% mx.tex :
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\begin{asy}
settings.outformat="pdf";
unitsize(1bp);

import fontsize;
defaultpen(fontsize(8pt));

pen textPen=rgb(0.4,0.3,0.3);
pen linePen=heavycyan+1bp;

real smlCircR=3;
real midCircR=4;
real bigCircR=5;

guide[] circMark={
scale(smlCircR)*unitcircle,
scale(midCircR)*unitcircle,
scale(bigCircR)*unitcircle,
};

pen[] circMarkPen={
rgb(0,0.996,0.329)+fontsize(8pt)
,rgb(0,0.702,1)+fontsize(10pt)
,red+fontsize(12pt)
};

string[] name={
"ENTRY",
"LOBBY",
"RECEPTION",
"SECURITY",
"LOUNGE",
"RESTROOMS",
"EMPLOYEE LOUNGE",
"CAF\'E",
"CLASSROOMS",
"REC. STUDIO",
"WORKSHOP",
"RECITAL HALL",
"GRAND THEATRE",
"DRESSING ROOM",
"REHEARSEL",
"MUSICIAN LOUNGE",
"MECH. ROOM",
"CONTROL ROOM",
"STORAGE",
};

real dr=12;
real dc=dr;
real r,c;
int n=name.length;
c=0;
Label L;

real maxw=0;
real w;
pair mx;

for(int i=0;i<n;++i){
r=dr*(n-i);
L=Label("\sffamily "+name[i],(0,0),E);
mx=max(object(L).g);
if(mx.x>maxw)maxw=mx.x;
}

real xshift=maxw+bigCircR;
real yshift=2bigCircR;

for(int i=0;i<n;++i){
r=dr*(n-i);
c=dc*i;
draw((0,(i+1)*dr)--(xshift+(n-1)*dc,(i+1)*dr),linePen);
draw((xshift+i*dc,yshift+n*dr)--(xshift+i*dc,dr),linePen);
}

layer();
c=0;
for(int i=0;i<n;++i){
r=dr*(n-i);
L=Label("\sffamily "+name[i],(0,0));
label(L,(c,r),E,textPen,UnFill(2));
}

r=n*dr;
for(int i=0;i<n;++i){
c=xshift+dc*i;
L=rotate(90)*Label("\sffamily "+name[i],(0,0));
label(L,(c,r+yshift),N,textPen);
}

void markCol(int circId, int col ... int[] seq){
for(int i=0;i<seq.length;++i){
}
}

void markCol(int circId, int col ... pair[] seq){ // mark sequences
for(int i=0;i<seq.length;++i){
for(int j=0;j<seq[i].y;++j){
}
}
}

void drawMarks(){
int id;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
if(id>0 && id<4){
fill(shift(xshift+j*dc,(n-i)*dr)*circMark[id-1],circMarkPen[id-1]);
fill(shift(xshift+i*dc,(n-j)*dr)*circMark[id-1],circMarkPen[id-1]);
}
}
}
}

void operator init(int n){
}
}

int smlId=1;
int midId=2;
int bigId=3;

m.markCol(smlId,2,7);
m.markCol(smlId,3,5);
m.markCol(smlId,5,7,18);
m.markCol(smlId,6,8);
m.markCol(smlId,7,9);
m.markCol(smlId,8,n-2);
m.markCol(smlId,9,n-2);
m.markCol(smlId,10,(n-7,3));

m.markCol(midId,0,n-9,n-10);
m.markCol(midId,1,7,13,14);
m.markCol(midId,2,3,5,6,8,9);
m.markCol(midId,4,5,8);

m.markCol(bigId,0,(1,6),(8,2));
m.markCol(bigId,1,(2,5),(8,2));
m.markCol(bigId,2,4,n-1);
m.markCol(bigId,3,4,6);
m.markCol(bigId,5,9,14);
m.markCol(bigId,6,(9,3),(13,3));
m.markCol(bigId,9,14);
m.markCol(bigId,10,(11,3));
m.markCol(bigId,11,16);
m.markCol(bigId,13,16,17,n-1);
m.markCol(bigId,14,(15,6));
m.markCol(bigId,16,n-4);
m.markCol(bigId,17,n-1);
m.markCol(bigId,18,n-1);

m.drawMarks();

fill(shift((bigCircR,(n+5)*dr))*circMark[bigId-1],circMarkPen[bigId-1]);
fill(shift((bigCircR,(n+4)*dr))*circMark[midId-1],circMarkPen[midId-1]);
fill(shift((bigCircR,(n+3)*dr))*circMark[smlId-1],circMarkPen[smlId-1]);

label("\sffamily MUST",  (2bigCircR,(n+5)*dr),E,circMarkPen[bigId-1]);
label("\sffamily SHOULD",(2bigCircR,(n+4)*dr),E,circMarkPen[midId-1]);
label("\sffamily MAYBE", (2bigCircR,(n+3)*dr),E,circMarkPen[smlId-1]);

\end{asy}
\end{figure}
\end{document}
% Prosess it with
%
% pdflatex mx.tex
% asy mx-*.asy
% pdflatex mx.tex

-