# Control output grid with in pgfplots while doing everything else automatically

A nice feature of pgfplots is that it automatically chooses reasonable values for maximum/minimum x and y values and for the x and y unit vectors which especially effects the grid size and the labels of the ticks on x and y axis.

On the other hand I know that I can choose the xmin,xmax,... values and the unit vectors manually. I do this for example when I want that the distance of the ticks is exactly 1 cm on the resulting printed paper. See for example my question here: pgfplots axis scaling

However is it possible to combine both things in a reasonable way such that the following hold: Require that pgfplots draws the grid lines such that the distance of the ticks is say 1 cm on the printed paper, but let it do everything else automatically similar like it would normally do such that the resulting plot fits nicely on the page...

Please ask if it is not completely clear what I want (I feel that my english is too bad to make it really clear...)

Edit

Here are two examples, see the comments in the code:

\documentclass{article}

\usepackage{pgfplots}

\begin{document}

%In this example everything is pretty nice, except that the grid on the printed paper is
%not exactly 1cm x 1cm

\begin{tikzpicture}
\begin{axis}[grid,no markers,samples=100]
\end{axis}
\end{tikzpicture}

%In this example the grid size on the printed paper is 1cm x 1cm, which I want, but
%the picture is really too large
\begin{tikzpicture}
\begin{axis}[grid,no markers,samples=100,x=1cm,y=1cm]
\end{axis}
\end{tikzpicture}

%Here I adjusted it manually. But I want that it does this automatically. I don't want to think about what will be the maximum value of the function etc.

\begin{tikzpicture}
\begin{axis}[grid=both,no markers,samples=100,x=1cm,y=1cm/50,yticks={0,50,...,200}]
\end{axis}
\end{tikzpicture}

\end{document}


I don't want to include the output in this case since it is just to large in the second example.

-
I am not sure I fully understand your question, but if you just specify the x and y unit vectors to be 1cm everything else should be automatic. Otherwise, please compose a MWE that exactly illustrates the problem. Also, once you specify the size of the unit vectors this restricts how much can fit on the page. – Peter Grill Sep 25 '12 at 7:54
@PeterGrill If I do that, the picture may get very large even larger than a page, depending on the function because 1 unit on the picture is one unit on the paper. But I want that the distance between the ticks (which determine the grid size) is 1cm on the paper, but that pgfplots automatically chooses what 1 corresponds to in "picture units" such that the picture has a reasonable size... – student Sep 25 '12 at 8:06
I don't really think it makes sense to force ticks at 1cm without defining what 1cm should be. Otherwise that would mean that the ticks could possibly be at meaningless numbers, such as 0.732, 1.468, ... – Peter Grill Sep 25 '12 at 8:13
So you want to allow the height and width of the plot to vary? – Jake Sep 25 '12 at 8:44
@Jake Yes. But within reasonable constraints, i.e. the size of the resulting picture (bounding box) should be comparable to the size of the output when pgfplots does everything automatically. – student Sep 25 '12 at 8:59

Okay, here's one way of doing it. You'll need to explicitly specify a width and height for the plot, which will be taken as a "target" value for the plot. You might run into problems for plots with very large values or data ranges (if you do, edit your question to include an example and I'll try to fix it).

\documentclass{article}

\usepackage{pgfplots}

\begin{document}

\pgfmathdeclarefunction{nicetick}{1}{%
\pgfmathsetmacro\exponent{floor(log10(#1))}%
\pgfmathsetmacro\fraction{#1/(10^\exponent}%
\pgfmathparse{(10 - (\fraction<5)*5 - (\fraction<2)*3 - (\fraction<1)*1)* 10^\exponent
}
}

\makeatletter
\pgfplotsset{
y grid length/.style={
before end axis/.append code={
\pgfplotsset{
calculate/.code={
\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
\pgfmathparse{\pgfplots@data@ymax-\pgfplots@data@ymin}
\let\datarange=\pgfmathresult
\pgfmathsetmacro\numberofticks{round(\pgfkeysvalueof{/pgfplots/height}/#1)}
\pgfmathsetmacro\niceytick{nicetick( (\datarange)/ (\numberofticks))}
\pgfmathsetmacro\minytick{(floor(\pgfplots@data@ymin/\niceytick)-1) * \niceytick}
\pgfmathsetmacro\secondytick{\minytick+\niceytick}
\pgfmathsetmacro\maxytick{(round(\pgfplots@data@ymax/\niceytick)+1) * \niceytick}
\pgfmathsetmacro\yunitlength{#1/\niceytick}
\pgfkeys{/pgf/fpu/output format=float,/pgf/fpu=false}
},
calculate,
y=\yunitlength pt,
ytick={\minytick,\secondytick,...,\maxytick}
}
}
},
x grid length/.style={
before end axis/.append code={
\pgfplotsset{
calculate/.code={
\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
\pgfmathparse{\pgfplots@data@xmax-\pgfplots@data@xmin}
\let\dataxrange=\pgfmathresult
\pgfmathsetmacro\numberofticks{round(\pgfkeysvalueof{/pgfplots/width}/#1)}
\pgfmathsetmacro\nicextick{nicetick( (\dataxrange)/ (\numberofticks))}
\pgfmathsetmacro\minxtick{(floor(\pgfplots@data@xmin/\nicextick)-1) * \nicextick}
\pgfmathsetmacro\secondxtick{\minxtick+\nicextick}
\pgfmathsetmacro\maxxtick{(round(\pgfplots@data@xmax/\nicextick)+1) * \nicextick}
\pgfkeys{/pgf/fpu/output format=float,/pgf/fpu=false}
},
calculate,
x=#1/\nicextick,
xtick={\minxtick,\secondxtick,...,\maxxtick}
}
}
}
}

\begin{tikzpicture}
\begin{axis}[
height=4cm,
width=8cm,
grid,
no markers,
samples=100,
title=No fixed grid size
]
\end{axis}
\end{tikzpicture}\\[0.5cm]

\begin{tikzpicture}
\begin{axis}[
height=4cm,
width=8cm,
grid,
no markers,
samples=100,
x grid length=1cm,
y grid length=1cm,
title=Grid size 1\,cm by 1\,cm
]
\end{axis}
\end{tikzpicture}\\[0.5cm]

\begin{tikzpicture}
\begin{axis}[
height=4cm,
width=8cm,
grid,
no markers,
samples=100,
x grid length=2cm,
y grid length=2cm,
title=Grid size 2\,cm by 2\,cm
]

Thanks. That's awesome. However it doesn't play well with setting larger values for xmax. Is there any way to fix this? – student Sep 25 '12 at 17:18
@student: That's similar to the normal behaviour, though. xmin and xmax only set the visible area, but not the range over which the plot is drawn. – Jake Sep 25 '12 at 20:51