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.

I'm trying to generate a normalized eigenvalue spectrum like this one:

enter image description here

In the above example, the normalized eigenvalues are like the following:

0.8332
0.0433
0.0310
0.0152
0.0061
0.0047
0.0035
0.0022
0.0018
0.0014
0.0013
0.0011
0.0010
0.0008
0.0007
... 
and more small ones

The accumulated eigenvalues are:

0.8332
0.8765
0.9074
0.9227
0.9287
0.9334
0.9369
0.9392
0.9410
0.9424
0.9437
0.9448
0.9458
0.9467
0.9474
... and more
1

The above spectra is generated by the following (with accumulated eigenvalues):

\begin{tikzpicture}[scale=10]

    \draw[ xstep=.1, ystep=0.1]  (0,0) grid (1,0.1);

    \fill [red!50]               ( 0,0.008)      rectangle ( 0.8332,0.1);
    \fill [purple!60]            ( 0.8332,0.008) rectangle ( 0.8765,0.1);
    \fill [blue!70]              ( 0.8765,0.008) rectangle ( 0.9074,0.1);
    \fill [green]             ( 0.9074,0.008) rectangle ( 0.9227,0.1);
    \fill [orange]            ( 0.9227,0.008) rectangle ( 0.9287,0.1);
    \fill [purple!!50!!red]   ( 0.9287,0.008) rectangle ( 0.9334,0.1);
    \fill [yellow]            ( 0.9334,0.008) rectangle ( 0.9369,0.1);
    \fill [purple!!50!!green] ( 0.9369,0.008) rectangle ( 0.9392,0.1);
    \fill [lime]              ( 0.9392,0.008) rectangle ( 0.9410,0.1);
    \fill [teal]              ( 0.9410,0.008) rectangle ( 0.9424,0.1);
    \fill [teal!!20!!white]   ( 0.9424,0.008) rectangle ( 0.9437, 0.1);

    %\fill [gray]              ( 0.9437,0.008) rectangle ( 1, 0.1);

    \fill  [teal!!20!!white]   (0.9437,0.008) rectangle ( 0.9448,0.1);
    \fill  [gray]              (0.9448,0.008) rectangle ( 0.9458,0.1);
    \fill  [red]               (0.9458,0.008) rectangle ( 0.9467,0.1);
    \fill  [purple]            (0.9467,0.008) rectangle ( 0.9474,0.1);
    \fill  [blue]              (0.9474,0.008) rectangle ( 0.9480,0.1);
    % and more ...        

    \draw[|<->|] (0,0.032) -- node [left, fill=red!50] {0.84} (0.5,0.032)  -- (0.8332,0.032);
    \draw[|<->|] (0,0.055) -- node [fill=red!50] {0.88} (0.7, 0.055) -- (0.8765,0.055);
    \draw[|<->|] (0,0.078) -- node [right, fill=red!50] {0.91} (0.9, 0.078) -- (0.9074,0.078);

\end{tikzpicture}

In the above I just choose colours manually, and copy-paste colours in visual block in Vim.

  1. Here I'm wondering, how can I assign colours automatically? And then maybe I can draw the above in a for loop.

  2. Is there a better way than drawing rectangles ?

EDIT. July 8 2013

The following colors seem OK for generating eigenvalue spectrum. Welcome suggestions and modifications on the color list.

\begin{filecontents}{eigenvaluesA}
% 20 value-color pairs
Values Colors
0.0500    red!50
0.1000    purple!60
0.1500    blue!70
0.2000    green
0.2500    orange
0.3000    purple!!50!!red
0.3500    yellow
0.4000    purple!!50!!green
0.4500    lime
0.5000    teal
0.5500    blue
0.6000    purple!!50!!red
0.6500    yellow
0.7000    purple!!50!!green
0.7500    lime
0.8000    teal
0.8500    yellow!!20!!white
0.9000    blue
0.9500    red
1.0000    green
\end{filecontents}

enter image description here

share|improve this question

1 Answer 1

up vote 10 down vote accepted

Starting from an input file containing values and colors, by means of a \drawspectrum macro it is possible to draw the spectrum completely automatic. There is an automatic tool also to deploy the arrowed paths with the values selected (it is automatic because it allows to both draw the lines towards the desired value and each line is vertically aligned) and the aspect can be customized with specific keys.

The code:

\documentclass[png,border=10pt,tikz]{standalone}
\usepackage{filecontents}
\usepackage{tikz,pgfplotstable}
\usetikzlibrary{calc}

\pgfkeys{/tikz/.cd,
  value fill color/.get=\valfillcol, % the background color for values
  value fill color=red!50,
  value precision/.get=\valprintprec, % the precision of the values
  value precision=2,
  diagram height/.get=\diagramheight, % the height of the diagram
  diagram height=1,
  }

% The file should containt values and colors
\begin{filecontents}{eigenvalues.dat}
Values Colors
0.8332 red!50
0.8765 purple!60
0.9 blue!70
0.9227 green
0.9287 orange
0.9334 purple!!50!!red
0.9369 yellow
0.9392 purple!!50!!green
0.9410 lime
0.9424 teal
0.9437 teal!!20!!white
0.9448 gray
0.9458 red
0.9467 purple
0.9474 blue
1      black
\end{filecontents}

% Argument: file
\newcommand{\drawspectrum}[1]{
\pgfplotstableread{#1}{\eigenvaltab}

\pgfplotstablegetrowsof{\eigenvaltab} % Number of rows
\pgfmathsetmacro{\numrows}{\pgfplotsretval-1}

\draw (0,0) -- (10,0);

\foreach \x[evaluate=\x as \printx using \x*0.1] in {0,1,...,10}{
\pgfkeys{/pgf/number format/.cd,fixed,precision=2}
\draw (\x,0.08) -- (\x,0) node[below,font=\footnotesize]{\pgfmathprintnumber{\printx}};
}

\foreach \x[count=\xi,evaluate=\x as \prevx using int(\x-1)] in {0,1,...,\numrows}{
 % value
 \pgfplotstablegetelem{\x}{[index]0}\of\eigenvaltab
 \pgfmathsetmacro\newval{\pgfplotsretval*10}
 \ifnum\xi=1
   \pgfmathsetmacro\initval{0}
 \else
   % prev value
   \pgfplotstablegetelem{\prevx}{[index]0}\of\eigenvaltab
   \pgfmathsetmacro\initval{\pgfplotsretval*10}
 \fi

 % color
 \pgfplotstablegetelem{\x}{[index]1}\of\eigenvaltab
 \def\rowcol{\pgfplotsretval}
 \fill [\rowcol] ( \initval,0.08) rectangle ( \newval,\diagramheight);
}
}

\newcommand{\drawspectrumvalue}[3]{
\draw[|<->|] (0,#2) -- node[fill=\valfillcol,
  inner sep=2pt,
  rounded corners] {#3} (#1,#2);
}

\newcommand{\drawspectrumvaluelist}[2][font=\scriptsize]{
  \foreach \value [count=\xi] in {#2}  {\global\let\maxnumvalues\xi}

  \pgfmathsetmacro\valuesdistance{\diagramheight/(\maxnumvalues+0.5)}
  \begin{scope}[#1]
  \foreach \x[count=\xi] in {#2}{
    \pgfmathsetmacro\xval{\x*10}
    \pgfkeys{/pgf/number format/.cd,fixed,precision=\valprintprec,zerofill}
    \drawspectrumvalue{\xval}{\xi*\valuesdistance}{\pgfmathprintnumber{\x}}
  }
  \end{scope}

}

\begin{document}

\begin{tikzpicture}
\drawspectrum{eigenvalues.dat}

\drawspectrumvaluelist{0.8322,0.8765,0.90}
\end{tikzpicture}

\begin{tikzpicture}[diagram height=2,value precision=3,value fill color=red!20]
\drawspectrum{eigenvalues.dat}

\drawspectrumvaluelist[font=\footnotesize]{0.8322,0.8765,0.90,0.9227,0.9287}
\end{tikzpicture}

\end{document}

The first image represents the picture provided by the OP:

enter image description here

A customized example:

enter image description here

share|improve this answer
    
Thank you! Then maybe we can make a \drawspectra{list-of-eig-values}{list-of-color-values}{colormap-name}. And we will just need to tune the list-of-color-values to make a proper spectrum! –  Hongying Jun 28 '13 at 11:12
    
You're welcome :). The problem that I see in that kind of macro is that, although it could be very useful at the user-side, it's very difficult to be implemented. In the sense that it brings some issues: we have to merge two different lists so this process has to be consistent (same number of elements, be sure of access the right value-color pair), for high number of values this is not efficient. Later I will improve the current version and I try to think on that macro, but without any guarantee. –  Claudio Fiandrino Jun 28 '13 at 11:44
    
How about we give user the freedom to choose colours for the big eigenvalues, and make it pick random colours for small ones? (Or maybe we can provide two or three static lists of colours, and always use one of them for small eigenvalues ? I'll think about a list of colours! :) ) –  Hongying Jun 28 '13 at 19:48
    
Of course could be possible, but if you derive your values via simulation, I think the best is the solution already here. You just have to create a file with the pair value-color and automatically it will be dispayed. –  Claudio Fiandrino Jun 29 '13 at 11:47
    
By the way, do you know how to make it shows up "0.90" rather than "0.9", when there is a "0" at the end? –  Hongying Jul 4 '13 at 14:02

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.