6

I tried to plot a data set containing seconds and milliseconds with pgfplots. I’ve found a solution for my task here (pgfplots data time format), which I changed a bit. This principally works very well. My code goes here:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepgfplotslibrary{dateplot}

\def\transformtime#1:#2:#3!{
    \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
    \pgfmathparse{#1*3600-\pgfkeysvalueof{/pgfplots/timeplot zero}*3600+#2*60+#3}
    \pgfkeys{/pgf/fpu=false}
}

\pgfplotsset{
    timeplot zero/.initial=0,
    timeplot/.style={
        y coord trafo/.code={\expandafter\transformtime##1!},
        y coord inv trafo/.code={%
            \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed,}
            \pgfmathsetmacro\hours{floor(##1/3600)+\pgfkeysvalueof{/pgfplots/timeplot zero}}
            \pgfmathsetmacro\minutes{floor((##1-(\hours - \pgfkeysvalueof{/pgfplots/timeplot zero})*3600)/60)}
            \pgfmathsetmacro\seconds{##1-floor((##1)/60)*60}
            \def\pgfmathresult{\pgfmathprintnumber{\hours}:\pgfmathprintnumber{\minutes}:\pgfmathprintnumber[fixed zerofill]{\seconds}}
            \pgfkeys{/pgf/fpu=false}
        },
    scaled y ticks=false,
    yticklabel=\tick
    }
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
    timeplot, timeplot zero=0, grid=major, grid style=dashed, ytick={00:12:00, 00:13:00, 00:14:00},
]
\addplot table {
State           Time  
-13 00:12:42.40
-12 00:12:57.06
-11 00:13:17.59
-10 00:13:40.83
-9  00:14:07.44
-8  00:14:31.11
-7  00:14:04.28
-6  00:14:12.07
-5  00:14:09.27
-4  00:13:59.92
-3  00:13:56.82
-2  00:13:55.17
-1  00:13:53.52
0   00:13:52.47
1   00:13:59.32
2   00:14:00.58
3   00:13:43.12
4   00:13:49.05
5   00:13:28.63
};
\end{axis}
\end{tikzpicture}
\end{document}

The problem now is that I get odd tick labels (both 12:60 and 14:0.00 is not I was expecting...):

enter image description here

I found a similar question (Date plot using pgfplots with odd tick label), but with that solution I unfortunately do not know how to solve my problem. Could anyone here give me a hint?

  • Welcome to TeX.SX! – OSjerick Dec 14 '13 at 16:15
  • The 12:60 is obviously wrong, but I'm not sure what you were expecting instead of the 14:0.00. Do you want that to print as 14:00? – Jake Dec 14 '13 at 16:36
  • Yes, I would prefer 14:00.00. – johannes Dec 16 '13 at 15:45
1

Here's one attempt, where I've added some conditional code to add the leading zero if the number is less than 10. The idea is like this (for the minutes part):

\pgfmathparse{ifthenelse(\minutes<10,0,)}\pgfmathresult\pgfmathprintnumber{\minutes}:%

The \pgfmathparse will store either 0 or an empty string depending on whether a leading zero is required (determined by testing if \minutes is less than 10). This is then dumped into the \def of the top-level \pgfmathresult by invoking \pgfmathresult inside the group, which is followed by the \pgfmathprintnumber for the number of minutes itself.

Unfortunately I was not really able to solve the 12:60 rounding issue. I thought maybe defining \seconds, \minutes, and \hours from the bottom up rather than the top down would help, but that caused issues elsewhere.

But: disabling the FPU makes it correct with no detrimental effects, because pgfplots does its own scaling to avoid "Dimension too large" errors. So it may or may not be an acceptable solution for you.

I also changed the options for the printing of \seconds:

\pgfmathprintnumber[fixed,fixed zerofill]{\seconds}%

Adding fixed "locks in" fixed mode so scientific notation is never used, and the fixed zerofill will always be respected (since we're always in fixed mode).

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}
\usepgfplotslibrary{dateplot}

\def\transformtime#1:#2:#3!{
%    \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
    \pgfmathparse{#1*3600-\pgfkeysvalueof{/pgfplots/timeplot zero}*3600+#2*60+#3}
%    \pgfkeys{/pgf/fpu=false}
}

\pgfplotsset{
    timeplot zero/.initial=0,
    timeplot/.style={
        y coord trafo/.code={\expandafter\transformtime##1!},
        y coord inv trafo/.code={%
%            \pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed,}
            \pgfmathsetmacro\hours{floor(##1/3600)+\pgfkeysvalueof{/pgfplots/timeplot zero}}
            \pgfmathsetmacro\minutes{floor((##1-(\hours - \pgfkeysvalueof{/pgfplots/timeplot zero})*3600)/60)}
            \pgfmathsetmacro\seconds{##1-floor((##1)/60)*60}
            \def\pgfmathresult{%
              \pgfmathparse{ifthenelse(  \hours<10,0,)}\pgfmathresult\pgfmathprintnumber{\hours}:%
              \pgfmathparse{ifthenelse(\minutes<10,0,)}\pgfmathresult\pgfmathprintnumber{\minutes}:%
              \pgfmathparse{ifthenelse(\seconds<10,0,)}\pgfmathresult\pgfmathprintnumber[fixed,fixed zerofill]{\seconds}%
            }
%            \pgfkeys{/pgf/fpu=false}
        },
    scaled y ticks=false,
    yticklabel=\tick
    }
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
    timeplot, timeplot zero=0, ytick={00:11:30.056, 00:12:00, 00:13:00, 00:14:00},
]
\addplot table {
State           Time  
-13 00:12:42.40
-12 00:12:57.06
-11 00:13:17.59
-10 00:13:40.83
-9  00:14:07.44
-8  00:14:31.11
-7  00:14:04.28
-6  00:14:12.07
-5  00:14:09.27
-4  00:13:59.92
-3  00:13:56.82
-2  00:13:55.17
-1  00:13:53.52
0   00:13:52.47
1   00:13:59.32
2   00:14:00.58
3   00:13:43.12
4   00:13:49.05
5   00:13:28.63
7   00:11:15.6256432
};
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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