# Best practice for plots (pgfplots, gnuplot, etc.)

I am writing a fairly large article with a lot of different plots. They range from simple ones like abs(x) or x^2 to high-polynomials with their first and second derivative, and nonlinearities (sigmoid, tan, etc.). Sometimes they are also in 3 dimensions.

I am using pgfplot within tikzpicture and then gnuplot. For the easy plots, this is straightforward. However, the more complex plots (that may include non-continuity points), the gnuplot expression becomes harder and harder to understand and maintain. For some plots, I need randomly created points anyway (created once, and then fixed), which need to be "classified" according to a function.

For all plots, I have (or could create) Python scripts to output a coordinates table that would be possible to use within the pgfplot table import functionality. This may seem overkill for x^2 but is really necessary for the more complex plots. And with the higher polynomials, I don't have to do the derivates manually.

This works for plots that are points or lines in 2D but not in 3D because the number of points for the imported table exceeds LaTeX's memory (x and y have 1000 samples each, which results in 1,000,000 coordinates).

As I have the functions in Python anyway, I could also use matplotlib (or seaborn, etc.) to create pdfs with the plot. This has the disadvantage that the plots do not look like they would when drawing with LaTeX/gnuplot (different colors, styles, etc.), so I would have to maintain the styles in two different places.

Is there a best practice for this type plotting? I want one type of plot (either only gnuplot or only Python) and not a mixture of different methods.

• Matplotlib has a pgf backend. ፨ In line of principals, the typesetting being delegated to TeX, you'd get a consistent look between plots and text — that said I have not a first hand experience and consequently I cannot give you a real answer. Jul 27, 2020 at 17:31
• Currently, this is the best option. I can use TensorFlow/numpy to compute the coordinates and then use matplotlib with pgf to draw, and then input them into the document. The downside is, that the plots are not cached and rendered on every run. Jul 28, 2020 at 15:20
• I googled pgf cache and the first outcome is https://github.com/dionhaefner/pgfcache ፨ I have no idea if it it can help you but I'd have a look if I were in your shoes. Jul 28, 2020 at 20:26
• Thanks, it is only compatible with pdflatex. It doesn't look like it's maintained anymore. Jul 29, 2020 at 8:20

I went through this problem years ago. In my cases I wanted to make sure I my tikz/pgfplots

1. could be done using axes as well as windows
2. were capable of showing a graph paper background
3. were able to handle multiple graphs at the same time
4. Could handle more complicated functions

Now simple functions, such as what you'd see in a high school are easily done with template 1: I posted Tikz plot x^a*cos(ln(x)). You'll see there are many settings where the axis environment is set. The line commented out %grid = both,%grid for major ticks (every integer) and minor ticks is preventing graph paper background. After experimenting a bit I found that the sagetex package was capable of the issue you are concerned with: handling more complicated functions. The documentation is found on CTAN here; the package gives you access to a computer algebra system (CAS), called SAGE, along with Python programming. From the CAS you get more complicated functions such as erf, riemann zeta, fourier, and so on. The SAGE documentation on built in functions is here. You also get accurate calculations, the ability to compute derivatives and integrals, and the ability to choose the points you graph. Since SAGE is not part of your LaTeX distribution it needs to be installed on your computer or you need to open a free Cocalc account. The free account is the easiest way to get up and running.

After pushing the Build button in Cocalc there is a 3 step process compilation process that goes on: first LaTeX is run. Second, SAGE runs on the content it needs to. Third, LaTeX is run on the final product consisting of LaTeX plus SAGE content. In order to get through compilation without errors I've found it easiest to create a raw string in Python which will take any calculations needed (such as coordinates in a plot) and create the text that will run in LaTeX. Template 2: for 2d plotting requiring SAGE is used in many posts on this site; for example: how to plot reciprocal of Gamma function in Latex. Notice that I imported the function with from sage.functions.other import gamma1 and used that in two ways. It's first plotted as a sageplot which is showing you the plot created by SAGE. The second plot shows the result when the coordinates are pushed through pgfplots to get the second plot shown. It's similar to the first template except now I'm putting the code through a string so SAGE can do the typesetting. Since my axis environment says output += r"grid = none," there will be no graph paper. In the post Plotting implicitly in Tikz you'll see the same basic template used to plot implicitly. Note the graph paper background comes from output += r"grid = both,". In addition to these 2 templates for plotting 2d, there is template 3: for 3d plots requiring SAGE in Tikz plotting 3d. Once you're comfortable with the process you can easily use SAGE as the engine for other plots not using the templates discussed. For example the post

1. Drawing Fourier expansion using pgfplots uses SAGE knowledge of Fourier series plus a different plot setup.
2. How to plot Lebesgue singular function in Tikz? uses Python programming more in creating the function.
3. Plotting function ℝ² →ℝ with pole at (0,0) smoothly shows how SAGE can plot using the specific points you want.
4. Drawing the dragon curve mentions how to increase your buffer: You'd change the compilation to something like buf_size=1000000 pdflatex -synctex=1 -interact=nonstopmode MyFile.tex.
5. Contour plot of arbitrary R^3 function without gnuplot shows how you can embed matplotlib plots in your document.
6. Given a list of primes, how can I plot π(x)? uses the built in prime function to plot a sequence.
7. Riemann Integral on Tikz with commands shows how to create a Python function which will generate left and right Riemann integrals.
8. How to automatically ask tikz to produce the coordinates and plot the graph from adjacency matrix creates vertices and edges type graph from an adjacency matrix.
9. Obtain a table of non-uniformly-distributed random 0 and 1 draws illustrates how a numpy array could processed to create an array of randomly created ones and zeros.
10. Projective Plot of a elliptic curve showing off SAGE 3d graphics.
11. How to plot this function containing ceiling in TikZ? shows how to plot a function with numerous dicontinuities.

In summary, you can use the sagetex package along with the three templates to create 2d/3d plots with the same look and feel, regardless of how complicated there are. The use of Python keeps code simpler to read and revise and even lets you force the plotting of specific points. You can easily increase the size of the buffer to handle more data. SAGE can handle differentiation as well as integration. You can also use matplotlib and SAGE plots if you want. There are other examples posted on this site you can search for as well.

What's best practice? I don't know that has an answer to satisfy everyone. However, the sagetex package can handle the problems you have mentioned.

• What about gnuplot? I am trying to learn some external CAS to be compatible and robust with latex. So, in your opinion, what should I start with: sagetex or gnuplot?
– Diaa
Aug 1, 2020 at 19:40
• gnuplot isn't a CAS; it's a scientific plotting program. Sage, working with sagetex in my answer here can with very little code determine the transpose of a matrix and multiplication of matrices. Sage also gives you access to Python which is easy to read/understand/remember. Depending on your needs you may like gnuplot better. Combining Sage, LaTeX and Python gives you the power to do most anything.
– DJP
Aug 1, 2020 at 22:41

I had a similar problem. What I did is "externalise" the generation of the plots. You do this by including

\usepgfplotslibrary{external}
\tikzexternalize


In your preamble. You have to call Latex with the additional options: -shell-escape. This will cause the compiler to start from scratch for each tikz-picture so your compilation will no longer accumulate memory consumption. There will be an individual file for each picture and they will be nicely combined into one document as well.

This being said, 1M points is still too much. And frankly, I don't think it is necessary to have a nice quality plot. You should reduce that anyway. Play around with the number of points (You have it in Python anyway so it should not be that hard.) I try to find the limit by trial and error. You might want to create and debug the picture in a separate document in order to get the error-log.

Here I propose one example for plotting sinus and cosinus functions where I show (with comments) the methods to graph paper, grid, graduations, particular point, etc.:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[>=latex,scale=1.5]
% first option for a grid like a millimetral grahic paper (next 3 lines)
\draw[thin,brown!25] (-.5,-1.5) grid[step= 1mm] ++ (7.5,3);
\draw[semithick,brown!50]   (-.5,-1.5) grid[step= 5mm] ++  (7.5,3);
\draw[    thick,brown!75]   (-.5,-1.5) grid[step=10mm] ++  (7.5,3);

% second option for a grid in dotted gray in next line (uncomment the next line but comment the preceding 3 lines)
%\draw[dotted] (-0,-1) grid (6.5,1);

% x axis and its label
\draw[->] (-.5,0) -- (6.5,0) node[right] {$x$};

% x axis graduations in integers
\foreach \x in {1,2,...,6}
\fill[shift={(\x,0)}] circle(.5pt) node[above] {\tiny $\x$};

% x axis graduations in \pi
\foreach \x /\n in {.7854/$\frac{\pi}{4}$,1.5708/$\frac{\pi}{2}$,2.3562/$\frac34\pi$,3.1416/$\pi$,3.9270/$\frac54\pi$,4.7124/$\frac32\pi$,5.4978/$\frac74\pi$,6.2832/$2\pi$} \draw[shift={(\x,0)}] (0pt,2pt) -- (0pt,-2pt) node[below] {\tiny \n};

% y axis, its label and graduations
\draw[->] (0,-1.5) -- (0,1.5) node[below right] {$y$};
\foreach \y in {-1,1}
\draw[shift={(0,\y)}] (2pt,0pt) -- (-2pt,0pt) node[left] {\tiny $\y$};
\node[below left] at (0,0) {\tiny $0$};

% draw functions
\draw[smooth,blue,mark=none,domain=0:6.283,line width=1.5pt] plot (\x,{sin(deg(\x))});
\draw[smooth,magenta,mark=none,domain=-0:6.283,line width=1.5pt] plot (\x,{cos(deg(\x))});

% draw the functions names
\draw[] (2,-1) node[magenta,below](1) {$y=\cos x$};
\draw[] (2,1) node[blue,above](1) {$y=\sin x$};

% plot the intersections points A and B
\fill[black,shift={(3.9270,-.707)}] circle(1.5pt) node[below] {\tiny B};
\fill[black,shift={(.7854,.707)}] circle(1.5pt) node[above] {\tiny A};

% draw the exact coordinates of A and B
\draw[] (5,-.95) node[below] (3) {\tiny A$\left(\frac{\pi}{4},\frac{\sqrt2}{2}\right)$ \quad \tiny B$\left(\frac{5}{4}\pi,-\frac{\sqrt2}{2}\right)$};
\end{tikzpicture}

\end{document}


And here the result: 