# Decimal separator and axis label centering with Tikz

The following code creates a figure with Tikz without the use of pfgplots (that I want to avoid here):

% compilation: pdflatex --jobname=Runge-f1 Runge.tex
\documentclass[12pt]{book}
\usepackage[utf8]{inputenc}
\usepackage{filecontents}
\usepackage{tikz}
\pgfrealjobname{Runge}

\begin{filecontents}{B6.dat}
-1  0
0   5
1   0
\end{filecontents}
\definecolor{rouge}{RGB}{233,55,77}

\def\xmin{-1.1}\def\xmax{1.1}\def\ymin{-.6}\def\ymax{5.6}

\begin{document}
\beginpgfgraphicnamed{Runge-f1}%
\footnotesize
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{tikzpicture}[>=latex,scale=1.4,x=4cm,y=1cm]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% background
\fill[rouge!10] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%% grid and labels
\begin{scope}
\clip (\xmin,\ymin) rectangle (\xmax,\ymax);
\foreach \x in {-1,-0.75,...,1} \draw[rouge!35] (\x,\ymin) -- (\x,\ymax);
\foreach \x in {-1,-0.75,...,1} \node[fill=rouge!10,inner sep=2pt,anchor=south,font=\tiny\color{rouge}] at (\x,-.5){$\mathsf\x$}; %%%%%% loop 1
\end{scope}
%%%% curve
\draw plot file{B6.dat};
%%%% external frame
\draw[line width=.6pt,rouge!50] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{tikzpicture}
\endpgfgraphicnamed%
\end{document}

• how is it possible to have a comma as the decimal separator in loop 1?
• in loop 1, would it be possible to center the $\x$ labels with respect to the grid by ignoring the negative sign - when present?

• I unfortunately don't understand the second question in loop 1, would it be possible to place the $\x$ label by ignoring the negative sign '-' when present? could you maybe rephrase it? Jun 7, 2013 at 13:57
• On the horizontal axis, labels -1, -0.75, -0.5 and -0.25 should be centered with respect to the grid by ignoring the - sign. Jun 7, 2013 at 13:59

You can work with siunitx. Therefore I defined a command:

\usepackage{siunitx}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{ \parsenumber } { m }
{
\num[ output-decimal-marker = { , }]{\fp_eval:n { abs ( #1 ) }}
}
\ExplSyntaxOff


\foreach \x in {-1,-0.75,...,1} \node[fill=rouge!10,inner sep=2pt,anchor=south,font=\tiny\color{rouge}] at (\x,-.5){ \parsenumber{\x} }; %%%%%% loop 1


It seems the minus symbol should be displayed without taking any space. Then, you can use:

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{ \parsenumber } { m }
{
\num[ output-decimal-marker = { , },bracket-negative-numbers,close-bracket={},open-bracket={\llap{$-$}}]{#1}
}
\ExplSyntaxOff


Result:

• Thanks! Looks promising. About question 2, I do not want to remove the minus sign in the output, I just want to ignore it for the positioning. Jun 7, 2013 at 14:05
• @pluton: Fixed it. (I hope). Is this what you wanted. Jun 7, 2013 at 14:06
• @JosephWright: Sorry for the misusing of your package ;-) Jun 7, 2013 at 14:08
• @pluton: You can use {$\mathsf{\parsenumber{\x}}$}; whereby you need the following options inside num: \num[detect-family = true, detect-inline-family = math,output-decimal-marker = { , },bracket-negative-numbers,close-bracket={},open-bracket={\llap{$\mathsf-$}}]{#1} Jun 7, 2013 at 14:18
• Add text depth=+0pt (or any other fixed value, say \depthof{$,$}) to the node’s option to vertically align the nodes or use the .base anchor to place the nodes (see my answer). Jun 7, 2013 at 18:45

You can also parse your number with PGF.

\documentclass[tikz]{standalone}
\usepackage{filecontents}

\begin{filecontents}{B6.dat}
-1  0
0   5
1   0
\end{filecontents}
\definecolor{rouge}{RGB}{233,55,77}

\def\xmin{-1.1}\def\xmax{1.1}\def\ymin{-.6}\def\ymax{5.6}

\begin{document}

\footnotesize
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{tikzpicture}[>=latex,scale=1.4,x=4cm,y=1cm]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% background
\fill[rouge!10] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%% grid and labels
\begin{scope}
\clip (\xmin,\ymin) rectangle (\xmax,\ymax);
\foreach \x in {-1,-0.75,...,1}{ \draw[rouge!35] (\x,\ymin) -- (\x,\ymax);}
\foreach \x in {-1,-0.75,...,1}{
\pgfmathsetmacro{\myshift}{(\x < 0? -0.4 : 0)}
\node[fill=rouge!10,
inner sep=2pt,
anchor=base,
font=\tiny\color{rouge},
xshift=\myshift em
]  at (\x,-.5) {$\mathsf{\pgfmathprintnumber[use comma]{\x}}$}; %%%%%% loop 1
}
\end{scope}
%%%% curve
\draw plot file{B6.dat};
%%%% external frame
\draw[line width=.6pt,rouge!50] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{tikzpicture}

\end{document}


I've just guessed the width of a minus but you can also measure it.

• yes, the xshift idea is smart. With, Qrrbrbirlbel's \x\ifdim\x pt<0pt\hphantom{-}\fi test, that should be fine! Jun 8, 2013 at 23:35

A slightly different approach then percusse’s:

We use PGF math’s \pgfmathprintnumber macro with

• the option use comma and
• the option zero-width sign which uses mathtools\mathllap macro that is \robustify-ed by etoolbox. You can also use \llap instead (see comment in code).

Two special macros from the pgfmathprintnumber needs to adjusted for this. (I have ignored the show pos option here that forces a plus sign.)

A rather unorthodox but safe approach would be to use \x\ifdim\x pt<0pt\hphantom{-}\fi, i.e. checking if \x is less then 0 (works only if \x is already an evaluated, expandable value) and add a hidden - after the number, thus centering the sign-less part of the number.

Both solutions have the disadvantage that the node’s border do not correlate to the actual text. (But if you use neither draw nor the border on the west and the right side, this shouldn’t be a problem.)

I also included the node from the second loop in the first loop, so that one doesn’t have to fill the node, this makes the drawing independent from the background (the just may be a line or a shading going on). This is usually also doable with the markings decoration and the mark connection node options, though that has failed me today.

I also included text depth=+0pt in the node options with sets the depth of the node text box to zero hiding the depth of the , and of - which would result in slightly different vertical alignment of the nodes because we have three different types of input:

• (zero-)positive integer (neither , nor -)
• negative integer (only -)
• positive and negative floats (depth of , is greater than the depth of -).

Another solution would be to use the base anchor to place the nodes instead of the (default) center one.

## Code

\documentclass[12pt,tikz,convert=false]{standalone}
\begin{filecontents}{B6.dat}
-1  0
0   5
1   0
\end{filecontents}
\usepackage{etoolbox,mathtools}
\robustify\mathllap
\makeatletter
\newif\ifpgfmathprintnumber@zerowidth@sign
\def\pgfmathprintnumber@zerowidth@#1{\mathllap{#1}}% or \llap{$#1$} without mathtools/etoolbox
\pgfqkeys{/pgf/number format}{zero-width sign/.is if=pgfmathprintnumber@zerowidth@sign,zero-width sign/.default=true}
\def\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printsign#1{%
\def\pgfmathfloat@loc@TMPb{#1}%
\edef\pgf@tempa{\ifpgfmathprintnumber@zerowidth@sign\pgfmathprintnumber@zerowidth@{#1}\else#1\fi}%
\ifx\pgfmathfloat@loc@TMPb\pgfmathfloatparsenumber@tok@MINUS
\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfmathresult\expandafter\expandafter\expandafter{\expandafter\pgfmathresult\pgf@tempa}%
\let\pgfmathfloat@loc@TMPb=\pgfutil@empty
\else
\ifx\pgfmathfloat@loc@TMPb\pgfmathfloatparsenumber@tok@PLUS
\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfmathresult\expandafter\expandafter\expandafter{\expandafter\pgfmathresult\pgf@tempa}%
\let\pgfmathfloat@loc@TMPb=\pgfutil@empty
\else
\ifpgfmathprintnumber@showpositive
\expandafter\def\expandafter\pgfmathresult\expandafter{\pgfmathresult +}%
\fi
\fi
\fi
\ifnum\c@pgf@counta>0
\def\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@NEXT{%
\expandafter\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printtrailingdigits\pgfmathfloat@loc@TMPb
}%
\else
\def\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@NEXT{%
\expandafter\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@counteverythird\pgfmathfloat@loc@TMPb
}%
\fi
\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@NEXT
}
\def\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printall#1{%
\def\pgfmathfloat@loc@TMPb{#1}%
\let\pgfmathfloat@loc@TMPc=\pgfutil@empty
\ifx\pgfmathfloat@loc@TMPb\pgfmathfloatparsenumber@tok@MINUS
\ifpgfmathprintnumber@zerowidth@sign
\let\pgfmathfloat@loc@TMPc\pgfmathprintnumber@zerowidth@
\fi
\else
\ifx\pgfmathfloat@loc@TMPb\pgfmathfloatparsenumber@tok@PLUS
\ifpgfmathprintnumber@zerowidth@sign
\let\pgfmathfloat@loc@TMPc\pgfmathprintnumber@zerowidth@
\fi
\else
\ifpgfmathprintnumber@showpositive
\def\pgfmathfloat@loc@TMPc{+}%
\fi
\fi
\fi
\expandafter\pgfmathprintnumber@fixed@styleDEFAULT@impl@noperiod@printall@\pgfmathfloat@loc@TMPc#1%
}
\makeatother

\definecolor{rouge}{RGB}{233,55,77}
\def\xmin{-1.1}\def\xmax{1.1}\def\ymin{-.6}\def\ymax{5.6}
\begin{document}
\footnotesize
\begin{tikzpicture}[>=latex,scale=1.4,x=4cm,y=1cm]
%%%% background
\fill[rouge!10] (\xmin,\ymin) rectangle (\xmax,\ymax);
%%%% grid and labels
\begin{scope}
\clip (\xmin,\ymin) rectangle (\xmax,\ymax);
\foreach \x in {-1,-0.75,...,1}
\path[rouge!35]
node[inner sep=2pt,anchor=south,font=\tiny\everymath{\color{rouge}\mathsf},text depth=+0pt] at (\x,-.5) {\pgfmathprintnumber[zero-width sign,use comma]{\x}}
edge (\x,\ymin)
edge (\x,\ymax);
\end{scope}
%%%% curve
\draw plot file{B6.dat};
%%%% external frame
\draw[line width=.6pt,rouge!50] (\xmin,\ymin) rectangle (\xmax,\ymax);
\end{tikzpicture}
\end{document}


## Output

• Very involved! I'm no sure how you can know all this!?? Jun 8, 2013 at 23:32

To solve the second part of your question: I would split up the second loop into two loops. In the first loop covering the negative values you can use a yshift by the 3pt (which is the amount of space the minus singt takes.

\foreach \x in {-1,-0.75,...,-0.25} \node[fill=rouge!10,inner
sep=2pt,anchor=south,font=\tiny\color{rouge}, xshift = -3pt] at (\x,-.5){$\mathsf\x$};
\foreach \x in {0,0.25,...,1} \node[fill=rouge!10,inner
sep=2pt,anchor=south,font=\tiny\color{rouge}] at (\x,-.5){$\mathsf\x$};