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 have a dataset which consists of repeating events over time. Each event takes an arbitrary amount of time. I could plot this using gnuplot but am unable to produce correct keys because of the hackish nature of script. I had to manually draw legends. The plot looks like this: timeline via gnuplot

Could I do something like this via TikZ or some other graphing tool?

My dataset looks as follows:

running 20
stage-out 47
running 34
stage-in 3
running 24
stage-out 39
...

As shown above, the file is a two-column text where the first column represents event name and the second column the time interval for that event.

share|improve this question
    
What kind of data structure do you have? Can you include a small sample of it via filecontents package? See this one as an example : tex.stackexchange.com/questions/82249/… –  percusse Nov 11 '12 at 1:45
    
Question edited. Thanks! –  Ketan Nov 11 '12 at 1:50

1 Answer 1

up vote 18 down vote accepted

After all my failed attempts (deleted) I got one version to work.

The problem was, that inside of the axis environment the loop of \DTLforeach didn't expand the macros at the proper moment, but after the loop ended. This led to the result that only one (i.e. the last) box was drawn.

This solution circumvents this as it assembles all the TikZ commands before (\eappto) but \draw or \fill must not be expanded which is the reason it is preceded by \noexpand.

Solution 1

This solution uses pgfplots only for the axes, the boxes are drawn by TikZ.

Code

\documentclass{article}
\usepackage[separator={{ }}]{datatool}% loads etoolbox
\usepackage{pgfplots}
\def\maximum{0}
\def\whattodraw{}

\begin{filecontents}{dataset.dat}
running 20
stage-out 47
running 34
stage-in 3
running 24
stage-out 39
\end{filecontents}

\begin{filecontents}{datasetcolor.dat}
stage-in red!75
stage-out green
running orange
\end{filecontents}

\DTLloaddb[noheader,keys={name,value},headers={name,value}]{dataset}{dataset.dat}
\DTLloaddb[noheader,keys={namec,color},headers={namec,color}]{datasetcolor}{datasetcolor.dat}

\DTLforeach*{datasetcolor}{\name=namec,\tikzColor=color}{
        \tikzset{DSCOLOR\name/.estyle={fill=\tikzColor}}
}

\DTLforeach{dataset}{\name=name,\val=value}{
    \DTLappendtorow{cumval}{\maximum}
    \pgfmathsetmacro{\maximum}{\maximum+\val}
}

\DTLforeach*{dataset}{\nameb=name,\valb=value,\cumval=cumval}{%
    \eappto\whattodraw{\noexpand\fill [DSCOLOR\nameb] (axis cs:\cumval,0.5) rectangle %
%       node[rotate=90,text width=2cm,align=center] {\nameb} %
        ++ (axis cs:\valb,1);%
    }
}
\begin{document}
\begin{tabular}{cl}
\DTLforeach*{datasetcolor}{\name=namec,\tikzColor=color}{
        \tikz\fill[DSCOLOR\name] (0,0) rectangle (2em,1.3ex); & \name \\
}
\end{tabular}

\begin{tikzpicture}
\begin{axis}[
    xmin=0,
    xmax=\maximum,
    ymin=0,
    ymax=2,
    axis y line=none,
    axis x line=bottom,
    height=5cm,
    legend columns=-1,
    width=\textwidth,
    xlabel={$t/{\textrm s}\quad (t_{\max} = \maximum)$}
]
\whattodraw
\end{axis}
\end{tikzpicture}
\end{document}

Output

enter image description here

Solution 2

This solution uses the xbar stacked style from pgfplots. There are no calculations needed, this is all done by pgfplots (thanks to stack dir=plus we don't even need to culuminate the entries).

Sadly, the scatter classes and the legend have yet to be built manually.

Code

\documentclass{article}
\usepackage[separator={{ }}]{datatool}% loads etoolbox
\usepackage{pgfplots}
\def\whattodraw{}

\begin{filecontents}{dataset.dat}
running 20
stage-out 47
running 34
stage-in 3
running 24
stage-out 39
\end{filecontents}

\begin{filecontents}{datasetcolor.dat}
stage-in red!75
stage-out green
running orange
\end{filecontents}

\DTLloaddb[noheader,keys={name,value},headers={name,value}]{dataset}{dataset.dat}
\DTLloaddb[noheader,keys={name,color},headers={name,color}]{datasetcolor}{datasetcolor.dat}

\DTLforeach{datasetcolor}{\name=name,\tikzColor=color}{
    \tikzset{DSCOLOR\name/.estyle={fill=\tikzColor}}
}

\DTLforeach*{dataset}{\namea=name,\vala=value}{%
    \eappto\whattodraw{%
        \noexpand\addplot[
            scatter,
            DSCOLOR\namea,
            no marks,
            draw=none,
            scatter src=explicit symbolic
        ] coordinates {(\vala,0) [\namea]};
    }
}

\begin{document}
\ref{legendhere}

\begin{tikzpicture}
\begin{axis}[
    xmin=0,
    axis y line=none,
    axis x line=bottom,
    xbar stacked,
    stack dir=plus,
    height=5cm,
    legend columns=-1,
    width=\textwidth,
    legend to name={legendhere},
    scatter/classes={
        stage-in={red!75},%
        running={orange},%
        stage-out={green}}
]
\whattodraw
\legend{stage-in,running,stage-out}
\end{axis}
\end{tikzpicture}
\end{document}

Output

enter image description here

Solution without pgfplots

Code

\documentclass{article}
\usepackage[separator={{ }}]{datatool}
\usepackage{pgfplots}
\def\maximum{0}

\newlength{\barHeight}\newlength{\barWidth}\newlength{\currentX}\newlength{\nextX}
\setlength{\barHeight}{2cm}
\setlength{\barWidth}{10cm}
\setlength{\currentX}{0cm}

\begin{filecontents}{dataset.dat}
running 20
stage-out 47
running 34
stage-in 3
running 24
stage-out 39
\end{filecontents}
\begin{filecontents}{datasetcolor.dat}
stage-in red!75
stage-out green
running orange
\end{filecontents}

\DTLloaddb[noheader,keys={name,value},headers={name,value}]{dataset}{dataset.dat}
\DTLloaddb[noheader,keys={namec,color},headers={namec,color}]{datasetcolor}{datasetcolor.dat}

\DTLforeach*{datasetcolor}{\name=namec,\tikzColor=color}{
    \tikzset{DSCOLOR\name/.estyle={fill=\tikzColor}}
}
\DTLforeach{dataset}{\name=name,\val=value}{
    \DTLappendtorow{cumval}{\maximum}
    \pgfmathsetmacro{\maximum}{\maximum+\val}
}

\pgfdeclarelayer{background}
\pgfdeclarelayer{main}
\pgfsetlayers{background,main}
\begin{document}
\begin{tikzpicture}
\DTLforeach*{dataset}{\name=name,\val=value}{
    \pgfmathsetlength{\nextX}{\val/\maximum*\the\barWidth}
    \begin{pgfonlayer}{background}
        \fill [DSCOLOR\name] (\the\currentX,0) rectangle ++ (\the\nextX,\the\barHeight);
    \end{pgfonlayer}
    \draw[|-|,shorten >=-.5\pgflinewidth,shorten <=-.5\pgflinewidth] (\the\currentX,.5*\the\barHeight) -- node [below] {\val} ++ (\the\nextX,0) ;
    \pgfmathsetlength{\currentX}{\currentX+\nextX}
}
\end{tikzpicture}
\end{document}

Output

enter image description here

share|improve this answer
    
Fantastic! Thanks much! I'll go ahead and accept it right away as this is exactly what I wanted! –  Ketan Nov 11 '12 at 20:59
    
@ketan You're welcome. If you only have three kinds of events, you can easily do the classes' definition manually (and the legend, too). For the magnified part I recommend the spy TikZ-library. –  Qrrbrbirlbel Nov 11 '12 at 22:22
    
Any chances the second solution code is missing some closing brace somewhere? I'm getting: Runaway argument? \@nil \let \@dtl@line =\@dtl@trmstr \ifx \@dtl@line \@longempty \else \ETC. ! File ended while scanning use of \@dtl@trim. –  Ketan Nov 12 '12 at 1:33
    
@ketan That seems to be a problem with datatool. Maybe your dataset has some irregularities (something about trimming)? –  Qrrbrbirlbel Nov 12 '12 at 1:47
    
@ketan Could you resolve those issues? Apparently blank lines are an issue for datatool. –  Qrrbrbirlbel Nov 22 '12 at 6:12

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.