Any package for matrix diagram?

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,
    symbolic x coords = {Entry,Lobby,Reception,Administration,Security,Lounge},
    symbolic y coords = {Entry,Lobby,Reception,Administration,Security,Lounge},
    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)
};
\addlegendentry{Must}
\addplot[only marks,blue] coordinates {
    (Reception,Administration) 
    (Administration,Reception)
};
\addlegendentry{Should}
\addplot[only marks,green] coordinates {
    (Entry,Entry) 
    (Lobby,Reception)
};
\addlegendentry{Maybe}
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here


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\\
  \hname{administration}\R\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{%
    \hname[x]{}\vname{entry}\vname{lobby}\vname{reception}\vname{administration}
  }{%
    \Shortstack{%
               \hname{entry}\R\B\G\X\\
               \hname{lobby}\G\B\X\R\\
           \hname{reception}\X\R\B\G\\
      \hname{administration}\R\R\B\G%
    }%
  }%
}
\end{document}

enter image description here


enter image description here

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",
"ADMINISTRATION",
"SECURITY",
"LOUNGE",
"RESTROOMS",
"EMPLOYEE LOUNGE",
"GIFT SHOP",
"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);
}

struct Mask{
  int[][] mask;

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

  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){
        mask[(int)seq[i].x+j][col]=circId;
      }
    }
  }

  void drawMarks(){
    int id;
    for(int i=0;i<n;++i){
      for(int j=0;j<n;++j){
        id=mask[i][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){
    mask=array(n,array(n,0));
  }
}

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

Mask m=Mask(n);

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