Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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

enter image description here

(Source)

share|improve this question
    
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
add comment

3 Answers

up vote 7 down vote accepted

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

share|improve this answer
    
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
add comment

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

share|improve this answer
add comment

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
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.