45

How do I make the axis labels use multiples of \pi in PGFPlots? enter image description here

6
  • 1
    See the example in pgfplots manual pages 262-263 (manual for version 1.5, of July 29 2011) for a solution. (Assuming you're after the labels on the x-axis.) Nov 15, 2011 at 16:31
  • I think you mean "display one axis". If so, which one? Can you clarify the question a bit? Also, it would help to show the code that produced your figure, not just the figure.
    – Alan Munn
    Nov 15, 2011 at 16:31
  • 4
    Does this post help?
    – cmhughes
    Nov 15, 2011 at 16:32
  • It is not clear what you are looking for. Please compose a MWE that illustrates the problem including the \documentclass and the appropriate packages so that those trying to help don't have to recreate it. Nov 15, 2011 at 16:34
  • Did you look at Pgfplots with custom axis markers? I think they solve your question. May be not an automatic solution, but a solution which looks like the one at page 264-265 (section 4.21) of pgfplots manual.
    – Ignasi
    Nov 15, 2011 at 16:36

4 Answers 4

43

As mentioned in the comments, this is basically the same as Pgfplots with custom axis markers. All you need to do is to specify where you want the xtick={...} and how you want each of them labelled via xticklabels={...}.

Method 1: Explicit Labels:

Explicit labels can be specified using xticklabels. The one complication that comes about is that sometimes the label overlaps with the plot as is the case for -\pi and 2pi in the blue graph. I have not found a elegant way to fix that so I just manually add some spacing to those labels to tweak them as I did the red graph:

enter image description here

Method 2: Scaled Axis Labels:

An alternate is to scale the x-axis labels in terms of multiples of pi, and show that the x axis labels are multiples of pi. This solution is based on Spikes solution, so you should up vote that if you prefer this version. I prefer to label this as part of the axis (brown graph), but others might prefer to display it as in the cyan graph:

enter image description here

xticklabels:

If you want a tick mark, but not a corresponding label you can simply place an empty label as in $$ or just better just use a double comma ,, to skip it being labelled. For instance, if the labels at +\pi and -\pi are not desired, simply replace those labels with spaces (extra spaces here are just to point out where the gap is):

xticklabels={$-2\pi$, $-\frac{3\pi}{2}$,    , $-\frac{\pi}{2}$, 
             $\frac{\pi}{2}$,     , $\frac{3\pi}{2}$, $2\pi$}

xtick:

Note that two methods of specifying where the tick marks go are used in the code. One is to explicitly list them as

xtick={-6.28318, -4.7123889, -3.14159, -1.5708, 1.5708, 3.14159, 4.7123889, 6.28318}

This is used in the first two examples so that the correspondence between the xtick and xticklabels is easier to see. The second two use the more compact method:

xtick={-6.28318, -4.7123889, ..., 6.28318}

Code:

\documentclass{article} 
\usepackage{pgfplots}

% Grouping the common style settings here to make the code below easier to read
\pgfkeys{/pgfplots/Axis Style/.style={
    width=13.5cm, height=5cm,
    axis x line=center, 
    axis y line=middle, 
    samples=100,
    ymin=-1.5, ymax=1.5,
    xmin=-7.0, xmax=7.0,
    domain=-2*pi:2*pi
}}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
    Axis Style,
    xtick={
        -6.28318, -4.7123889, -3.14159, -1.5708,
        1.5708, 3.14159, 4.7123889, 6.28318
    },
    xticklabels={
        $-2\pi$, $-\frac{3\pi}{2}$, $-\pi$, $-\frac{\pi}{2}$,
        $\frac{\pi}{2}$, $\pi$, $\frac{3\pi}{2}$, $2\pi$
    }
]
\addplot [mark=none, ultra thick, blue] {sin(deg(x))};
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[
    Axis Style,
    xtick={
        -6.28318, -4.7123889, -3.14159, -1.5708,
        1.5708, 3.14159, 4.7123889, 6.28318
    },
    xticklabels={
        $-2\pi$, $-\frac{3\pi}{2}$, $-\pi\hspace{0.30cm}$, $-\frac{\pi}{2}$,
        $\frac{\pi}{2}$, $\pi\hspace{0.10cm}$, $\frac{3\pi}{2}$, $\hspace{0.25cm} 2\pi$
    }
]
\addplot [mark=none, ultra thick, red] {sin(deg(x))};
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[
    Axis Style,
    xtick={-6.28318, -4.7123889, ..., 6.28318},
    scaled x ticks={real:3.1415},
    xtick scale label code/.code={},
    xlabel={$x \thinspace [\times \pi]$}
]
\addplot [mark=none, ultra thick, brown] {sin(deg(x))};
\end{axis}
\end{tikzpicture}

\begin{tikzpicture}
\begin{axis}[
    Axis Style,
    xtick={-6.28318, -4.7123889, ..., 6.28318},
    scaled x ticks={real:3.1415},
    xtick scale label code/.code={$[\times \pi]$},
    xlabel={$x$}
]
\addplot [mark=none, ultra thick, cyan] {sin(deg(x))};
\end{axis}
\end{tikzpicture}
\end{document}
4
15

There is also a bit more "automated" solution which I first presented here (-- this seems to be a duplicate of this question --) with some more refinement inspired by this answer.

Please have a look at the comments of the code to find out, how it works.

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    \pgfplotsset{
        axis lines=middle,
        xlabel=$x$,
        ylabel=$y$,
        no markers,
        samples=51,
        trig format plots=rad,
        %
        % create a style to scale x axis values by \pi and
        % remove the corresponding label
        x axis in pi/.style={
            scaled x ticks={real:\PI},
            xtick scale label code/.code={},
            % in case you want to set an explicit tick distance
            xtick distance=pi/#1,
            % add code here for formatting the `xticklabels'
            % I configured exceptions for \pm\pi where no number in front
            % of these are shown and for fractional values these should be
            % shown as fractions
            xticklabel={%
                % to avoid some mess with TeX precision, first
                % round the `\tick' value to one digit after the comma
                \pgfmathparse{round(100*\tick)/100}
                \ifdim \pgfmathresult pt = 1pt
                    \strut$\pi$%
                \else\ifdim \pgfmathresult pt = -1pt
                    \strut$-\pi$%
                \else
                    % depending on whether the resulting number is an integer
                    % show it as integer only, otherwise use the style given
                    % in `xticklabel style'
                    \pgfmathifisint{\pgfmathresult}{%
                        \strut$\pgfmathprintnumber[int detect]{\pgfmathresult}\pi$%
                    }{%
                        % show \pi next to the frac
                        \strut$\pgfmathprintnumber{\pgfmathresult}\pi$%
%                        % show \pi in the numerator of the frac
%                        \pgfmathparse{\pgfmathresult*#1}%
%                        \strut$\frac{\pgfmathprintnumber[int detect]{\pgfmathresult}\pi}{#1}$%
                    }
                \fi\fi
            },
            % set number plotting to frac style
            xticklabel style={
                /pgf/number format/.cd,
                    frac,
                    frac whole=false,
%                    % if you prefer to have the same denominator value everywhere
%                    frac denom=#1,
            },
        },
    }
    % define precision of \pi
    % this is set here to the value of \pgfmathpi
    \pgfmathsetmacro{\PI}{pi}
\begin{document}
    \begin{tikzpicture}
        \begin{axis}[
%            % uncomment the next two lines for `x axis in pi=4' so the
%            % `xticklabels' don't overlap
%            width=1.5*\axisdefaultwidth,
%            height=\axisdefaultheight,
            domain=-1.1*pi:2.1*pi,
            ymin=-1.1,
            ymax=+1.1,
            % apply the above created style
            % (works for the values 1, 2 and 4)
            x axis in pi=2,
            ytick distance=1,
            smooth,
        ]
            \addplot {sin(x)};
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code

4
  • Is it possible to encapsulate your code to a key/style?
    – Julia
    Apr 25, 2017 at 19:07
  • Is it also possible to have $\frac{\pi}{2}$ instead of $\frac{1}{2}\pi$ etc.?
    – Julia
    Apr 25, 2017 at 19:12
  • If I change $\PI/2$ to $\PI/4$ in your code it doesn't work anymore (gives large fractions), changing 10 to 1000 in round, and loading fp solves this, but I didn't manage to make $\PI/8$ work...
    – Julia
    Apr 25, 2017 at 19:15
  • @Julia, of course you can encapsulate it into a style and you also can place \pi in the numerator of \frac. Therefore see my edited code. Unfortunately I am also unable to make my solution work for \pi/8, sorry. Apr 27, 2017 at 1:48
6

Here is another solution inspired by Stefan Pinnow's answer. To avoid the precision issue with /pgf/number format/frac, it calculates explicitly the reduced fraction for every label, so it should work for pi/8, etc.

sin(x)

\documentclass[border=5pt]{standalone}

% Workaround for gcd() issue in pgfplots 1.14
% (see https://sourceforge.net/p/pgfplots/bugs/129/ and
% https://tex.stackexchange.com/questions/328972/ )
\usepackage{tikz}
\makeatletter
\let\pgfmathgcdX=\pgfmathgcd@
\usepackage{pgfplots}%
\let\pgfmathgcd@=\pgfmathgcdX
\makeatother

% Load math library, for \tikzmath
\usetikzlibrary{math}

\pgfplotsset{
    % Typeset fractions of pi at regular intervals on x axis
    x axis in pi/.style={
        % Make sure the x axis is in radians
        trig format plots=rad,
        % Set tick distance from style argument
        xtick distance={pi/#1},
        % Set label style: calculate reduced fraction of pi
        xticklabel={
            \tikzmath{
                % Calculate this tick's multiple of pi/#1
                int \numorig, \gcd, \num, \denom, \absnum;
                \numorig = round(\tick*#1/pi);
                % Calculate reduced fraction for \numorig/#1
                \gcd = gcd(\numorig,#1);
                \num = \numorig / \gcd;
                \absnum = abs(\num);
                \denom = #1 / \gcd;
                % Build label text
                if \num < 0 then {
                    let \sign = -;
                } else {
                    let \sign =;
                };
                if \absnum == 1 then {
                    let \numpi = \pi;
                } else {
                    let \numpi = \absnum\pi;
                };
                if \denom == 1 then {
                    if \num == 0 then {
                        { \strut$0$ };
                    } else {
                        { \strut$\sign\numpi$ };
                    };
                } else {
                    { \strut$\sign\frac{\numpi}{\denom}$ };
                    % Other style with all pi symbols same and aligned:
                    %{ \strut$\sign\frac{\absnum}{\denom}\pi$ };
                };
            }
        },
    },
}

\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        width=14cm,
        axis equal image,
        domain=-2*pi:2*pi,
        axis lines=center,
        enlargelimits={abs=0.4},
        no markers,
        samples=100,
        ytick distance = 1,
        x axis in pi=2, % tick distance as fraction of pi
        ]
        \addplot {sin(x)};
    \end{axis}
\end{tikzpicture}
\end{document}
2
1

I realize the question is on PGFPlots, but I was interested in finding or providing in this case a solution using only TikZ code. Although the PGFPlots automation and mathematical nature of the code is appealing, I wonder if all the overhead is necessary for most Trig graphs. In any case, here is my solution. The one concern I had in making this graph was for the axes to represent true relative distances. Therefore, the x-axis is scaled by pi/4 while the y-axis is simply units of natural numbers.

\documentclass[border=5pt]{standalone}

\usepackage{amsmath}    \usepackage{amsfonts}   \usepackage{amssymb}
\usepackage{amsthm}     \usepackage{latexsym}   \usepackage{mathtools}

\usepackage{tikz}
\usetikzlibrary{arrows,automata,calc}

\begin{document}


\newcommand*{\xMin}{-9}
\newcommand*{\xMax}{9}
\newcommand*{\yMin}{-3}
\newcommand*{\yMax}{3}
\scriptsize
    \begin{tikzpicture}[->,>=stealth,scale=0.65]

        \foreach \i in {\xMin,...,\xMax} {
        \draw [-,very thin,gray,scale={pi/4}] (\i,{-3/(pi/4)}) -- (\i,{3/(pi/4)});
        }

        \foreach \i in {\yMin,...,\yMax} {
        \draw [-,very thin,gray] ({\xMin*pi/4},\i) -- ({\xMax*pi/4},\i);
        }

        \draw node at ({pi},0) [below] {${\pi}$};
        \draw node at ({2*pi},0) [below] [xshift=1pt] {${2\pi}$};
        \draw node at ({-pi},0) [below] [xshift=-2pt]  {${-\pi}$};
        \draw node at ({-2*pi},0) [below] [xshift=-2pt] {${-2\pi}$};

        \draw node at (0,1) [left] {$1$};
        \draw node at (0,2) [left] {$2$};
        \draw node at (0,-1) [left] {$-1$};
        \draw node at (0,-2) [left] {$-2$};


        \draw [->] [thick] ({\xMin*(pi/4)},0) -- ({\xMax*(pi/4)+0.5},0) 
            node [right] {$x$};
        \draw [->] [thick] (0,-3) -- (0,3.5)
            node [pos=0.45] [xshift=-3.5pt,yshift=-2pt] {$o$}
            node [above] {$y$};

        \draw [-,thick,magenta,domain={-2*pi}:{2*pi},samples=100] 
        plot (\x, {sin(\x*180/pi)});

        \end{tikzpicture}
\normalsize


\end{document}


sine waves

1
  • No fractional labels? Nov 17, 2020 at 14:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .