6

I am tinkering with a graph. By third parties I am required to use pgfplots to do so.

(So the real reason for my problems in this matter can be seen in my own social skills: I let myself get into a situation that should be avoided: Getting involved in putting something together quickly and well without having profound knowledge of the tools to be used to do it. That one needs some time to get familiar with TikZ and pgfplots can't be blamed on the developers.

I am grateful for the helpful answers and thankful for the kindness and straightforwardness with which I was met by those who helped me.)

So far I have pieced together the code below.

I would like to optimize the illustration that I have so far.
After I have been working on it for more than two days now—most of the time searching the correct piece of information on usage of pgfplots—I still have the following questions:

  1. How do I get the (thin, lighter) grid lines of the "minor grid" to be below the thicker/darker grid lines of the "major grid" instead of above them? Also for the extra x ticks and the extra y ticks, where not only horizontal but also vertical lines of the minor grid are above the lines of the major grid?
  2. How to have ticks in the same color as the axes?
  3. How to extract data about linestyle/color etc of ticks so that the data can be used outside the axes-environment as well?
  4. Is there an easier way to label the coordinate origin as in the figure, which also works within the axis environment?
  5. How to have graphs not stick into the axes?
\documentclass[tikz,border=5mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat = newest} % <- Without this strangely the axis label is not placed 
                              %    correctly; it took four hours to figure this out.

\begin{document}

\begin{tikzpicture}[x=1cm, y=1cm]
% Why are there no pgf-keys whose values could be retrieved for having the length of
% the x- and the y-unit-vector.
\path(1,1);\pgfgetlastxy{\Ax}{\Ay}%
\begin{axis}[%
  x=\Ax, y=\Ay,
  axis y line = left,
  axis x line = bottom,
  xtick pos=bottom,
  ytick pos=left,
  y axis line style = {->},
  x axis line style = {->},
  xtick distance = 1, 
  ytick distance = 1, 
  tick align=outside,
  minor tick style={draw=none},
  xlabel style={at={(rel axis cs:1,0)}}, xlabel = {\(x\)},
  ylabel style={at={(rel axis cs:0,1)},rotate=-90},  ylabel = {\(y\)},
  grid=both, 
    minor grid style={very thin, lightgray!25}, 
    minor tick num = 9, 
    major grid style={thin},
  xmin = 0, xmax = 15.5, ymin = 0, ymax = 3.5,
  xtick = {1,...,15.5},
  ytick = {1,...,3.5},
  extra x ticks={0,1},
  extra x tick labels={},
  extra x tick style={grid=minor, major tick length=0pt},
  extra y ticks={0,1},
  extra y tick labels={},
  extra y tick style={grid=minor, major tick length=0pt},
]%
%  It seems drawing outside the area specified by xmin/xmax/ymin/ymax
%  is not (easily) possible from inside the axis environment, so let's
%  calculate the components of the vector of the origin tick now and
%  save them to macros for usage outside the axis environment.
%  Probably the line-style of major ticks should be saved for usage
%  outside also but I don't want to spend a week on finding out how
%  to do so.
%\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/x}}%
%\global\let\scratchx=\pgfmathresult
%\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/y}}%
%\global\let\scratchy=\pgfmathresult
\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/x}/sqrt(2)}%
\global\let\scratchx=\pgfmathresult
\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/y}/sqrt(2)}%
\global\let\scratchy=\pgfmathresult
%
\addplot[
  domain = 0:15.5,%
  samples = 2,% <- I suppose for a straight line more samples are not needed
  smooth, thick, blue
]{x/5} node[above,pos=0.5] {\vbox{\hbox{\(f(x)=\frac{x}{5}\)}\kern.1\dimexpr\Ay\relax}};
\end{axis}
% Draw the origin:
%\draw[very thin] (0,0)--(\scratchx,\scratchy) node [anchor=north east]{\(\mathrm{O}\)};
\draw[very thin] (0,0)--(\scratchx,\scratchy);
\coordinate (\scratchx,\scratchy) node [anchor=north east]{\(\mathrm{O}\)};
\end{tikzpicture}
\end{document}

The entire graph:

enter image description here

Enlargement of the bottom left corner so one can see what my questions are about:
 

enter image description here



Thanks to dexteritas and Torbjørn T., I have now put together something that works within the axis environment, which makes question 3 obsolete and also solves all other problems:

Here is the code:

\documentclass[tikz,border=5mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{arrows}
\pgfplotsset{compat = newest} % <- Without this the axis label is not placed correctly.
\begin{document}
\begin{tikzpicture}[x=1cm, y=1cm]
% Why are there no pgf-keys whose values could be retrieved for having the length of
% the x- and the y-unit-vector?
\path(1,1);\pgfgetlastxy{\Ax}{\Ay}%
\begin{axis}[%
  %
  % General settings:
  %
  % - Make x and y the same as that of the surrounding tikzpicture environment:
  %
  x=\Ax, y=\Ay,
  %
  % - When the end of the axis environment is reached redraw the axes to ensure
  %   they are not overlapped by a graph or by components of the grid:
  %
  after end axis/.append code={
      \pgfplotsset{
          axis line style=opaque,
          ticklabel style=opaque,
          tick style=opaque,
          grid=none
      }
      \csname pgfplots@draw@axis\endcsname
  },
  %
  % - Make it possible to draw outside the area denoted by xmin/xmax/ymin/ymax:
  %
  clip mode=individual,
  %
  % Appearance of the axes:
  %
  axis y line = left,
  axis x line = bottom,
  y axis line style = {->, >=stealth'},
  x axis line style = {->, >=stealth'},
  xlabel style={at={(rel axis cs:1,0)}}, xlabel = {\(x\)},
  ylabel style={at={(rel axis cs:0,1)},rotate=-90},  ylabel = {\(y\)},
  %
  % - range of the axes:
  %
  xmin = 0, xmax = 15.5, ymin = 0, ymax = 3.5,
  %
  % Appearance of the ticks on the axes and the tick labels:
  %
  xtick pos=bottom,
  ytick pos=left,
  xtick distance = 1, 
  ytick distance = 1, 
  tick align=outside,
  major tick style={thin, black},
  minor tick style={very thin, black},
  minor tick num = 1, 
  %
  % As the origin needs extra treatment labels of major ticks shall begin with 1:
  %
  xtick = {1,...,15},
  ytick = {1,...,3},
  %
  % Draw extra minor ticks at x=0.5 and y=0.5; the pgfplots-manual says that
  % all extra ticks are considered major ticks, so use extra x tick style/
  % extra y tick style for assigning major ticks the parameters of minor ticks
  % and then draw them without labels:
  %
  extra x tick style={major tick length=\pgfkeysvalueof{/pgfplots/minor tick length}, major tick style={very thin, black}},
  extra y tick style={major tick length=\pgfkeysvalueof{/pgfplots/minor tick length}, major tick style={very thin, black}},
  extra x ticks={0.5},
  extra y ticks={0.5},
  extra x tick labels={},
  extra y tick labels={},
  grid=none, 
]%
%
% Draw the grids:
%
\draw[xstep=0.1,ystep=0.1,lightgray!25,ultra thin] (0,0) grid (15.5,3.5); 
\draw[xstep=0.5,ystep=0.5,lightgray!66,very thin] (0,0) grid (15.5,3.5);
\draw[xstep=1,ystep=1,lightgray,thin] (0,0) grid (15.5,3.5);
%
% Draw the plot(s):
%  
% - The slope of the following plot is 1/5. So let's rotate the node atan(1/5).
\pgfmathparse{atan(1/5)}\let\scratch\pgfmathresult
\addplot[
  domain = 0:15.5,%
  samples = 2,% <- I suppose for a straight line more samples are not needed
  smooth, thick, blue
]{x/5} node[above,pos=0.5,rotate={\scratch}] {\footnotesize\(f(x)=\frac{x}{5}\)};
%
% Draw the origin:
%
%\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/x}}%
%\let\scratchx=\pgfmathresult
%\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/y}}%
%\let\scratchy=\pgfmathresult
%\draw[thin] (0,0)--(\scratchx,\scratchy) node [anchor=north east]{\(\mathrm{O}\)};
\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/x}/sqrt(2)}%
\let\scratchx=\pgfmathresult
\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/y}/sqrt(2)}%
\let\scratchy=\pgfmathresult
\draw[thin] (0,0)--(\scratchx,\scratchy);
\coordinate (\scratchx,\scratchy) node [anchor=north east]{\(\mathrm{O}\)};
%
\end{axis}
\end{tikzpicture}
\end{document}

Here is the entire plot:

enter image description here

Here the enlargement:

enter image description here

8
  • 1
    A couple of minor comments: About 4.: everything outside x/y-min/max is clipped by default, you can turn that off with clip=false. Alternatively, clip mode=individual will clip plot lines, but not \node, \draw etc. Regarding label placement, compat=1.3 or higher will improve the positioning. It is actually mentioned in the manual in the section about x/y/zlabel but I won't necessary disagree about it being a bit obscure. Sep 5, 2022 at 19:40
  • 1
    2. You can make ticks black with \pgfplotsset{every tick/.append style={color=black}}.
    – dexteritas
    Sep 5, 2022 at 19:57
  • 1
    About 5. (?) "The blue graph should not overlap the black axis" see tikz/pgfplots advanced z-order axis/grid.
    – dexteritas
    Sep 5, 2022 at 20:22
  • 2
    Maybe noticing the requirer that things can be done easier, handier, and highly customized with plain TikZ
    – Black Mild
    Sep 6, 2022 at 4:42
  • 1
    I think @BlackMild is right here. It is always difficult for a high level package (pgfplots) to provide the same functionality as the layer below (pgf/tikz). For very specific customizations it is then probably easier to draw it directly with tikz to avoid complicated solutions (and unnecessary duplications). It would of course be useful if the order in which the grids and axes are drawn were also directly adjustable with the package. The manual is very detailed and you have to search a bit, but I found the answer for question 2 directly in the manual.
    – dexteritas
    Sep 6, 2022 at 7:04

1 Answer 1

5

Adaptations

That were many questions. I solved some of them:

  1. draw a major grid manually again
    \draw[xstep=1,ystep=1,lightgray,thin] (0,0) grid (15.5,3.5);
    
    I set xmin = 0.01, ymin = 0.01 so that it is possible to have xtick and ytick start with 0 and thus not need the extra ticks that would be drawn above again.
  2. make ticks black with
    \pgfplotsset{every tick/.append style={color=black}}
    
  3. and ...
  4. Maybe use the comment by Torbjørn T. (I haven't implemented that one)
  5. "The blue graph should not overlap the black axis" – I used the answer by Jake at tikz/pgfplots advanced z-order axis/grid:
    after end axis/.append code={
        \pgfplotsset{
            axis line style=opaque,
            ticklabel style=opaque,
            tick style=opaque,
            grid=none
        }
        \pgfplotsdrawaxis
    },
    

Result

enter image description here

Code

\documentclass[tikz,border=5mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat = newest} % <- Without this strangely the axis label is not placed 
                              %    correctly; it took four hours to figure this out.

\begin{document}

\makeatletter \newcommand{\pgfplotsdrawaxis}{\pgfplots@draw@axis} \makeatother

\pgfplotsset{
    every tick/.append style={color=black},
    after end axis/.append code={
        \pgfplotsset{
            axis line style=opaque,
            ticklabel style=opaque,
            tick style=opaque,
            grid=none
        }
        \pgfplotsdrawaxis
    },
} % applies to major and minor ticks,

\begin{tikzpicture}[x=1cm, y=1cm]
% Why are there no pgf-keys whose values could be retrieved for having the length of
% the x- and the y-unit-vector.
\path(1,1);\pgfgetlastxy{\Ax}{\Ay}%
\begin{axis}[%
  x=\Ax, y=\Ay,
  axis y line = left,
  axis x line = bottom,
  xtick pos=bottom,
  ytick pos=left,
  y axis line style = {->},
  x axis line style = {->},
  xtick distance = 1, 
  ytick distance = 1, 
  tick align=outside,
  minor tick style={draw=none},
  xlabel style={at={(rel axis cs:1,0)}}, xlabel = {\(x\)},
  ylabel style={at={(rel axis cs:0,1)},rotate=-90},  ylabel = {\(y\)},
  grid=both, 
    minor grid style={very thin, lightgray!25}, 
    minor tick num = 9, 
    major grid style={thin},
  xmin = 0.01, xmax = 15.5, ymin = 0.01, ymax = 3.5,
  xtick = {0,...,15.5},
  ytick = {0,...,3.5},
]%
%  It seems drawing outside the area specified by xmin/xmax/ymin/ymax
%  is not (easily) possible from inside the axis environment, so let's
%  calculate the components of the vector of the origin tick now and
%  save them to macros for usage outside the axis environment.
%  Probably the line-style of major ticks should be saved for usage
%  outside also but I don't want to spend a week on finding out how
%  to do so.
%\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/x}}%
%\global\let\scratchx=\pgfmathresult
%\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/y}}%
%\global\let\scratchy=\pgfmathresult
\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/x}/sqrt(2)}%
\global\let\scratchx=\pgfmathresult
\pgfmathparse{-\pgfkeysvalueof{/pgfplots/major tick length}/\pgfkeysvalueof{/pgfplots/y}/sqrt(2)}%
\global\let\scratchy=\pgfmathresult
%
\draw[xstep=1,ystep=1,lightgray,thin] (0,0) grid (15.5,3.5); % override with major grid again
%
\addplot[
  domain = 0:15.5,%
  samples = 2,% <- I suppose for a straight line more samples are not needed
  smooth, thick, blue
]{x/5} node[above,pos=0.5] {\vbox{\hbox{\(f(x)=\frac{x}{5}\)}\kern.1\dimexpr\Ay\relax}};
\end{axis}
% Draw the origin:
%\draw[very thin] (0,0)--(\scratchx,\scratchy) node [anchor=north east]{\(\mathrm{O}\)};
\draw[very thin] (0,0)--(\scratchx,\scratchy);
\coordinate (\scratchx,\scratchy) node [anchor=north east]{\(\mathrm{O}\)};
\end{tikzpicture}
\end{document}

You must log in to answer this question.

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